From 8b46126a076075aeed31dae1c80eca1ed9f5a251 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 17 Sep 2002 23:45:21 +0000 Subject: Never, *ever* hold a mutex lock in the message database where there may be traversals being attempted. Yes, this was from bitter experience (and an out of control server :-). Also allow callers to break out of a tdb_chainlock with sigalarm if desired. Jeremy. (This used to be commit a7781f91d8c1177210bffc199cd2f3b7ff993eaf) --- source3/Makefile.in | 4 +-- source3/lib/messages.c | 69 ---------------------------------------------- source3/lib/server_mutex.c | 5 ++-- source3/passdb/secrets.c | 66 ++++++++++++++++++++++++++++++++++++++++++++ source3/tdb/tdb.c | 15 ++++++++++ source3/tdb/tdb.h | 1 + source3/tdb/tdbbackup.c | 1 + 7 files changed, 87 insertions(+), 74 deletions(-) (limited to 'source3') diff --git a/source3/Makefile.in b/source3/Makefile.in index 87ee4ef540..cc8fb42e9a 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -136,7 +136,7 @@ LIB_OBJ = lib/charcnv.o lib/debug.o lib/fault.o \ lib/util.o lib/util_sock.o lib/util_sec.o \ lib/talloc.o lib/hash.o lib/substitute.o lib/fsusage.o \ lib/ms_fnmatch.o lib/select.o lib/error.o lib/messages.o \ - lib/server_mutex.o lib/tallocmsg.o lib/dmallocmsg.o \ + lib/tallocmsg.o lib/dmallocmsg.o \ lib/md5.o lib/hmacmd5.o lib/iconv.o lib/smbpasswd.o \ nsswitch/wb_client.o nsswitch/wb_common.o \ lib/pam_errors.o intl/lang_tdb.o lib/account_pol.o \ @@ -259,7 +259,7 @@ SMBD_OBJ_SRV = smbd/files.o smbd/chgpasswd.o smbd/connection.o \ smbd/dosmode.o smbd/filename.o smbd/open.o smbd/close.o \ smbd/blocking.o smbd/sec_ctx.o \ smbd/vfs.o smbd/vfs-wrap.o smbd/statcache.o \ - smbd/posix_acls.o lib/sysacls.o \ + smbd/posix_acls.o lib/sysacls.o lib/server_mutex.o \ smbd/process.o smbd/service.o smbd/error.o \ printing/printfsp.o lib/util_seaccess.o smbd/srvstr.o \ smbd/build_options.o \ diff --git a/source3/lib/messages.c b/source3/lib/messages.c index 21470dff5c..d9886a54da 100644 --- a/source3/lib/messages.c +++ b/source3/lib/messages.c @@ -471,73 +471,4 @@ BOOL message_send_all(TDB_CONTEXT *conn_tdb, int msg_type, *n_sent = msg_all.n_sent; return True; } - -static SIG_ATOMIC_T gotalarm; - -/*************************************************************** - Signal function to tell us we timed out. -****************************************************************/ - -static void gotalarm_sig(void) -{ - gotalarm = 1; -} - -/** - * Lock the messaging tdb based on a string - this is used as a primitive - * form of mutex between smbd instances. - * - * @param name A string identifying the name of the mutex. - */ - -BOOL message_named_mutex(char *name, unsigned int timeout) -{ - TDB_DATA key; - int ret; - void (*oldsig_handler)(int) = NULL; - - if (!message_init()) - return False; - - key.dptr = name; - key.dsize = strlen(name)+1; - - if (timeout) { - gotalarm = 0; - oldsig_handler = CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig); - alarm(timeout); - } - - ret = tdb_chainlock(tdb, key); - - if (timeout) { - alarm(0); - CatchSignal(SIGALRM, SIGNAL_CAST oldsig_handler); - if (gotalarm) - return False; - } - - if (ret == 0) - DEBUG(10,("message_named_mutex: got mutex for %s\n", name )); - - return (ret == 0); -} - -/** - * Unlock a named mutex. - * - * @param name A string identifying the name of the mutex. - */ - -void message_named_mutex_release(char *name) -{ - TDB_DATA key; - - key.dptr = name; - key.dsize = strlen(name)+1; - - tdb_chainunlock(tdb, key); - DEBUG(10,("message_named_mutex: released mutex for %s\n", name )); -} - /** @} **/ diff --git a/source3/lib/server_mutex.c b/source3/lib/server_mutex.c index 416d77564d..3e5512c734 100644 --- a/source3/lib/server_mutex.c +++ b/source3/lib/server_mutex.c @@ -38,7 +38,7 @@ BOOL grab_server_mutex(const char *name) DEBUG(0,("grab_server_mutex: malloc failed for %s\n", name)); return False; } - if (!message_named_mutex(mutex_server_name, 20)) { + if (!secrets_named_mutex(mutex_server_name, 10)) { DEBUG(10,("grab_server_mutex: failed for %s\n", name)); SAFE_FREE(mutex_server_name); return False; @@ -50,8 +50,7 @@ BOOL grab_server_mutex(const char *name) void release_server_mutex(void) { if (mutex_server_name) { - message_named_mutex_release(mutex_server_name); + secrets_named_mutex_release(mutex_server_name); SAFE_FREE(mutex_server_name); } } - diff --git a/source3/passdb/secrets.c b/source3/passdb/secrets.c index 307dc132fc..b2bdaf2753 100644 --- a/source3/passdb/secrets.c +++ b/source3/passdb/secrets.c @@ -559,3 +559,69 @@ NTSTATUS secrets_get_trusted_domains(TALLOC_CTX* ctx, int* enum_ctx, int max_num return status; } +static SIG_ATOMIC_T gotalarm; + +/*************************************************************** + Signal function to tell us we timed out. +****************************************************************/ + +static void gotalarm_sig(void) +{ + gotalarm = 1; +} + +/* + lock the secrets tdb based on a string - this is used as a primitive form of mutex + between smbd instances. +*/ +BOOL secrets_named_mutex(const char *name, unsigned int timeout) +{ + TDB_DATA key; + int ret; + + if (!message_init()) + return False; + + key.dptr = (char *)name; + key.dsize = strlen(name)+1; + + /* Allow tdb_chainlock to be interrupted by an alarm. */ + gotalarm = 0; + tdb_set_lock_alarm(&gotalarm); + + if (timeout) { + CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig); + alarm(timeout); + } + + ret = tdb_chainlock(tdb, key); + + /* Prevent tdb_chainlock from being interrupted by an alarm. */ + tdb_set_lock_alarm(NULL); + + if (timeout) { + alarm(0); + CatchSignal(SIGALRM, SIGNAL_CAST SIG_IGN); + if (gotalarm) + return False; + } + + if (ret == 0) + DEBUG(10,("secrets_named_mutex: got mutex for %s\n", name )); + + return (ret == 0); +} + +/* + unlock a named mutex +*/ +void secrets_named_mutex_release(char *name) +{ + TDB_DATA key; + + key.dptr = name; + key.dsize = strlen(name)+1; + + tdb_chainunlock(tdb, key); + DEBUG(10,("secrets_named_mutex: released mutex for %s\n", name )); +} diff --git a/source3/tdb/tdb.c b/source3/tdb/tdb.c index 40e7dcd42c..5bb75ffe07 100644 --- a/source3/tdb/tdb.c +++ b/source3/tdb/tdb.c @@ -34,6 +34,7 @@ #include #include #include +#include #include "tdb.h" #include "spinlock.h" #else @@ -160,6 +161,18 @@ struct list_struct { */ }; +/*************************************************************** + Allow a caller to set a "alarm" flag that tdb can check to abort + a blocking lock on SIGALRM. +***************************************************************/ + +static sig_atomic_t *palarm_fired; + +void tdb_set_lock_alarm(sig_atomic_t *palarm) +{ + palarm_fired = palarm; +} + /* a byte range locking function - return 0 on success this functions locks/unlocks 1 byte at the specified offset. @@ -186,6 +199,8 @@ static int tdb_brlock(TDB_CONTEXT *tdb, tdb_off offset, do { ret = fcntl(tdb->fd,lck_type,&fl); + if (ret == -1 && errno == EINTR && palarm_fired && *palarm_fired) + break; } while (ret == -1 && errno == EINTR); if (ret == -1) { diff --git a/source3/tdb/tdb.h b/source3/tdb/tdb.h index 8cc908703f..42b88aeb16 100644 --- a/source3/tdb/tdb.h +++ b/source3/tdb/tdb.h @@ -126,6 +126,7 @@ int tdb_lockall(TDB_CONTEXT *tdb); void tdb_unlockall(TDB_CONTEXT *tdb); /* Low level locking functions: use with care */ +void tdb_set_lock_alarm(sig_atomic_t *palarm); int tdb_chainlock(TDB_CONTEXT *tdb, TDB_DATA key); int tdb_chainunlock(TDB_CONTEXT *tdb, TDB_DATA key); diff --git a/source3/tdb/tdbbackup.c b/source3/tdb/tdbbackup.c index f59f98a90f..36ba7db918 100644 --- a/source3/tdb/tdbbackup.c +++ b/source3/tdb/tdbbackup.c @@ -53,6 +53,7 @@ #include #include #include +#include #include "tdb.h" static int failed; -- cgit