From 3480b42be1adc7c2876a77e8260049447338c3ff Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 6 Nov 2007 21:48:01 -0800 Subject: [PATCH] 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. --- source/lib/replace/replace.h | 4 ++++ source/lib/replace/system/wait.h | 4 ++++ source/lib/util_tdb.c | 2 ++ source/tdb/common/lock.c | 12 ++++++++++++ source/tdb/common/tdb_private.h | 2 ++ source/tdb/include/tdb.h | 2 ++ 6 files changed, 26 insertions(+) diff --git a/source/lib/replace/replace.h b/source/lib/replace/replace.h index b96356ac46..c298b36fcb 100644 --- a/source/lib/replace/replace.h +++ b/source/lib/replace/replace.h @@ -79,6 +79,10 @@ #include #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/source/lib/replace/system/wait.h b/source/lib/replace/system/wait.h index 179ef0774e..074675d8a4 100644 --- a/source/lib/replace/system/wait.h +++ b/source/lib/replace/system/wait.h @@ -44,4 +44,8 @@ #define SA_RESETHAND SA_ONESHOT #endif +#if !defined(HAVE_SIG_ATOMIC_T_TYPE) +typedef int sig_atomic_t; +#endif + #endif diff --git a/source/lib/util_tdb.c b/source/lib/util_tdb.c index a1b5bf5bb1..48e34e0b32 100644 --- a/source/lib/util_tdb.c +++ b/source/lib/util_tdb.c @@ -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", diff --git a/source/tdb/common/lock.c b/source/tdb/common/lock.c index 8a964371d3..3bc0a9cb9e 100644 --- a/source/tdb/common/lock.c +++ b/source/tdb/common/lock.c @@ -28,6 +28,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. @@ -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) { diff --git a/source/tdb/common/tdb_private.h b/source/tdb/common/tdb_private.h index 10bc6dacdc..8442242326 100644 --- a/source/tdb/common/tdb_private.h +++ b/source/tdb/common/tdb_private.h @@ -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; }; diff --git a/source/tdb/include/tdb.h b/source/tdb/include/tdb.h index 51bf709f44..3bd30b8f56 100644 --- a/source/tdb/include/tdb.h +++ b/source/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); -- 2.34.1