summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2002-09-17 23:45:21 +0000
committerJeremy Allison <jra@samba.org>2002-09-17 23:45:21 +0000
commit8b46126a076075aeed31dae1c80eca1ed9f5a251 (patch)
treef562440e4e262cf8c91b4892c7a4375394dd27a2
parentfe92e9caedbb68756f9d4fcb8ee20c2573e9c4ae (diff)
downloadsamba-8b46126a076075aeed31dae1c80eca1ed9f5a251.tar.gz
samba-8b46126a076075aeed31dae1c80eca1ed9f5a251.tar.bz2
samba-8b46126a076075aeed31dae1c80eca1ed9f5a251.zip
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)
-rw-r--r--source3/Makefile.in4
-rw-r--r--source3/lib/messages.c69
-rw-r--r--source3/lib/server_mutex.c5
-rw-r--r--source3/passdb/secrets.c66
-rw-r--r--source3/tdb/tdb.c15
-rw-r--r--source3/tdb/tdb.h1
-rw-r--r--source3/tdb/tdbbackup.c1
7 files changed, 87 insertions, 74 deletions
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 <errno.h>
#include <sys/mman.h>
#include <sys/stat.h>
+#include <signal.h>
#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 <sys/stat.h>
#include <sys/time.h>
#include <ctype.h>
+#include <signal.h>
#include "tdb.h"
static int failed;