multilog_add_type()/multilog_del_type cycles correctly.
o fixed segfault in multilog_add_type()
o fixed test-multilog.c
o cleaned up libmultilog (list macros, indentation, braces, comments)
}
out:
+ multilog_del_type(standard, ldata);
+
if (device_arg)
free(device_arg);
#include "dmeventd.h"
#include "libmultilog.h"
-
#include <dlfcn.h>
#include <errno.h>
#include <fcntl.h>
struct thread_status *ret = (typeof(ret)) dbg_malloc(sizeof(*ret));
if (ret) {
- memset(ret, 0, sizeof(*ret));
- if ((ret->device_path = dbg_strdup(data->device_path))) {
- ret->dso_data = dso_data;
- ret->events = data->events.field;
- } else {
+ if (!memset(ret, 0, sizeof(*ret)) ||
+ !(ret->device_path = dbg_strdup(data->device_path))) {
dbg_free(ret);
ret = NULL;
+ } else {
+ ret->dso_data = dso_data;
+ ret->events = data->events.field;
}
}
struct dso_data *ret = (typeof(ret)) dbg_malloc(sizeof(*ret));
if (ret) {
- memset(ret, 0, sizeof(*ret));
- if (!(ret->dso_name = dbg_strdup(data->dso_name))) {
+ if (!memset(ret, 0, sizeof(*ret)) ||
+ !(ret->dso_name = dbg_strdup(data->dso_name))) {
dbg_free(ret);
ret = NULL;
}
dbg_free(data);
}
+/* FIXME: Factor out. */
+static char *dm_basename(char *str)
+{
+ char *p = strrchr(str, '/');
+
+ return p ? p + 1 : str;
+}
+
/*
* Fetch a string off src and duplicate it into *ptr.
* Pay attention to 0 lenght strings.
if ((len = strlen(params)) &&
params[len - 1] == 'F') {
*/
- if((len = strlen(params))){
+ if (params && (len = strlen(params))) {
thread->current_events |= DEVICE_ERROR;
return 1;
}
if (!(dmt = dm_task_create(DM_DEVICE_WAITEVENT)))
return 0;
- if ((ret = dm_task_set_name(dmt, basename(thread->device_path))) &&
+ if ((ret = dm_task_set_name(dmt, dm_basename(thread->device_path))) &&
(ret = dm_task_set_event_nr(dmt, thread->event_nr)) &&
(ret = dm_task_run(dmt))) {
do {
if ((ret = error_detected(thread, params)))
break;
} while(next);
- dm_task_get_info(dmt, &info);
- thread->event_nr = info.event_nr;
+
+ if ((ret = dm_task_get_info(dmt, &info)))
+ thread->event_nr = info.event_nr;
}
dm_task_destroy(dmt);
}
/* Initialize a fifos structure with path names. */
-static void init_fifos(struct fifos *fifos)
+static int init_fifos(struct fifos *fifos)
{
- memset(fifos, 0, sizeof(*fifos));
- fifos->client_path = FIFO_CLIENT;
- fifos->server_path = FIFO_SERVER;
+ if (memset(fifos, 0, sizeof(*fifos))) {
+ fifos->client_path = FIFO_CLIENT;
+ fifos->server_path = FIFO_SERVER;
+
+ return 1;
+ }
+
+ return 0;
}
/* Open fifos used for client communication. */
/* FIXME: better error handling */
/* Read the request from the client. */
- memset(&msg, 0, sizeof(msg));
- if (!client_read(fifos, &msg)) {
+ if (!memset(&msg, 0, sizeof(msg)) ||
+ !client_read(fifos, &msg)) {
stack;
return;
}
int ret;
struct fifos fifos;
struct log_data *tsdata = malloc(sizeof(*tsdata));
+
if(!tsdata)
exit(-ENOMEM);
+
if(!memset(tsdata, 0, sizeof(*tsdata)))
exit(-ENOMEM);
tsdata->verbose_level = _LOG_DEBUG;
multilog_add_type(threaded_syslog, tsdata);
+ if (!init_fifos(&fifos))
+ exit (-ENOMEM);
-
- init_fifos(&fifos);
pthread_mutex_init(&mutex, NULL);
if (mlockall(MCL_FUTURE) == -1)
int initialized:1;
};
-/* Need a circular buffer to hold the messages - this will have to be
- * global so all threads can see it */
+/*
+ * Need a circular buffer to hold the messages - this will
+ * have to be global so all threads can see it.
+ */
static struct circ_buf cbuf = {
.mutex = PTHREAD_MUTEX_INITIALIZER,
.cond = PTHREAD_COND_INITIALIZER,
static int will_overrun(int read_pos, int write_pos,
int first_len, int second_len) {
- if(((read_pos > write_pos) &&
- (write_pos + first_len >= read_pos)) ||
- ((read_pos < write_pos) &&
- (second_len >= read_pos)))
- return 1;
- else
- return 0;
+ return (((read_pos > write_pos) &&
+ (write_pos + first_len >= read_pos)) ||
+ ((read_pos < write_pos) &&
+ (second_len >= read_pos)));
}
-/* Messages are encoded in the buffer with the following format:
- priority:file:line:msg
-*/
+/*
+ * Messages are encoded in the buffer with the following format:
+ *
+ * priority:file:line:msg
+ */
void write_to_buf(void *data, int priority, const char *file, int line,
const char *string)
{
written_len = snprintf(curpos, CBUFSIZE-1, ":%s:%d:",
file, line);
- /* file, func, line were too long for the buffer,
- so leave them blank */
- if(written_len >= (CBUFSIZE-1)) {
+
+ /*
+ * file, func, line were too long for the buffer,
+ * so leave them blank.
+ */
+ if (written_len >= (CBUFSIZE-1)) {
sprintf(curpos, ":::");
written_len = 3;
}
+
curpos += written_len;
- /* write message to circular buffer - what kind of delimiter do we
- * want? Is NULL ok? */
- strncpy(curpos, string, CBUFSIZE-written_len);
+ /*
+ * write message to circular buffer - what kind of delimiter
+ * do we want? Is NULL ok?
+ */
+ strncpy(curpos, string, CBUFSIZE - written_len);
/* FIXME: should we warn somehow if the buffer was truncated? */
buf[CBUFSIZE-1] = '\0';
- /* FIXME - if the message is too long for the buffer, should
- * we retry without the filename, function and line number? */
-
+ /*
+ * FIXME - if the message is too long for the buffer, should
+ * we retry without the filename, function and line number?
+ */
buf_len = strlen(buf) + 1;
pthread_mutex_lock(&cbuf.mutex);
/* Need to split the write into parts */
- if((cbuf.write_pos + buf_len) >= CBUFSIZE) {
+ if ((cbuf.write_pos + buf_len) >= CBUFSIZE) {
first_len = CBUFSIZE - (cbuf.write_pos);
second_len = buf_len - first_len;
+
/* Protect from overrun */
- if(!will_overrun(cbuf.read_pos, cbuf.write_pos,
- first_len, second_len)) {
+ if (!will_overrun(cbuf.read_pos, cbuf.write_pos,
+ first_len, second_len)) {
strncpy(&cbuf.buf[cbuf.write_pos], buf, first_len);
strncpy(&cbuf.buf[0], buf + first_len, second_len);
cbuf.write_pos = second_len;
ret = 0;
} else {
/* Protect from overrun */
- if(!will_overrun(cbuf.read_pos, cbuf.write_pos,
- buf_len, -1)) {
+ if (!will_overrun(cbuf.read_pos, cbuf.write_pos, buf_len, -1)) {
strncpy(&cbuf.buf[cbuf.write_pos], buf, buf_len);
cbuf.write_pos += buf_len;
ret = 1;
ret = 0;
}
- /* We don't need to signal the syslog thread when it's writing
- * to syslog */
- if(cbuf.should_sig)
+ /*
+ * We don't need to signal the syslog thread
+ * when it's writing to syslog.
+ */
+ if (cbuf.should_sig)
pthread_cond_signal(&cbuf.cond);
pthread_mutex_unlock(&cbuf.mutex);
-
- return;
-
}
-
static int read_from_buf(int *priority, char *file, int *line,
char *msg, int len)
{
char tmpbuf[CBUFSIZE] = {0};
char *curpos = &cbuf.buf[cbuf.read_pos];
- /* Pull the entire message into a temporary buffer first to
- * handle wraparound cleanly */
+ /*
+ * Pull the entire message into a temporary
+ * buffer first to handle wraparound cleanly
+ */
first_len = CBUFSIZE - cbuf.read_pos;
strncpy(tmpbuf, &cbuf.buf[cbuf.read_pos], first_len);
- if(tmpbuf[first_len - 1] != '\0') {
+ if (tmpbuf[first_len - 1] != '\0') {
/* FIXME: Make sure we're null terminated */
strncpy(tmpbuf+first_len, &cbuf.buf[0], cbuf.read_pos);
cbuf.read_pos = strlen(&cbuf.buf[0]) + 1;
- } else {
+ } else
cbuf.read_pos += strlen(tmpbuf) + 1;
- }
/* Parse the message for various fields */
curpos = tmpbuf;
- if(!(pos = strchr(curpos, ':'))) {
+ if (!(pos = strchr(curpos, ':')))
return 0;
- }
+
pbuf[0] = curpos[0];
pbuf[1] = '\0';
sscanf(pbuf, "%d", priority);
curpos = pos;
- if(!(pos = strchr(curpos+1, ':'))) {
+ if (!(pos = strchr(curpos+1, ':')))
return 0;
- }
- if(pos != curpos + 1) {
+
+ if (pos != curpos + 1) {
strncpy(file, curpos + 1, MAX_FILELEN - 1);
file[pos - (curpos + 1)] = '\0';
}
+
curpos = pos;
- if(!(pos = strchr(curpos+1, ':'))) {
+ if (!(pos = strchr(curpos+1, ':')))
return 0;
- }
- if(pos != curpos + 1) {
+
+ if (pos != curpos + 1) {
strncpy(pbuf, curpos + 1, MIN(MAX_LINELEN, pos - (curpos + 1)));
sscanf(pbuf, "%d", line);
} else
*line = -1;
- curpos = pos + 1;
+ curpos = pos + 1;
strncpy(msg, curpos, MIN(len, (CBUFSIZE - (curpos - tmpbuf))));
//cbuf.read_pos += strlen(msg) + (curpos - tmpbuf) + 1;
char mybuf[CBUFSIZE] = {0};
while(cbuf.write_pos != cbuf.read_pos) {
- /*call read_from_buf, unlock mutex,
- * and write to syslog */
- read_from_buf(&priority, file, &line,
- mybuf, CBUFSIZE);
+ /* Call read_from_buf, unlock mutex, and write to syslog. */
+ read_from_buf(&priority, file, &line, mybuf, CBUFSIZE);
- /* Unlock the mutex before writing to syslog
+ /*
+ * Unlock the mutex before writing to syslog
* so we don't block the writer threads - but
- * then how to we handle
- * pthread_cond_signal? */
+ * then how to we handle pthread_cond_signal?
+ */
pthread_mutex_unlock(&cbuf.mutex);
syslog(priority, "%s", mybuf);
pthread_mutex_lock(&cbuf.mutex);
pthread_mutex_unlock(&cbuf.mutex);
}
-/* handle logging to syslog through circular buffer so that syslog
- * blocking doesn't hold anyone up */
+/*
+ * Handle logging to syslog through circular buffer so that syslog
+ * blocking doesn't hold anyone up.
+ */
static void *process_syslog(void *arg)
{
char mybuf[CBUFSIZE] = {0};
char file[256];
int line;
- /* We can lock this because cbuf is initialized at creation
- time */
+ /* We can lock this because cbuf is initialized at creation time */
pthread_mutex_lock(&cbuf.mutex);
/* FIXME: Should I return an error code or something here? */
- /* Prevent multiple process_syslog threads from starting */
- if(cbuf.initialized) {
+ /* Prevent multiple process_syslog threads from starting. */
+ if (cbuf.initialized)
pthread_exit(NULL);
- }
cbuf.initialized = 1;
-
pthread_cleanup_push(finish_processing, NULL);
- /* FIXME: The program name needs to be variable */
+
+ /* FIXME: The program name needs to be variable. */
openlog("dmeventd", LOG_NDELAY | LOG_PID, LOG_DAEMON);
while (1) {
/* check write_pos & read_pos */
- if(cbuf.write_pos != cbuf.read_pos) {
- /*call read_from_buf, unlock mutex,
- * and write to syslog */
- read_from_buf(&priority, file, &line,
- mybuf, CBUFSIZE);
-
- /* Unlock the mutex before writing to syslog
- * so we don't block the writer threads */
+ if (cbuf.write_pos != cbuf.read_pos) {
+ /*
+ * Call read_from_buf, unlock mutex,
+ * and write to syslog.
+ */
+ read_from_buf(&priority, file, &line, mybuf, CBUFSIZE);
+
+ /*
+ * Unlock the mutex before writing to syslog
+ * so we don't block the writer threads.
+ */
pthread_mutex_unlock(&cbuf.mutex);
-
syslog(priority, "%s", mybuf);
-
pthread_mutex_lock(&cbuf.mutex);
} else {
- /* set the should_sig var before waiting so
+ /*
+ * Set the should_sig var before waiting so
* the threads using the log know to signal it
- * to wake up after adding to the log */
+ * to wake up after adding to the log.
+ */
cbuf.should_sig = 1;
pthread_cond_wait(&cbuf.cond, &cbuf.mutex);
cbuf.should_sig = 0;
}
}
+
closelog();
pthread_cleanup_pop(0);
+
return NULL;
}
-
int start_syslog_thread(pthread_t *thread, long usecs)
{
struct timeval ts = {0, usecs};
pthread_create(thread, NULL, process_syslog, NULL);
-
select(0, NULL, NULL, NULL, &ts);
- /* Not grabbing the mutex before I check this - mainly
+
+ /*
+ * Not grabbing the mutex before I check this - mainly
* because it better be atomic - either 0 or 1, and if
* it changes from 0 -> 1 while i'm reading it, I
- * don't really care */
- if(cbuf.initialized)
- return 1;
-
- return 0;
+ * don't really care.
+ */
+ return cbuf.initialized ? 1 : 0;
}
-
int stop_syslog_thread(struct log_data *data)
{
pthread_cancel(data->info.threaded_syslog.thread);
pthread_join(data->info.threaded_syslog.thread, NULL);
+
return 1;
}
#include <unistd.h>
+/* FIXME: add locking while updating logs registry. */
+
struct log_list {
struct list list;
enum log_type type;
{
return;
}
+
static void standard_log(void *data, int priority, const char *file, int line,
const char *string)
{
struct log_data *ldata = (struct log_data *) data;
- char locn[4096];
+ /* FIXME: stack allocation of large buffer. */
+ char locn[512];
if (ldata->verbose_level > _LOG_DEBUG)
snprintf(locn, sizeof(locn), "#%s:%d ", file, line);
else
locn[0] = '\0';
-
switch (ldata->verbose_level) {
case _LOG_DEBUG:
if (!strcmp("<backtrace>", string) &&
ldata->verbose_level <= _LOG_DEBUG)
break;
- if (ldata->verbose_level >= _LOG_DEBUG) {
- fprintf(stderr, "%s%s", locn, string);
- fputc('\n', stderr);
- }
+
+ if (ldata->verbose_level >= _LOG_DEBUG)
+ fprintf(stderr, "%s%s\n", locn, string);
+
break;
case _LOG_INFO:
- if (ldata->verbose_level >= _LOG_INFO) {
- fprintf(stderr, "%s%s", locn, string);
- fputc('\n', stderr);
- }
+ if (ldata->verbose_level >= _LOG_INFO)
+ fprintf(stderr, "%s%s\n", locn, string);
+
break;
case _LOG_NOTICE:
- if (ldata->verbose_level >= _LOG_NOTICE) {
- fprintf(stderr, "%s%s", locn, string);
- fputc('\n', stderr);
- }
+ if (ldata->verbose_level >= _LOG_NOTICE)
+ fprintf(stderr, "%s%s\n", locn, string);
+
break;
case _LOG_WARN:
- if (ldata->verbose_level >= _LOG_WARN) {
- printf("%s", string);
- putchar('\n');
- }
+ if (ldata->verbose_level >= _LOG_WARN)
+ printf("%s\n", string);
+
break;
case _LOG_ERR:
- if (ldata->verbose_level >= _LOG_ERR) {
- fprintf(stderr, "%s%s", locn, string);
- fputc('\n', stderr);
- }
+ if (ldata->verbose_level >= _LOG_ERR)
+ fprintf(stderr, "%s%s\n", locn, string);
+
break;
case _LOG_FATAL:
default:
- if (ldata->verbose_level >= _LOG_FATAL) {
- fprintf(stderr, "%s%s", locn, string);
- fputc('\n', stderr);
- }
+ if (ldata->verbose_level >= _LOG_FATAL)
+ fprintf(stderr, "%s%s\n", locn, string);
+
break;
};
}
-static int start_threaded_syslog(struct log_list *logl, struct log_data *logdata)
+static int start_threaded_syslog(struct log_list *logl,
+ struct log_data *logdata)
{
+ void (*log_fxn) (void *data, int priority, const char *file, int line,
+ const char *string);
+ int (*start_syslog) (pthread_t *t, long usecs);
- int i;
-
- if(!(logdata->info.threaded_syslog.dlh = dlopen("libmultilog_async.so", RTLD_NOW))) {
+ if (!(logdata->info.threaded_syslog.dlh = dlopen("libmultilog_async.so", RTLD_NOW))) {
fprintf(stderr, "%s\n", dlerror());
return 0;
}
- void (*log_fxn) (void *data, int priority, const char *file, int line,
- const char *string);
- int (*start_syslog) (pthread_t *t, long usecs);
-
log_fxn = dlsym(logdata->info.threaded_syslog.dlh, "write_to_buf");
start_syslog = dlsym(logdata->info.threaded_syslog.dlh, "start_syslog_thread");
/* FIXME: the timeout here probably can be tweaked */
/* FIXME: Probably want to do something if this fails */
- if(start_syslog(&(logdata->info.threaded_syslog.thread), 100000))
+ if (start_syslog(&(logdata->info.threaded_syslog.thread), 100000))
logl->log = log_fxn;
- if(!logl->log)
- return 0;
-
- return 1;
-
+ return logl->log ? 1 : 0;
}
-/* FIXME: Can currently add multiple logging types */
+/* FIXME: Can currently add multiple logging types. */
int multilog_add_type(enum log_type type, struct log_data *data)
{
struct log_list *logl;
- struct list *tmp;
- if(!(logl = malloc(sizeof(*logl))))
- return 0;
- if(!(memset(logl, 0, sizeof(*logl))))
- return 0;
-
- /* If the type has already been registered, it doesn't need to
- * be registered again */
- list_iterate(tmp, &logs) {
- logl = list_item(tmp, struct log_list);
- if(logl->type == type)
+ /*
+ * If the type has already been registered,
+ * it doesn't need to be registered again.
+ */
+ list_iterate_items(logl, &logs) {
+ if (logl->type == type)
return 1;
}
- list_init(&logl->list);
+ if (!(logl = malloc(sizeof(*logl))) ||
+ !(memset(logl, 0, sizeof(*logl))))
+ return 0;
+
+ list_init(&logl->list); /* Superfluous but safe ;) */
logl->type = type;
logl->data = data;
- switch(type) {
+ switch (type) {
case standard:
logl->log = standard_log;
break;
logl->log = nop_log;
break;
case threaded_syslog:
- if(!start_threaded_syslog(logl, data)) {
+ if (!start_threaded_syslog(logl, data))
return 0;
- }
+
break;
case custom:
/* Caller should use multilog_custom to set their
}
list_add(&logs, &logl->list);
+
return 1;
}
{
struct list *tmp, *next;
struct log_list *logl;
+
list_iterate_safe(tmp, next, &logs) {
logl = list_item(tmp, struct log_list);
- if(logl->data) {
+ if (logl->data)
free(logl->data);
- }
+
list_del(tmp);
}
}
list_iterate_safe(tmp, next, &logs) {
logl = list_item(tmp, struct log_list);
- if(logl->type == type) {
- if(logl->type == threaded_syslog) {
+
+ if (logl->type == type) {
+ if (logl->type == threaded_syslog) {
int (*stop_syslog) (struct log_data *log);
- stop_syslog = dlsym(data->info.threaded_syslog.dlh,
- "stop_syslog_thread");
- stop_syslog(data);
+
+ if ((stop_syslog = dlsym(data->info.threaded_syslog.dlh, "stop_syslog_thread")))
+ stop_syslog(data);
}
+
list_del(tmp);
+ free(logl);
break;
}
}
void multilog_custom(multilog_fn fn)
{
- struct list *tmp;
struct log_list *logl;
- /* FIXME: Should we present an error if we can't find a
- * suitable target? */
- list_iterate(tmp, &logs) {
- logl = list_item(tmp, struct log_list);
- if(logl->type == custom && logl->log == nop_log)
+
+ /*
+ * FIXME: Should we present an error if
+ * we can't find a suitable target?
+ */
+ list_iterate_items(logl, &logs) {
+ if (logl->type == custom && logl->log == nop_log)
logl->log = fn;
}
}
void multilog(int priority, const char *file, int line, const char *format, ...)
{
- struct list *tmp;
- struct log_list *logl;
+ /* FIXME: stack allocation of large buffer. */
char buf[4096];
+ struct log_list *logl;
va_list args;
/* FIXME: shove everything into a single string */
va_start(args, format);
-
vsnprintf(buf, 4096, format, args);
-
va_end(args);
- list_iterate(tmp, &logs) {
- logl = list_item(tmp, struct log_list);
+ list_iterate_items(logl, &logs)
logl->log(logl->data, priority, file, line, buf);
- }
-
}
#define _LOG_FATAL 2
-
struct file_log {
const char *filename;
};
typedef void (*multilog_fn) (void *data, int level, const char *file, int line,
const char *f);
-void multilog(int level, const char *file, int line, const char *f, ...)
- __attribute__ ((format(printf, 4, 5)));
+void multilog(int priority, const char *file, int line, const char *f, ...)
+ __attribute__ ((format(printf, 4, 5)));
+
/*
* The library user may wish to register their own
* logging function, by default errors go to stderr.
* Use dm_log_init(NULL) to restore the default log fn.
*/
-
-
int multilog_add_type(enum log_type type, struct log_data *data);
void multilog_clear_logging(void);
void multilog_del_type(enum log_type type, struct log_data *data);
void multilog_custom(multilog_fn fn);
void multilog_init_verbose(int level);
-
#undef plog
#undef log_error
#undef log_print
#include <stdio.h>
-
+#include <stdlib.h>
#include <syslog.h>
#include <unistd.h>
#include "libmultilog.h"
int main(int argc, char **argv)
{
int i;
- struct threaded_syslog_log sl_logdata;
+ struct log_data logdata;
- sl_logdata.verbose_level = 4;
+ logdata.verbose_level = 4;
- if(!multilog_add_type(threaded_syslog, &sl_logdata)) {
+ if (!multilog_add_type(threaded_syslog, &logdata))
fprintf(stderr, "Unable to add threaded syslog logging\n");
- }
- multilog_add_type(standard, NULL);
- for( i = 0; i < 100; i++) {
- log_err("Testing really long strings so that we can fill the buffer up and show skips %d", i);
- if(i == 5) {
+ multilog_add_type(standard, &logdata);
+
+ for (i = 0; i < 100; i++) {
+ log_err("Testing really long strings so that we can "
+ "fill the buffer up and show skips %d", i);
+
+ if (i == 5)
multilog_del_type(standard, NULL);
- }
}
log_debug("Testing debug");
-
log_err("Test of errors2");
sleep(2);
log_err("Test of errors3");
log_err("Test of errors4");
- multilog_add_type(standard, NULL);
+ /*
+ * FIXME: locking on libmultilog bytes here, because the
+ * threaded log is still active.
+ */
+ // multilog_add_type(standard, NULL);
log_err("Test of errors5");
log_err("Test of errors6");
- multilog_del_type(threaded_syslog, &sl_logdata);
+ multilog_del_type(threaded_syslog, &logdata);
- return 0;
+ exit(EXIT_SUCCESS);
}