summaryrefslogtreecommitdiff
path: root/ctdb
diff options
context:
space:
mode:
authorAmitay Isaacs <amitay@gmail.com>2017-11-17 12:38:47 +1100
committerMartin Schwenke <martins@samba.org>2017-11-21 08:58:45 +0100
commitc1b4a74f272977ebdc735c040e976853c7ca800f (patch)
tree0bdeaa23d69829600a90cd1517d1c6764a034373 /ctdb
parent41d888afbecfca6e4ea3c6c86c05101bd5e5b5c4 (diff)
downloadsamba-c1b4a74f272977ebdc735c040e976853c7ca800f.tar.gz
ctdb-common: Add async version of shutdown in sock_daemon
Signed-off-by: Amitay Isaacs <amitay@gmail.com> Reviewed-by: Martin Schwenke <martin@meltin.net> Autobuild-User(master): Martin Schwenke <martins@samba.org> Autobuild-Date(master): Tue Nov 21 08:58:45 CET 2017 on sn-devel-144
Diffstat (limited to 'ctdb')
-rw-r--r--ctdb/common/sock_daemon.c68
-rw-r--r--ctdb/common/sock_daemon.h11
-rw-r--r--ctdb/tests/src/sock_daemon_test.c40
3 files changed, 110 insertions, 9 deletions
diff --git a/ctdb/common/sock_daemon.c b/ctdb/common/sock_daemon.c
index ce6f9230a6d..7554cd6da07 100644
--- a/ctdb/common/sock_daemon.c
+++ b/ctdb/common/sock_daemon.c
@@ -524,6 +524,7 @@ struct sock_daemon_run_state {
pid_t pid_watch;
int fd;
+ int exit_code;
};
static void sock_daemon_run_started(struct tevent_req *subreq);
@@ -535,6 +536,8 @@ static void sock_daemon_run_signal_handler(struct tevent_context *ev,
static void sock_daemon_run_reconfigure(struct tevent_req *req);
static void sock_daemon_run_reconfigure_done(struct tevent_req *subreq);
static void sock_daemon_run_shutdown(struct tevent_req *req);
+static void sock_daemon_run_shutdown_done(struct tevent_req *subreq);
+static void sock_daemon_run_exit(struct tevent_req *req);
static bool sock_daemon_run_socket_listen(struct tevent_req *req);
static void sock_daemon_run_socket_fail(struct tevent_req *subreq);
static void sock_daemon_run_watch_pid(struct tevent_req *subreq);
@@ -702,6 +705,8 @@ static void sock_daemon_run_signal_handler(struct tevent_context *ev,
{
struct tevent_req *req = talloc_get_type_abort(
private_data, struct tevent_req);
+ struct sock_daemon_run_state *state = tevent_req_data(
+ req, struct sock_daemon_run_state);
D_NOTICE("Received signal %d\n", signum);
@@ -711,8 +716,8 @@ static void sock_daemon_run_signal_handler(struct tevent_context *ev,
}
if (signum == SIGINT || signum == SIGTERM) {
+ state->exit_code = EINTR;
sock_daemon_run_shutdown(req);
- tevent_req_error(req, EINTR);
}
}
@@ -770,6 +775,7 @@ static void sock_daemon_run_reconfigure_done(struct tevent_req *subreq)
static void sock_daemon_run_shutdown(struct tevent_req *req)
{
+ struct tevent_req *subreq;
struct sock_daemon_run_state *state = tevent_req_data(
req, struct sock_daemon_run_state);
struct sock_daemon_context *sockd = state->sockd;
@@ -782,11 +788,53 @@ static void sock_daemon_run_shutdown(struct tevent_req *req)
TALLOC_FREE(sock);
}
+ if (sockd->funcs != NULL && sockd->funcs->shutdown_send != NULL &&
+ sockd->funcs->shutdown_recv != NULL) {
+ subreq = sockd->funcs->shutdown_send(state, state->ev,
+ sockd->private_data);
+ if (subreq == NULL) {
+ sock_daemon_run_exit(req);
+ return;
+ }
+ tevent_req_set_callback(subreq, sock_daemon_run_shutdown_done,
+ req);
+ return;
+ }
+
if (sockd->funcs != NULL && sockd->funcs->shutdown != NULL) {
sockd->funcs->shutdown(sockd->private_data);
}
+ sock_daemon_run_exit(req);
+}
+
+static void sock_daemon_run_shutdown_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct sock_daemon_run_state *state = tevent_req_data(
+ req, struct sock_daemon_run_state);
+ struct sock_daemon_context *sockd = state->sockd;
+
+ sockd->funcs->shutdown_recv(subreq);
+ TALLOC_FREE(subreq);
+
+ sock_daemon_run_exit(req);
+}
+
+static void sock_daemon_run_exit(struct tevent_req *req)
+{
+ struct sock_daemon_run_state *state = tevent_req_data(
+ req, struct sock_daemon_run_state);
+ struct sock_daemon_context *sockd = state->sockd;
+
TALLOC_FREE(sockd->pid_ctx);
+
+ if (state->exit_code == 0) {
+ tevent_req_done(req);
+ } else {
+ tevent_req_error(req, state->exit_code);
+ }
}
static bool sock_daemon_run_socket_listen(struct tevent_req *req)
@@ -826,13 +874,14 @@ static void sock_daemon_run_socket_fail(struct tevent_req *subreq)
status = sock_socket_start_recv(subreq, &ret, state, &sockpath);
TALLOC_FREE(subreq);
- sock_daemon_run_shutdown(req);
if (! status) {
D_ERR("socket %s closed unexpectedly\n", sockpath);
- tevent_req_error(req, ret);
+ state->exit_code = ret;
} else {
- tevent_req_done(req);
+ state->exit_code = 0;
}
+
+ sock_daemon_run_shutdown(req);
}
static void sock_daemon_run_watch_pid(struct tevent_req *subreq)
@@ -855,8 +904,8 @@ static void sock_daemon_run_watch_pid(struct tevent_req *subreq)
if (ret == -1) {
if (errno == ESRCH) {
D_ERR("PID %d gone away, exiting\n", state->pid_watch);
+ state->exit_code = ESRCH;
sock_daemon_run_shutdown(req);
- tevent_req_error(req, ESRCH);
return;
} else {
D_ERR("Failed to check PID status %d, ret=%d\n",
@@ -898,17 +947,18 @@ static void sock_daemon_run_wait_done(struct tevent_req *subreq)
struct sock_daemon_run_state *state = tevent_req_data(
req, struct sock_daemon_run_state);
struct sock_daemon_context *sockd = state->sockd;
- int ret;
+ int ret = 0;
bool status;
status = sockd->funcs->wait_recv(subreq, &ret);
TALLOC_FREE(subreq);
- sock_daemon_run_shutdown(req);
if (! status) {
- tevent_req_error(req, ret);
+ state->exit_code = ret;
} else {
- tevent_req_done(req);
+ state->exit_code = 0;
}
+
+ sock_daemon_run_shutdown(req);
}
bool sock_daemon_run_recv(struct tevent_req *req, int *perr)
diff --git a/ctdb/common/sock_daemon.h b/ctdb/common/sock_daemon.h
index 2cc94c6bf5d..a071833c2f3 100644
--- a/ctdb/common/sock_daemon.h
+++ b/ctdb/common/sock_daemon.h
@@ -63,6 +63,12 @@ struct sock_client_context;
* shutdown() is called when process receives SIGINT or SIGTERM or
* when wait computation has finished
*
+ * shutdown_send()/shutdown_recv() is the async version of shutdown()
+ *
+ * Please note that only one (sync or async) version of these functions
+ * will be called. If both versions are defined, then only async function
+ * will be called.
+ *
* wait_send() starts the async computation to keep running the daemon
* wait_recv() ends the async computation to keep running the daemon
*
@@ -86,6 +92,11 @@ struct sock_daemon_funcs {
void (*shutdown)(void *private_data);
+ struct tevent_req * (*shutdown_send)(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ void *private_data);
+ void (*shutdown_recv)(struct tevent_req *req);
+
struct tevent_req * (*wait_send)(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
void *private_data);
diff --git a/ctdb/tests/src/sock_daemon_test.c b/ctdb/tests/src/sock_daemon_test.c
index 05a5748fa6d..505ff78e768 100644
--- a/ctdb/tests/src/sock_daemon_test.c
+++ b/ctdb/tests/src/sock_daemon_test.c
@@ -297,6 +297,40 @@ static void test2_shutdown(void *private_data)
assert(nwritten == sizeof(ret));
}
+struct test2_shutdown_state {
+ int fd;
+};
+
+static struct tevent_req *test2_shutdown_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ void *private_data)
+{
+ struct tevent_req *req;
+ struct test2_shutdown_state *state;
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct test2_shutdown_state);
+ if (req == NULL) {
+ return NULL;
+ }
+
+ state->fd = *(int *)private_data;
+
+ tevent_req_done(req);
+ return tevent_req_post(req, ev);
+}
+
+static void test2_shutdown_recv(struct tevent_req *req)
+{
+ struct test2_shutdown_state *state = tevent_req_data(
+ req, struct test2_shutdown_state);
+ int ret = 3;
+ ssize_t nwritten;
+
+ nwritten = write(state->fd, &ret, sizeof(ret));
+ assert(nwritten == sizeof(ret));
+}
+
static void test2(TALLOC_CTX *mem_ctx, const char *pidfile,
const char *sockpath)
{
@@ -405,6 +439,8 @@ static void test2(TALLOC_CTX *mem_ctx, const char *pidfile,
.startup = test2_startup,
.reconfigure_send = test2_reconfigure_send,
.reconfigure_recv = test2_reconfigure_recv,
+ .shutdown_send = test2_shutdown_send,
+ .shutdown_recv = test2_shutdown_recv,
};
close(fd[0]);
@@ -449,6 +485,10 @@ static void test2(TALLOC_CTX *mem_ctx, const char *pidfile,
ret = kill(pid, SIGTERM);
assert(ret == 0);
+ n = read(fd[0], &ret, sizeof(ret));
+ assert(n == sizeof(ret));
+ assert(ret == 3);
+
pid2 = waitpid(pid, &ret, 0);
assert(pid2 == pid);
assert(WEXITSTATUS(ret) == 0);