aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Schwenke <martin@meltin.net>2018-09-12 17:51:47 +1000
committerKarolin Seeger <kseeger@samba.org>2018-09-20 09:13:11 +0200
commiteb498ec2baea154bdba313fc495a9dc7e0322f77 (patch)
tree2cecb3937331d3ceab1ac4a4fb080acd8980889a
parent1954a94203789422b163b4f257aa3c9ab83fa9a2 (diff)
downloadsamba-eb498ec2baea154bdba313fc495a9dc7e0322f77.tar.gz
samba-eb498ec2baea154bdba313fc495a9dc7e0322f77.tar.xz
samba-eb498ec2baea154bdba313fc495a9dc7e0322f77.zip
ctdb-cluster-mutex: Block signals around fork
If SIGTERM is received and the tevent signal handler setup in the recovery daemon is still enabled then the signal is handled and a corresponding event is queued. The child never runs an event loop so the signal is effectively ignored. Resetting the SIGTERM handler isn't enough. A signal can arrive before that. Block SIGTERM before forking and then immediately unblock it in the parent. In the child, unblock SIGTERM after the signal handler is reset. An explicit unblock is needed because according to sigprocmask(2) "the signal mask is preserved across execve(2)". BUG: https://bugzilla.samba.org/show_bug.cgi?id=13617 Signed-off-by: Martin Schwenke <martin@meltin.net> Reviewed-by: Amitay Isaacs <amitay@gmail.com> (cherry picked from commit e789d0da57fc3fc6d22bfa00577a2e65034ca27a)
-rw-r--r--ctdb/server/ctdb_cluster_mutex.c22
1 files changed, 22 insertions, 0 deletions
diff --git a/ctdb/server/ctdb_cluster_mutex.c b/ctdb/server/ctdb_cluster_mutex.c
index e8c75debfb8..330d5fd1d90 100644
--- a/ctdb/server/ctdb_cluster_mutex.c
+++ b/ctdb/server/ctdb_cluster_mutex.c
@@ -196,6 +196,7 @@ ctdb_cluster_mutex(TALLOC_CTX *mem_ctx,
{
struct ctdb_cluster_mutex_handle *h;
char **args;
+ sigset_t sigset_term;
int ret;
h = talloc(mem_ctx, struct ctdb_cluster_mutex_handle);
@@ -225,11 +226,22 @@ ctdb_cluster_mutex(TALLOC_CTX *mem_ctx,
return NULL;
}
+ sigemptyset(&sigset_term);
+ sigaddset(&sigset_term, SIGTERM);
+ ret = sigprocmask(SIG_BLOCK, &sigset_term, NULL);
+ if (ret != 0) {
+ DBG_WARNING("Failed to block SIGTERM (%d)\n", errno);
+ }
+
h->child = ctdb_fork(ctdb);
if (h->child == (pid_t)-1) {
close(h->fd[0]);
close(h->fd[1]);
talloc_free(h);
+ ret = sigprocmask(SIG_UNBLOCK, &sigset_term, NULL);
+ if (ret != 0) {
+ DBG_WARNING("Failed to unblock SIGTERM (%d)\n", errno);
+ }
return NULL;
}
@@ -244,6 +256,11 @@ ctdb_cluster_mutex(TALLOC_CTX *mem_ctx,
errno);
}
+ ret = sigprocmask(SIG_UNBLOCK, &sigset_term, NULL);
+ if (ret != 0) {
+ DBG_WARNING("Failed to unblock SIGTERM (%d)\n", errno);
+ }
+
/* Make stdout point to the pipe */
close(STDOUT_FILENO);
dup2(h->fd[1], STDOUT_FILENO);
@@ -258,6 +275,11 @@ ctdb_cluster_mutex(TALLOC_CTX *mem_ctx,
/* Parent */
+ ret = sigprocmask(SIG_UNBLOCK, &sigset_term, NULL);
+ if (ret != 0) {
+ DBG_WARNING("Failed to unblock SIGTERM (%d)\n", errno);
+ }
+
DEBUG(DEBUG_DEBUG, (__location__ " Created PIPE FD:%d\n", h->fd[0]));
set_close_on_exec(h->fd[0]);