Fix bug where tdb lock call interrupted with
authorJeremy Allison <jra@samba.org>
Wed, 7 Nov 2007 05:48:01 +0000 (21:48 -0800)
committerJeremy Allison <jra@samba.org>
Wed, 7 Nov 2007 05:48:01 +0000 (21:48 -0800)
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.

source/lib/replace/replace.h
source/lib/replace/system/wait.h
source/lib/util_tdb.c
source/tdb/common/lock.c
source/tdb/common/tdb_private.h
source/tdb/include/tdb.h

index b96356ac4670c2e4b76e0458986f8fdf50629a30..c298b36fcbaa8dd3ead757ef704fecff16190a0b 100644 (file)
 #include <stddef.h>
 #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
index 179ef0774e0a2a25f6a6746f6591d8c4c965b437..074675d8a46f636f8d8406ab346ace0048a4fecf 100644 (file)
@@ -44,4 +44,8 @@
 #define SA_RESETHAND SA_ONESHOT
 #endif
 
+#if !defined(HAVE_SIG_ATOMIC_T_TYPE)
+typedef int sig_atomic_t;
+#endif
+
 #endif
index a1b5bf5bb16d1bcbb4ead4ea28939f0d6762c4ca..48e34e0b32f576e2fbcf99014a577c4a3c5b99d2 100644 (file)
@@ -68,6 +68,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);
        }
 
@@ -78,6 +79,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",
index 8a964371d3aa846510c90edc7e95a7c7c11eec67..3bc0a9cb9e48bd56f8b5fc4c33645d488c4cc62a 100644 (file)
 
 #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.
 
@@ -59,6 +64,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) {
index 10bc6dacdcfbf4d49a1255b1add5dc728d301afd..84422423261fc2543877a51d3ac9ed435224855b 100644 (file)
@@ -29,6 +29,7 @@
 #include "system/time.h"
 #include "system/shmem.h"
 #include "system/select.h"
+#include "system/wait.h"
 #include "tdb.h"
 
 #ifndef u32
@@ -170,6 +171,7 @@ struct tdb_context {
        struct tdb_transaction *transaction;
        int page_size;
        int max_dead_records;
+       volatile sig_atomic_t *interrupt_sig_ptr;
 };
 
 
index 51bf709f44212f11b16543f4d8bf3bf942b18571..3bd30b8f56092841d4a6a8fe4e31b40988ab8a4c 100644 (file)
@@ -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);