]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
ctdb-cluster-mutex: Block signals around fork
authorMartin Schwenke <martin@meltin.net>
Wed, 12 Sep 2018 07:51:47 +0000 (17:51 +1000)
committerKarolin Seeger <kseeger@samba.org>
Thu, 20 Sep 2018 07:13:11 +0000 (09:13 +0200)
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)

ctdb/server/ctdb_cluster_mutex.c

index e8c75debfb879df898d2aa9eb560ff4d059571c6..330d5fd1d909c2275eba5af7c857dbf3ff911463 100644 (file)
@@ -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]);