From d8f3c9d0786ff637241d2a9409e1c7c253715ba5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 6 Nov 2007 21:47:57 -0800 Subject: 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) --- source3/lib/replace/replace.h | 4 ++++ source3/lib/replace/system/wait.h | 4 ++++ source3/lib/tdb/common/lock.c | 12 ++++++++++++ source3/lib/tdb/common/tdb_private.h | 2 ++ source3/lib/tdb/include/tdb.h | 2 ++ source3/lib/tdb/tools/tdbbackup.c | 1 + source3/lib/tdb/tools/tdbdump.c | 1 + source3/lib/tdb/tools/tdbtool.c | 1 + source3/lib/util_tdb.c | 2 ++ 9 files changed, 29 insertions(+) (limited to 'source3/lib') 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", -- cgit