summaryrefslogtreecommitdiffstats
path: root/src/run.c
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2012-11-06 16:51:11 +0100
committerPablo Neira Ayuso <pablo@netfilter.org>2012-11-06 17:10:39 +0100
commit102293accbc6ac3a21d68ab98e058263b316a407 (patch)
treee01388237cfbc0f48634fa55665e71154e0a490a /src/run.c
parente61ac9a2e58cdcf6dc9a12d32b1f221e078e5d05 (diff)
conntrackd: fix deadlock due to wrong nested signal blocking
The existing code may nest several signal blocking and unblocking calls in different paths of the code. This may result in deadlocks while receiving signals. This patch simplifies the signal blocking approach. Now signals are blocked in three paths: 1) Internal timers handling, while running timer callback for expired timers. 2) File descriptor handling, while running file descriptor callbacks. 3) While handling signals, to avoid that SIGINT and SIGTERM in a row results in a deadlock. Thanks a lot to Ulrich Weber <ulrich.weber@sophos.com> for discussing a fix for this problem. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src/run.c')
-rw-r--r--src/run.c13
1 files changed, 8 insertions, 5 deletions
diff --git a/src/run.c b/src/run.c
index 3337694..44a179f 100644
--- a/src/run.c
+++ b/src/run.c
@@ -40,10 +40,15 @@
#include <time.h>
#include <fcntl.h>
-void killer(int foo)
+void killer(int signal)
{
- /* no signals while handling signals */
- sigprocmask(SIG_BLOCK, &STATE(block), NULL);
+ /* Signals are re-entrant, disable signal handling to avoid problems
+ * in case we receive SIGINT and SIGTERM in a row. This function is
+ * also called via -k from the unix socket context, we already disabled
+ * signals in that path, so don't do it.
+ */
+ if (signal)
+ sigprocmask(SIG_BLOCK, &STATE(block), NULL);
local_server_destroy(&STATE(local));
@@ -58,8 +63,6 @@ void killer(int foo)
dlog(LOG_NOTICE, "---- shutdown received ----");
close_log();
- sigprocmask(SIG_UNBLOCK, &STATE(block), NULL);
-
exit(0);
}