summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2007-11-06 21:47:57 -0800
committerJeremy Allison <jra@samba.org>2007-11-06 21:47:57 -0800
commitd8f3c9d0786ff637241d2a9409e1c7c253715ba5 (patch)
tree7fe843ce0e72d348e6114af9626d41c29419c1c0
parent7498e1b8c09abef2db0658c6bfd6d42891c9690d (diff)
downloadsamba-d8f3c9d0786ff637241d2a9409e1c7c253715ba5.tar.gz
samba-d8f3c9d0786ff637241d2a9409e1c7c253715ba5.tar.bz2
samba-d8f3c9d0786ff637241d2a9409e1c7c253715ba5.zip
Fix bug where tdb lock call interrupted with
an alarm sig would not terminate and could lead to runaway smbd processes. Thanks to Dave Daugherty @ Centrify for pointing this out to us. Jeremy. (This used to be commit ef8da1698371c95495add53df81a978df709c88d)
-rw-r--r--source3/lib/replace/replace.h4
-rw-r--r--source3/lib/replace/system/wait.h4
-rw-r--r--source3/lib/tdb/common/lock.c12
-rw-r--r--source3/lib/tdb/common/tdb_private.h2
-rw-r--r--source3/lib/tdb/include/tdb.h2
-rw-r--r--source3/lib/tdb/tools/tdbbackup.c1
-rw-r--r--source3/lib/tdb/tools/tdbdump.c1
-rw-r--r--source3/lib/tdb/tools/tdbtool.c1
-rw-r--r--source3/lib/util_tdb.c2
9 files changed, 29 insertions, 0 deletions
diff --git a/source3/lib/replace/replace.h b/source3/lib/replace/replace.h
index e42d5ff168..55ed2e9570 100644
--- a/source3/lib/replace/replace.h
+++ b/source3/lib/replace/replace.h
@@ -452,6 +452,10 @@ typedef int bool;
#define MAX(a,b) ((a)>(b)?(a):(b))
#endif
+#if !defined(HAVE_VOLATILE)
+#define volatile
+#endif
+
/**
this is a warning hack. The idea is to use this everywhere that we
get the "discarding const" warning from gcc. That doesn't actually
diff --git a/source3/lib/replace/system/wait.h b/source3/lib/replace/system/wait.h
index de94cf09d5..5784b1ae92 100644
--- a/source3/lib/replace/system/wait.h
+++ b/source3/lib/replace/system/wait.h
@@ -48,4 +48,8 @@
#define SA_RESETHAND SA_ONESHOT
#endif
+#if !defined(HAVE_SIG_ATOMIC_T_TYPE)
+typedef int sig_atomic_t;
+#endif
+
#endif
diff --git a/source3/lib/tdb/common/lock.c b/source3/lib/tdb/common/lock.c
index 22896f5227..43be5d20e1 100644
--- a/source3/lib/tdb/common/lock.c
+++ b/source3/lib/tdb/common/lock.c
@@ -27,6 +27,11 @@
#include "tdb_private.h"
+void tdb_setalarm_sigptr(struct tdb_context *tdb, volatile sig_atomic_t *ptr)
+{
+ tdb->interrupt_sig_ptr = ptr;
+}
+
/* a byte range locking function - return 0 on success
this functions locks/unlocks 1 byte at the specified offset.
@@ -58,6 +63,13 @@ int tdb_brlock(struct tdb_context *tdb, tdb_off_t offset,
do {
ret = fcntl(tdb->fd,lck_type,&fl);
+
+ /* Check for a sigalarm break. */
+ if (ret == -1 && errno == EINTR &&
+ tdb->interrupt_sig_ptr &&
+ *tdb->interrupt_sig_ptr) {
+ break;
+ }
} while (ret == -1 && errno == EINTR);
if (ret == -1) {
diff --git a/source3/lib/tdb/common/tdb_private.h b/source3/lib/tdb/common/tdb_private.h
index d2f2c23d72..daef07aff1 100644
--- a/source3/lib/tdb/common/tdb_private.h
+++ b/source3/lib/tdb/common/tdb_private.h
@@ -28,6 +28,7 @@
#include "system/time.h"
#include "system/shmem.h"
#include "system/select.h"
+#include "system/wait.h"
#include "tdb.h"
#ifndef HAVE_GETPAGESIZE
@@ -161,6 +162,7 @@ struct tdb_context {
struct tdb_transaction *transaction;
int page_size;
int max_dead_records;
+ volatile sig_atomic_t *interrupt_sig_ptr;
};
diff --git a/source3/lib/tdb/include/tdb.h b/source3/lib/tdb/include/tdb.h
index a75df2d7d5..21410e840b 100644
--- a/source3/lib/tdb/include/tdb.h
+++ b/source3/lib/tdb/include/tdb.h
@@ -138,6 +138,8 @@ int tdb_chainunlock(struct tdb_context *tdb, TDB_DATA key);
int tdb_chainlock_read(struct tdb_context *tdb, TDB_DATA key);
int tdb_chainunlock_read(struct tdb_context *tdb, TDB_DATA key);
+void tdb_setalarm_sigptr(struct tdb_context *tdb, volatile sig_atomic_t *sigptr);
+
/* Debug functions. Not used in production. */
void tdb_dump_all(struct tdb_context *tdb);
int tdb_printfreelist(struct tdb_context *tdb);
diff --git a/source3/lib/tdb/tools/tdbbackup.c b/source3/lib/tdb/tools/tdbbackup.c
index dedfb9e665..6f3ca48314 100644
--- a/source3/lib/tdb/tools/tdbbackup.c
+++ b/source3/lib/tdb/tools/tdbbackup.c
@@ -44,6 +44,7 @@
#include "system/locale.h"
#include "system/time.h"
#include "system/filesys.h"
+#include "system/wait.h"
#include "tdb.h"
#ifdef HAVE_GETOPT_H
diff --git a/source3/lib/tdb/tools/tdbdump.c b/source3/lib/tdb/tools/tdbdump.c
index a654c0fb31..8d930383b0 100644
--- a/source3/lib/tdb/tools/tdbdump.c
+++ b/source3/lib/tdb/tools/tdbdump.c
@@ -21,6 +21,7 @@
#include "system/locale.h"
#include "system/time.h"
#include "system/filesys.h"
+#include "system/wait.h"
#include "tdb.h"
static void print_data(TDB_DATA d)
diff --git a/source3/lib/tdb/tools/tdbtool.c b/source3/lib/tdb/tools/tdbtool.c
index da040f95f3..79435a3571 100644
--- a/source3/lib/tdb/tools/tdbtool.c
+++ b/source3/lib/tdb/tools/tdbtool.c
@@ -24,6 +24,7 @@
#include "system/locale.h"
#include "system/time.h"
#include "system/filesys.h"
+#include "system/wait.h"
#include "tdb.h"
static int do_command(void);
diff --git a/source3/lib/util_tdb.c b/source3/lib/util_tdb.c
index 6aa7a5348f..35c1a92ad5 100644
--- a/source3/lib/util_tdb.c
+++ b/source3/lib/util_tdb.c
@@ -72,6 +72,7 @@ static int tdb_chainlock_with_timeout_internal( TDB_CONTEXT *tdb, TDB_DATA key,
if (timeout) {
CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig);
+ tdb_setalarm_sigptr(tdb, &gotalarm);
alarm(timeout);
}
@@ -82,6 +83,7 @@ static int tdb_chainlock_with_timeout_internal( TDB_CONTEXT *tdb, TDB_DATA key,
if (timeout) {
alarm(0);
+ tdb_setalarm_sigptr(tdb, NULL);
CatchSignal(SIGALRM, SIGNAL_CAST SIG_IGN);
if (gotalarm) {
DEBUG(0,("tdb_chainlock_with_timeout_internal: alarm (%u) timed out for key %s in tdb %s\n",