]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
ctdb-mutex: Change parent checking to use an asynchronous computation
authorMartin Schwenke <martin@meltin.net>
Thu, 27 Jun 2019 03:45:01 +0000 (13:45 +1000)
committerMartin Schwenke <martins@samba.org>
Fri, 26 Jul 2019 03:34:17 +0000 (03:34 +0000)
Put the checking for the process being immediately re-parented into
the computation too.  This will be very rare and doing it
consistently makes testing saner.

Signed-off-by: Martin Schwenke <martin@meltin.net>
Reviewed-by: Amitay Isaacs <amitay@gmail.com>
ctdb/server/ctdb_mutex_fcntl_helper.c
ctdb/tests/cunit/cluster_mutex_001.sh
ctdb/tests/cunit/cluster_mutex_002.sh
ctdb/tests/cunit/cluster_mutex_003.sh
ctdb/wscript

index 44505047167e58c72b17dcbf5daefc4325cfed18..85095c64c719306b22d28eba5533b250e6ff468d 100644 (file)
@@ -3,6 +3,10 @@
 
    Copyright (C) Martin Schwenke 2015
 
+   wait_for_parent() code from ctdb_lock_helper.c:
+
+   Copyright (C) Amitay Isaacs  2013
+
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
 #include "system/filesys.h"
 #include "system/network.h"
 
+#include <tevent.h>
+
 #include "lib/util/sys_rw.h"
+#include "lib/util/tevent_unix.h"
 
 /* protocol.h is just needed for ctdb_sock_addr, which is used in system.h */
 #include "protocol/protocol.h"
@@ -68,12 +75,97 @@ static char fcntl_lock(const char *file, int *outfd)
        return '0';
 }
 
+/*
+ * Wait and see if the parent exits
+ */
+
+struct wait_for_parent_state {
+       struct tevent_context *ev;
+       pid_t ppid;
+};
+
+static void wait_for_parent_check(struct tevent_req *subreq);
+
+static struct tevent_req *wait_for_parent_send(TALLOC_CTX *mem_ctx,
+                                              struct tevent_context *ev,
+                                              pid_t ppid)
+{
+       struct tevent_req *req, *subreq;
+       struct wait_for_parent_state *state;
+
+       req = tevent_req_create(mem_ctx, &state, struct wait_for_parent_state);
+       if (req == NULL) {
+               return NULL;
+       }
+
+       state->ev = ev;
+       state->ppid = ppid;
+
+       if (ppid == 1) {
+               fprintf(stderr, "parent == 1\n");
+               tevent_req_done(req);
+               return tevent_req_post(req, ev);
+       }
+
+       subreq = tevent_wakeup_send(state, ev,
+                                   tevent_timeval_current_ofs(5,0));
+       if (tevent_req_nomem(subreq, req)) {
+               return tevent_req_post(req, ev);
+       }
+       tevent_req_set_callback(subreq, wait_for_parent_check, req);
+
+       return req;
+}
+
+static void wait_for_parent_check(struct tevent_req *subreq)
+{
+       struct tevent_req *req = tevent_req_callback_data(
+               subreq, struct tevent_req);
+       struct wait_for_parent_state *state = tevent_req_data(
+               req, struct wait_for_parent_state);
+       bool status;
+
+       status = tevent_wakeup_recv(subreq);
+       TALLOC_FREE(subreq);
+       if (! status) {
+               /* Ignore error */
+               fprintf(stderr,
+                       "ctdb_mutex_fcntl_helper: "
+                       "tevent_wakeup_recv() failed\n");
+       }
+
+       if (kill(state->ppid, 0) == -1 && errno == ESRCH) {
+               fprintf(stderr, "parent gone\n");
+               tevent_req_done(req);
+               return;
+       }
+
+       subreq = tevent_wakeup_send(state, state->ev,
+                                   tevent_timeval_current_ofs(5,0));
+       if (tevent_req_nomem(subreq, req)) {
+               return;
+       }
+       tevent_req_set_callback(subreq, wait_for_parent_check, req);
+}
+
+static bool wait_for_parent_recv(struct tevent_req *req)
+{
+       if (tevent_req_is_unix_error(req, NULL)) {
+               return false;
+       }
+
+       return true;
+}
+
 int main(int argc, char *argv[])
 {
+       struct tevent_context *ev;
        char result;
        int ppid;
        const char *file = NULL;
        int fd = -1;
+       struct tevent_req *req;
+       bool status;
 
        progname = argv[0];
 
@@ -82,20 +174,14 @@ int main(int argc, char *argv[])
                exit(1);
        }
 
-       ppid = getppid();
-
-       if (ppid == 1) {
-               /* The original parent is gone and the process has
-                * been reparented to init.  This can happen if the
-                * helper is started just as the parent is killed
-                * during shutdown.  The error message doesn't need to
-                * be stellar, since there won't be anything around to
-                * capture and log it...
-                */
-               fprintf(stderr, "%s: PPID == 1\n", progname);
+       ev = tevent_context_init(NULL);
+       if (ev == NULL) {
+               fprintf(stderr, "locking: tevent_context_init() failed\n");
                exit(1);
        }
 
+       ppid = getppid();
+
        file = argv[1];
 
        result = fcntl_lock(file, &fd);
@@ -105,7 +191,22 @@ int main(int argc, char *argv[])
                return 0;
        }
 
-       ctdb_wait_for_process_to_exit(ppid);
+       req = wait_for_parent_send(ev, ev, ppid);
+       if (req == NULL) {
+               fprintf(stderr,
+                       "%s: wait_for_parent_send() failed\n",
+                       progname);
+               exit(1);
+       }
+
+       tevent_req_poll(req, ev);
+
+       status = wait_for_parent_recv(req);
+       if (! status) {
+               fprintf(stderr,
+                       "%s: wait_for_parent_recv() failed\n",
+                       progname);
+       }
 
        if (fd != -1) {
                close(fd);
index 81671da8f4843d9388f9031b106a31c6380b2ba1..feb78f3efa8dfed59004e075858e8503b3028009 100755 (executable)
@@ -52,6 +52,7 @@ unit_test cluster_mutex_test lock-wait-unlock "$lockfile"
 
 ok <<EOF
 LOCK
+parent gone
 LOCK
 UNLOCK
 EOF
index fea6cfe2b93b2d5e13bfe79f83399408728f70a6..6cc92d0b2a3ca81d7d70ac28761a83af861cfe30 100755 (executable)
@@ -54,6 +54,7 @@ unit_test cluster_mutex_test lock-wait-unlock "$helper"
 
 ok <<EOF
 LOCK
+parent gone
 LOCK
 UNLOCK
 EOF
index 19298b653352d1abbb417a496b01bd0a4722162c..5f351d9e9e1dcc6c234ce82e19fcdd95c2517d98 100755 (executable)
@@ -61,6 +61,7 @@ unit_test cluster_mutex_test lock-wait-unlock "$helper"
 
 ok <<EOF
 LOCK
+parent gone
 LOCK
 UNLOCK
 EOF
index ec6389189ad966fc205cb0a83fc958f066339160..3b8fea45e74f00cf8556fd9904824ef9db4e9053 100644 (file)
@@ -625,7 +625,9 @@ def build(bld):
 
     bld.SAMBA_BINARY('ctdb_mutex_fcntl_helper',
                      source='server/ctdb_mutex_fcntl_helper.c',
-                     deps='sys_rw ctdb-system',
+                     deps='''sys_rw ctdb-system tevent-util
+                             talloc tevent
+                          ''',
                      includes='include',
                      install_path='${CTDB_HELPER_BINDIR}')