From 345104a248a4b9840aa37570e8eb6d33b25215d1 Mon Sep 17 00:00:00 2001 From: Ben Kibbey Date: Mon, 22 Oct 2007 20:03:45 -0400 Subject: [PATCH] Added configuration parameter --disable-locking for systems that don't have a complete pthread_mutex_t data type. A complete data type is required because the mutex is stored in shared memory and a pointer won't work. FreeBSD and probably others have this problem. I'll probably end up rewriting pwmd to use multi-threading exclusively so this won't be a problem anymore. Until then, for systems that have this limitation, the chances of data file corruption are increased quite a bit if two processes have the same file open and both try to write. This also affects the key cache when two processes want to change the key when saving. --- configure.ac | 28 +++++++++++++++++++++++++++- src/cache.h | 11 ++++++++--- src/commands.c | 12 ++++++++++++ src/pwmd.c | 24 ++++++++++++++++++++++++ 4 files changed, 71 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index 592cf709..b953ca4e 100644 --- a/configure.ac +++ b/configure.ac @@ -48,7 +48,33 @@ AM_PATH_LIBGCRYPT(,, AC_MSG_ERROR([libgcrypt not found])) AM_PATH_XML2(,, AC_MSG_ERROR([libxml2 not found])) AM_PATH_LIBASSUAN(,, AC_MSG_ERROR([libassuan not found])) AM_PATH_GPG_ERROR(,, AC_MSG_ERROR([libgpg-error not found])) -ACX_PTHREAD() +ACX_PTHREAD(, AC_MSG_ERROR([pthreads not found])) + +AC_ARG_ENABLE(locking, AC_HELP_STRING([--disable-locking], [Disable cache mutex locking support.]), + locking=no, locking=yes) + +AC_MSG_CHECKING([if pthread_mutex_t is a complete type]) +AC_TRY_COMPILE([pthread.h], [ + void pthread_test() + { + pthread_mutex_t a; + typeof(*a) *b; + } + ], pthreads_ok=no, pthreads_ok=yes) + +if test "$pthreads_ok" = "yes"; then + AC_MSG_RESULT([yes]) + AC_DEFINE([WORKING_PTHREADS], 1, \ + [Define if your pthreads implementation has a complete pthread_mutex_t data type.]) +else + AC_MSG_RESULT([no]) + + if test "$locking" = "yes"; then + AC_MSG_ERROR([pthread_mutex_t must be a complete type for cache locking to + work properly. Update your OS or specify --disable-locking.]) + fi +fi + AC_CHECK_LIB(z, deflate,, AC_MSG_ERROR([Version 1.2.2.1 or later of zlib is required])) diff --git a/src/cache.h b/src/cache.h index 8488d600..7c50d583 100644 --- a/src/cache.h +++ b/src/cache.h @@ -19,6 +19,7 @@ #ifndef CACHE_H #define CACHE_H +#ifdef WORKING_PTHREADS #include /* @@ -51,6 +52,13 @@ is_locked = FALSE; \ } +pthread_mutex_t cache_mutex; +pthread_mutex_t *cache_mutexp; +gboolean is_locked; +#else +#define MUTEX_OFFSET cache_size +#endif + typedef struct { guchar filename[16]; // MD5 guchar key[32]; // SHA256/AES256/gcrykeysize @@ -61,9 +69,6 @@ typedef struct { void *shm_data; glong cache_size; -pthread_mutex_t cache_mutex; -pthread_mutex_t *cache_mutexp; -gboolean is_locked; void cache_adjust_timer(void); gboolean cache_set_timeout(const guchar *md5filename, glong timeout); diff --git a/src/commands.c b/src/commands.c index 6d96ff26..fbf468ad 100644 --- a/src/commands.c +++ b/src/commands.c @@ -299,7 +299,9 @@ static int open_command(assuan_context_t ctx, char *line) gchar **req; gchar *filename = NULL; +#ifdef WORKING_PTHREADS MUTEX_LOCK(ctx); +#endif if ((req = split_input_line(line, " ", 2)) != NULL) filename = req[0]; @@ -768,7 +770,9 @@ static int save_command(assuan_context_t ctx, char *line) glong outsize = 0; gint zerror; +#ifdef WORKING_PTHREADS MUTEX_LOCK(ctx); +#endif error = file_modified(client); if (error) { @@ -2083,7 +2087,9 @@ static int iscached_command(assuan_context_t ctx, char *line) gchar **req = split_input_line(line, " ", 0); guchar md5file[16]; +#ifdef WORKING_PTHREADS MUTEX_LOCK(ctx); +#endif if (!req || !*req) { g_strfreev(req); @@ -2118,7 +2124,9 @@ static int clearcache_command(assuan_context_t ctx, char *line) gchar **req = split_input_line(line, " ", 0); guchar md5file[16]; +#ifdef WORKING_PTHREADS MUTEX_LOCK(ctx); +#endif if (!req || !*req) { g_strfreev(req); @@ -2141,7 +2149,9 @@ static int cachetimeout_command(assuan_context_t ctx, char *line) gchar **req = split_input_line(line, " ", 0); gchar *p; +#ifdef WORKING_PTHREADS MUTEX_LOCK(ctx); +#endif if (!req || !*req || !req[1]) { g_strfreev(req); @@ -2217,7 +2227,9 @@ void cleanup_assuan(assuan_context_t ctx) struct client_s *cl = assuan_get_pointer(ctx); cleanup_client(cl); +#ifdef WORKING_PTHREADS MUTEX_UNLOCK; +#endif } gpg_error_t register_commands(assuan_context_t ctx) diff --git a/src/pwmd.c b/src/pwmd.c index cb9aa77b..3085b4e2 100644 --- a/src/pwmd.c +++ b/src/pwmd.c @@ -188,17 +188,25 @@ static void catchsig(gint sig, siginfo_t *info, gpointer uctx) reload_rcfile(); break; case SIGABRT: +#ifdef WORKING_PTHREADS MUTEX_LOCK(NULL); cache_clear(NULL, 2); MUTEX_UNLOCK; +#else + cache_clear(NULL, 2); +#endif #ifndef MEM_DEBUG xpanic(); #endif exit(EXIT_FAILURE); case SIGALRM: +#ifdef WORKING_PTHREADS MUTEX_LOCK(NULL); cache_adjust_timer(); MUTEX_UNLOCK; +#else + cache_adjust_timer(); +#endif alarm(1); break; case SIGCHLD: @@ -211,10 +219,14 @@ static void catchsig(gint sig, siginfo_t *info, gpointer uctx) break; case SIGHUP: +#ifdef WORKING_PTHREADS MUTEX_LOCK(NULL); +#endif log_write(N_("clearing file cache")); cache_clear(NULL, 2); +#ifdef WORKING_PTHREADS MUTEX_UNLOCK; +#endif break; default: signal(SIGALRM, SIG_IGN); @@ -272,14 +284,18 @@ static void child_catchsig(int sig) case SIGTERM: ret = EXIT_SUCCESS; case SIGPIPE: +#ifdef WORKING_PTHREADS MUTEX_UNLOCK; +#endif cleanup_assuan(ctx); g_free(global_client); assuan_deinit_server(ctx); _exit(ret); break; case SIGABRT: +#ifdef WORKING_PTHREADS MUTEX_UNLOCK; +#endif #ifndef MEM_DEBUG xpanic(); #endif @@ -296,8 +312,10 @@ static void child_catchsig(int sig) */ static void command_finalize(assuan_context_t ctx, gint error) { +#ifdef WORKING_PTHREADS if (is_locked == TRUE) MUTEX_UNLOCK; +#endif } /* @@ -310,7 +328,9 @@ static void doit(int fd) struct client_s *cl = g_malloc0(sizeof(struct client_s)); gchar ver[ASSUAN_LINELENGTH]; +#ifdef WORKING_PTHREADS is_locked = FALSE; +#endif signal(SIGCHLD, SIG_DFL); signal(SIGHUP, SIG_IGN); signal(SIGINT, SIG_IGN); @@ -1285,9 +1305,11 @@ int main(int argc, char *argv[]) } g_free(datadir); +#ifdef WORKING_PTHREADS pthread_mutex_init(&cache_mutex, NULL); cache_mutexp = shm_data + MUTEX_OFFSET; memcpy(cache_mutexp, &cache_mutex, sizeof(cache_mutex)); +#endif if (listen(sfd, 0) == -1) { warn("listen()"); @@ -1382,8 +1404,10 @@ do_exit: } while (clients); } +#ifdef WORKING_PTHREADS if (cache_mutexp) pthread_mutex_destroy(cache_mutexp); +#endif memset(shm_data, 0, cache_size); -- 2.11.4.GIT