*/
#include <dlfcn.h>
-#include <pthread.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
struct list list;
enum log_type type;
multilog_fn log;
- void *data;
+ struct log_data *data;
};
/* FIXME: probably shouldn't do it this way, but... */
static LIST_INIT(logs);
-/* Mutext for logs accesses. */
-static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
-static int (*lock_fn)(pthread_mutex_t *) = NULL;
-static int (*unlock_fn)(pthread_mutex_t *) = NULL;
+/* locking for log accesss */
+static void* (*init_lock_fn)(void) = NULL;
+static int (*lock_fn)(void *) = NULL;
+static int (*unlock_fn)(void *) = NULL;
+static void (*destroy_lock_fn)(void *) = NULL;
+void *lock_dlh = NULL;
+void *lock_handle = NULL;
-static void lock_mutex(void)
+static void *init_lock(void)
+{
+ return init_lock_fn ? init_lock_fn() : NULL;
+}
+
+static int lock_list(void *handle)
{
if (lock_fn)
- (*lock_fn)(&mutex);
+ return !(*lock_fn)(handle);
+ return 0;
}
-static void unlock_mutex(void)
+static int unlock_list(void *handle)
{
if (unlock_fn)
- (*unlock_fn)(&mutex);
+ return !(*unlock_fn)(handle);
+ return 0;
+}
+
+static void destroy_lock(void *handle)
+{
+ if(destroy_lock_fn)
+ (*destroy_lock_fn)(handle);
+}
+
+static void *init_nop_lock(void)
+{
+ return NULL;
}
-static int load_pthread_syms(struct log_data *data)
+static int nop_lock(void *handle)
+{
+ return 0;
+}
+
+static int nop_unlock(void *handle)
+{
+ return 0;
+}
+
+static void destroy_nop_lock(void *handle)
+{
+ return;
+}
+
+static int load_lock_syms(struct log_data *data)
{
void *dlh;
- if (!(dlh = dlopen("libpthread.so", RTLD_NOW))) {
- fprintf(stderr, "%s\n", dlerror());
- return 0;
+ if (!(dlh = dlopen("libmultilog_pthread_lock.so", RTLD_NOW))) {
+ //fprintf(stderr, "%s\n", dlerror());
+ if(strstr(dlerror(), "undefined symbol: pthread")) {
+ fprintf(stderr, "pthread library not linked in - using nop locking\n");
+ init_lock_fn = init_nop_lock;
+ lock_fn = nop_lock;
+ unlock_fn = nop_unlock;
+ destroy_lock_fn = destroy_nop_lock;
+ return 1;
+ }
+ else
+ return 0;
}
- data->info.threaded_syslog.pthread_dlh = dlh;
+ lock_dlh = dlh;
- return (lock_fn = dlsym(dlh, "pthread_mutex_lock")) &&
- (unlock_fn = dlsym(dlh, "pthread_mutex_unlock"));
+ return ((init_lock_fn = dlsym(dlh, "init_locking")) &&
+ (lock_fn = dlsym(dlh, "lock_fn")) &&
+ (unlock_fn = dlsym(dlh, "unlock_fn")) &&
+ (destroy_lock_fn = dlsym(dlh, "destroy_locking")));
}
log_fxn = dlsym(logdata->info.threaded_syslog.dlh, "write_to_buf");
start_syslog = dlsym(logdata->info.threaded_syslog.dlh, "start_syslog_thread");
- if (!log_fxn || !start_syslog ||
- !load_pthread_syms(logdata)) {
+ if (!log_fxn || !start_syslog) {
dlclose(logdata->info.threaded_syslog.dlh);
return 0;
}
{
struct log_list *logl, *ll;
+ /* FIXME: Potential race here */
+ /* attempt to load locking protocol */
+ if(!init_lock_fn) {
+ if(!load_lock_syms(data)) {
+ fprintf(stderr, "Unalbe to load locking\n");
+ return 0;
+ }
+ lock_handle = init_lock();
+ }
/*
* Preallocate because we don't want to sleep holding a lock.
*/
* If the type has already been registered,
* it doesn't need to be registered again.
*/
- lock_mutex();
+ lock_list(lock_handle);
list_iterate_items(ll, &logs) {
if (ll->type == type) {
- unlock_mutex();
+ unlock_list(lock_handle);
free(logl);
-
return 1;
}
}
-
logl->type = type;
logl->data = data;
+ list_add(&logs, &logl->list);
+ unlock_list(lock_handle);
switch (type) {
case standard:
break;
case threaded_syslog:
if (!start_threaded_syslog(logl, data)) {
- unlock_mutex();
+ lock_list(lock_handle);
+ list_del(&logl->list);
+ unlock_list(lock_handle);
free(logl);
return 0;
}
break;
}
- list_add(&logs, &logl->list);
- unlock_mutex();
-
return 1;
}
list_init(&ll);
/* First step: move elements to temporary local list safely. */
- lock_mutex();
+ lock_list(lock_handle);
list_iterate_safe(tmp, next, &logs) {
list_del(tmp);
list_add(&ll, tmp);
}
- unlock_mutex();
+ unlock_list(lock_handle);
/* Second step: delete them. */
list_iterate_safe(tmp, next, &ll) {
logl = list_item(tmp, struct log_list);
+ if(logl->type == threaded_syslog) {
+ if(logl->data->info.threaded_syslog.dlh) {
+ int (*stop_syslog) (struct log_data *log);
+ stop_syslog = dlsym(logl->data->info.threaded_syslog.dlh,
+ "stop_syslog_thread");
+ stop_syslog(logl->data);
+ dlclose(logl->data->info.threaded_syslog.dlh);
+ }
+ }
+
if (logl->data)
free(logl->data);
list_del(tmp);
}
+ /* FIXME: Not sure the destroy_lock call is really necessary */
+ destroy_lock(lock_handle);
+ dlclose(lock_dlh);
+
}
/* FIXME: Might want to have this return an error if we can't find the type */
struct log_list *logl, *ll = NULL;
/* First delete type from list safely. */
- lock_mutex();
+ lock_list(lock_handle);
list_iterate_safe(tmp, next, &logs) {
logl = list_item(tmp, struct log_list);
}
}
- unlock_mutex();
+ unlock_list(lock_handle);
if (ll) {
if (ll->type == threaded_syslog) {
stop_syslog(data);
dlclose(data->info.threaded_syslog.dlh);
- dlclose(data->info.threaded_syslog.pthread_dlh);
}
free(ll);
* FIXME: Should we present an error if
* we can't find a suitable target?
*/
- lock_mutex();
+ lock_list(lock_handle);
list_iterate_items(logl, &logs) {
if (logl->type == custom && logl->log == nop_log)
logl->log = fn;
}
- unlock_mutex();
+ unlock_list(lock_handle);
}
vsnprintf(buf, 4096, format, args);
va_end(args);
- lock_mutex();
+ lock_list(lock_handle);
list_iterate_items(logl, &logs)
logl->log(logl->data, priority, file, line, buf);
- unlock_mutex();
+ unlock_list(lock_handle);
}
--- /dev/null
+#
+# Copyright (C) 2005 Red Hat, Inc. All rights reserved.
+#
+# This file is part of the device-mapper userspace tools.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU Lesser General Public License v.2.1.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+interface = @interface@
+
+SOURCES = pthread_lock.c
+
+LIB_STATIC = libmultilog_pthread_lock.a
+
+ifeq ("@LIB_SUFFIX@","dylib")
+ LIB_SHARED = libmultilog_pthread_lock.dylib
+else
+ LIB_SHARED = libmultilog_pthread_lock.so
+endif
+
+LDFLAGS += -ldl -ldevmapper -lpthread -L..
+
+include ../../make.tmpl
+
+.PHONY: install_dynamic install_static
+
+INSTALL_TYPE = install_dynamic
+
+ifeq ("@STATIC_LINK@", "yes")
+ INSTALL_TYPE += install_static
+endif
+
+install: $(INSTALL_TYPE)
+
+install_dynamic: libmultilog_pthread_lock.$(LIB_SUFFIX)
+ $(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
+ $(libdir)/libmultilog_pthread_lock.$(LIB_SUFFIX).$(LIB_VERSION)
+ $(LN_S) -f libmultilog_pthread_lock.$(LIB_SUFFIX).$(LIB_VERSION) \
+ $(libdir)/libmultilog_pthread_lock.$(LIB_SUFFIX)
+
+install_static: libmultilog_pthread_lock.a
+ $(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
+ $(libdir)/libmultilog_pthread_lock.a.$(LIB_VERSION)
+ $(LN_S) -f libmultilog_pthread_lock.a.$(LIB_VERSION) $(libdir)/libmultilog_pthread_lock.a
--- /dev/null
+/*
+ * Copyright (C) 2005 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of the device-mapper userspace tools.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <pthread.h>
+#include <stdlib.h>
+#include <string.h>
+#include "pthread_lock.h"
+
+void *nop(void *data)
+{
+ pthread_exit(NULL);
+}
+
+void *init_locking(void)
+{
+ pthread_t thread;
+ pthread_mutex_t *mutex;
+ if(!(mutex = malloc(sizeof(*mutex))))
+ return NULL;
+ if(!memset(mutex, 0, sizeof(*mutex)))
+ return NULL;
+ /*
+ * Hack to ensure DSO loading fails if not linked with
+ * libpthread
+ */
+ pthread_create(&thread, NULL, nop, NULL);
+
+ return mutex;
+}
+
+int lock_fn(void *handle)
+{
+ pthread_mutex_t *mutex = (pthread_mutex_t *)handle;
+ if(mutex)
+ return pthread_mutex_lock(mutex);
+ else
+ return 0;
+}
+
+
+int unlock_fn(void *handle)
+{
+ pthread_mutex_t *mutex = (pthread_mutex_t *)handle;
+ if(mutex)
+ return pthread_mutex_unlock(mutex);
+ else
+ return 0;
+}
+
+
+void destroy_locking(void *handle)
+{
+ pthread_mutex_t *mutex = (pthread_mutex_t *)handle;
+ if(mutex)
+ free(mutex);
+}
+