From: AJ Lewis Date: Wed, 4 May 2005 17:55:12 +0000 (+0000) Subject: o Added a lib to handle locking - the multilog lib attempts to load it, X-Git-Tag: v1_01_02~13 X-Git-Url: https://sourceware.org/git/?a=commitdiff_plain;h=c5af50a787755eeac55d3e6ae2016d309a24a5d2;p=dm.git o Added a lib to handle locking - the multilog lib attempts to load it, and if it fails because the binary wasn't compiled with pthread support it just uses NOP locking. If it fails for any other reason, it fails adding locking. o added libmultilog_pthread_lock library that just does pthread mutex locking --- diff --git a/configure b/configure index daa7a98..ae6c609 100755 --- a/configure +++ b/configure @@ -4979,7 +4979,7 @@ fi ################################################################################ -ac_config_files="$ac_config_files Makefile make.tmpl include/Makefile dmeventd/Makefile dmsetup/Makefile lib/Makefile lib/event/Makefile lib/libdm-common.h kernel/Makefile man/Makefile multilog/Makefile multilog/async/Makefile multilog/tests/Makefile po/Makefile" +ac_config_files="$ac_config_files Makefile make.tmpl include/Makefile dmeventd/Makefile dmsetup/Makefile lib/Makefile lib/event/Makefile lib/libdm-common.h kernel/Makefile man/Makefile multilog/Makefile multilog/async/Makefile multilog/pthread_lock/Makefile multilog/tests/Makefile po/Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure @@ -5489,6 +5489,7 @@ do "man/Makefile" ) CONFIG_FILES="$CONFIG_FILES man/Makefile" ;; "multilog/Makefile" ) CONFIG_FILES="$CONFIG_FILES multilog/Makefile" ;; "multilog/async/Makefile" ) CONFIG_FILES="$CONFIG_FILES multilog/async/Makefile" ;; + "multilog/pthread_lock/Makefile" ) CONFIG_FILES="$CONFIG_FILES multilog/pthread_lock/Makefile" ;; "multilog/tests/Makefile" ) CONFIG_FILES="$CONFIG_FILES multilog/tests/Makefile" ;; "po/Makefile" ) CONFIG_FILES="$CONFIG_FILES po/Makefile" ;; *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 diff --git a/configure.in b/configure.in index 404a00d..d8d6415 100644 --- a/configure.in +++ b/configure.in @@ -364,6 +364,7 @@ kernel/Makefile \ man/Makefile \ multilog/Makefile \ multilog/async/Makefile \ +multilog/pthread_lock/Makefile \ multilog/tests/Makefile \ po/Makefile \ ) diff --git a/multilog/Makefile.in b/multilog/Makefile.in index 7ecaefb..bfa65c3 100644 --- a/multilog/Makefile.in +++ b/multilog/Makefile.in @@ -16,7 +16,7 @@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ interface = @interface@ -SUBDIRS += async +SUBDIRS += async pthread_lock SOURCES = libmultilog.c diff --git a/multilog/libmultilog.c b/multilog/libmultilog.c index 3302d81..dd0c970 100644 --- a/multilog/libmultilog.c +++ b/multilog/libmultilog.c @@ -13,7 +13,6 @@ */ #include -#include #include #include #include @@ -33,42 +32,89 @@ struct log_list { 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"))); } @@ -142,8 +188,7 @@ static int start_threaded_syslog(struct log_list *logl, 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; } @@ -161,6 +206,15 @@ int multilog_add_type(enum log_type type, struct log_data *data) { 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. */ @@ -172,19 +226,19 @@ int multilog_add_type(enum log_type type, struct log_data *data) * 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: @@ -200,7 +254,9 @@ int multilog_add_type(enum log_type type, struct log_data *data) 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; } @@ -213,9 +269,6 @@ int multilog_add_type(enum log_type type, struct log_data *data) break; } - list_add(&logs, &logl->list); - unlock_mutex(); - return 1; } @@ -230,24 +283,38 @@ void multilog_clear_logging(void) 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 */ @@ -257,7 +324,7 @@ void multilog_del_type(enum log_type type, struct log_data *data) 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); @@ -269,7 +336,7 @@ void multilog_del_type(enum log_type type, struct log_data *data) } } - unlock_mutex(); + unlock_list(lock_handle); if (ll) { if (ll->type == threaded_syslog) { @@ -279,7 +346,6 @@ void multilog_del_type(enum log_type type, struct log_data *data) stop_syslog(data); dlclose(data->info.threaded_syslog.dlh); - dlclose(data->info.threaded_syslog.pthread_dlh); } free(ll); @@ -294,14 +360,14 @@ void multilog_custom(multilog_fn fn) * 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); } @@ -317,10 +383,10 @@ void multilog(int priority, const char *file, int line, const char *format, ...) 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); } diff --git a/multilog/libmultilog.h b/multilog/libmultilog.h index cdd59ad..4c64148 100644 --- a/multilog/libmultilog.h +++ b/multilog/libmultilog.h @@ -34,7 +34,6 @@ struct file_log { struct threaded_syslog_log { pthread_t thread; void *dlh; - void *pthread_dlh; }; union log_info { diff --git a/multilog/pthread_lock/.exported_symbols b/multilog/pthread_lock/.exported_symbols new file mode 100644 index 0000000..673b466 --- /dev/null +++ b/multilog/pthread_lock/.exported_symbols @@ -0,0 +1,4 @@ +init_locking +lock_fn +unlock_fn +destroy_locking \ No newline at end of file diff --git a/multilog/pthread_lock/Makefile.in b/multilog/pthread_lock/Makefile.in new file mode 100644 index 0000000..6d42bfa --- /dev/null +++ b/multilog/pthread_lock/Makefile.in @@ -0,0 +1,52 @@ +# +# 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 diff --git a/multilog/pthread_lock/pthread_lock.c b/multilog/pthread_lock/pthread_lock.c new file mode 100644 index 0000000..dfe24dc --- /dev/null +++ b/multilog/pthread_lock/pthread_lock.c @@ -0,0 +1,68 @@ +/* + * 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 +#include +#include +#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); +} + diff --git a/multilog/pthread_lock/pthread_lock.h b/multilog/pthread_lock/pthread_lock.h new file mode 100644 index 0000000..c180ae9 --- /dev/null +++ b/multilog/pthread_lock/pthread_lock.h @@ -0,0 +1,23 @@ +/* + * 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 + */ + +#ifndef LIB_PTHREADLOCK_H +#define LIB_PTHREADLOCK_H + +void *init_locking(void); +int lock_fn(void *handle); +int unlock_fn(void *handle); +void destroy_locking(void *handle); + +#endif