The branch, master has been updated via ed722c3 ctdb-common: Add wait_send/wait_recv to sock_daemon_funcs via d09469e ctdb-common: Avoid any processing after finishing tevent_req via d5be557 ctdb-common: Pass tevent_req to the computation sub-functions via 31274cf ctdb-common: Use consistent naming for sock_daemon_run computation functions via 9e09a25 ctdb-common: Correct name of sock_daemon_run_send/recv state structure from ff0d45c ctdb-tests: Fix name of the variable representing init script
https://git.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit ed722c3aa9690873af495cb467dd440c1a714d82 Author: Amitay Isaacs <ami...@gmail.com> Date: Wed Jan 11 20:37:00 2017 +1100 ctdb-common: Add wait_send/wait_recv to sock_daemon_funcs BUG: https://bugzilla.samba.org/show_bug.cgi?id=12510 To be able to terminate the daemon from within the implementation, create a subreq using wait_send() provided by the implementation. When the subreq is finished, it signals the sock_daemon code to terminate the daemon. This avoids the need to keep track of the top level tevent_req causing layer violation and keeps the code flow straighforward. Signed-off-by: Amitay Isaacs <ami...@gmail.com> Reviewed-by: Stefan Metzmacher <me...@samba.org> Autobuild-User(master): Stefan Metzmacher <me...@samba.org> Autobuild-Date(master): Mon Jan 16 21:16:51 CET 2017 on sn-devel-144 commit d09469e575233242eab2a8c1c0767f52e7cad1e5 Author: Amitay Isaacs <ami...@gmail.com> Date: Wed Jan 11 19:54:36 2017 +1100 ctdb-common: Avoid any processing after finishing tevent_req BUG: https://bugzilla.samba.org/show_bug.cgi?id=12510 Signed-off-by: Amitay Isaacs <ami...@gmail.com> Reviewed-by: Stefan Metzmacher <me...@samba.org> commit d5be55725000eb34611dc76a2e8e7188eea2503f Author: Amitay Isaacs <ami...@gmail.com> Date: Fri Jan 13 10:43:44 2017 +1100 ctdb-common: Pass tevent_req to the computation sub-functions BUG: https://bugzilla.samba.org/show_bug.cgi?id=12510 Signed-off-by: Amitay Isaacs <ami...@gmail.com> Reviewed-by: Stefan Metzmacher <me...@samba.org> commit 31274cf7aec1bb26e8dac0dbd1b9a3fa799b2b85 Author: Amitay Isaacs <ami...@gmail.com> Date: Fri Jan 13 10:40:43 2017 +1100 ctdb-common: Use consistent naming for sock_daemon_run computation functions BUG: https://bugzilla.samba.org/show_bug.cgi?id=12510 Signed-off-by: Amitay Isaacs <ami...@gmail.com> Reviewed-by: Stefan Metzmacher <me...@samba.org> commit 9e09a253b4ca1b5f9aa432c986c1755a173a9566 Author: Amitay Isaacs <ami...@gmail.com> Date: Wed Jan 11 19:50:34 2017 +1100 ctdb-common: Correct name of sock_daemon_run_send/recv state structure BUG: https://bugzilla.samba.org/show_bug.cgi?id=12510 Signed-off-by: Amitay Isaacs <ami...@gmail.com> Reviewed-by: Stefan Metzmacher <me...@samba.org> ----------------------------------------------------------------------- Summary of changes: ctdb/common/sock_daemon.c | 132 +++++++++++++---------- ctdb/common/sock_daemon.h | 14 ++- ctdb/tests/cunit/sock_daemon_test_001.sh | 2 + ctdb/tests/src/sock_daemon_test.c | 175 ++++++++++++++++++++++++------- 4 files changed, 226 insertions(+), 97 deletions(-) Changeset truncated at 500 lines: diff --git a/ctdb/common/sock_daemon.c b/ctdb/common/sock_daemon.c index ca4086d..b53b4d8 100644 --- a/ctdb/common/sock_daemon.c +++ b/ctdb/common/sock_daemon.c @@ -70,7 +70,6 @@ struct sock_daemon_context { struct pidfile_context *pid_ctx; struct sock_socket *socket_list; - struct tevent_req *req; }; /* @@ -451,8 +450,6 @@ bool sock_socket_write_recv(struct tevent_req *req, int *perr) * Socket daemon */ -static int sock_daemon_context_destructor(struct sock_daemon_context *sockd); - int sock_daemon_setup(TALLOC_CTX *mem_ctx, const char *daemon_name, const char *logging, const char *debug_level, const char *pidfile, @@ -487,21 +484,10 @@ int sock_daemon_setup(TALLOC_CTX *mem_ctx, const char *daemon_name, } } - talloc_set_destructor(sockd, sock_daemon_context_destructor); - *out = sockd; return 0; } -static int sock_daemon_context_destructor(struct sock_daemon_context *sockd) -{ - if (sockd->req != NULL) { - tevent_req_done(sockd->req); - } - - return 0; -} - int sock_daemon_add_unix(struct sock_daemon_context *sockd, const char *sockpath, struct sock_socket_funcs *funcs, @@ -529,7 +515,7 @@ int sock_daemon_add_unix(struct sock_daemon_context *sockd, * Run socket daemon */ -struct sock_daemon_start_state { +struct sock_daemon_run_state { struct tevent_context *ev; struct sock_daemon_context *sockd; pid_t pid_watch; @@ -537,15 +523,16 @@ struct sock_daemon_start_state { int fd; }; -static void sock_daemon_started(struct tevent_req *subreq); -static void sock_daemon_signal_handler(struct tevent_context *ev, - struct tevent_signal *se, - int signum, int count, void *siginfo, - void *private_data); -static void sock_daemon_socket_fail(struct tevent_req *subreq); -static void sock_daemon_watch_pid(struct tevent_req *subreq); -static void sock_daemon_reconfigure(struct sock_daemon_start_state *state); -static void sock_daemon_shutdown(struct sock_daemon_start_state *state); +static void sock_daemon_run_started(struct tevent_req *subreq); +static void sock_daemon_run_signal_handler(struct tevent_context *ev, + struct tevent_signal *se, + int signum, int count, void *siginfo, + void *private_data); +static void sock_daemon_run_reconfigure(struct tevent_req *req); +static void sock_daemon_run_shutdown(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); +static void sock_daemon_run_wait_done(struct tevent_req *subreq); struct tevent_req *sock_daemon_run_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, @@ -553,12 +540,12 @@ struct tevent_req *sock_daemon_run_send(TALLOC_CTX *mem_ctx, pid_t pid_watch) { struct tevent_req *req, *subreq; - struct sock_daemon_start_state *state; + struct sock_daemon_run_state *state; struct tevent_signal *se; struct sock_socket *sock; req = tevent_req_create(mem_ctx, &state, - struct sock_daemon_start_state); + struct sock_daemon_run_state); if (req == NULL) { return NULL; } @@ -573,28 +560,28 @@ struct tevent_req *sock_daemon_run_send(TALLOC_CTX *mem_ctx, if (tevent_req_nomem(subreq, req)) { return tevent_req_post(req, ev); } - tevent_req_set_callback(subreq, sock_daemon_started, req); + tevent_req_set_callback(subreq, sock_daemon_run_started, req); se = tevent_add_signal(ev, state, SIGHUP, 0, - sock_daemon_signal_handler, req); + sock_daemon_run_signal_handler, req); if (tevent_req_nomem(se, req)) { return tevent_req_post(req, ev); } se = tevent_add_signal(ev, state, SIGUSR1, 0, - sock_daemon_signal_handler, req); + sock_daemon_run_signal_handler, req); if (tevent_req_nomem(se, req)) { return tevent_req_post(req, ev); } se = tevent_add_signal(ev, state, SIGINT, 0, - sock_daemon_signal_handler, req); + sock_daemon_run_signal_handler, req); if (tevent_req_nomem(se, req)) { return tevent_req_post(req, ev); } se = tevent_add_signal(ev, state, SIGTERM, 0, - sock_daemon_signal_handler, req); + sock_daemon_run_signal_handler, req); if (tevent_req_nomem(se, req)) { return tevent_req_post(req, ev); } @@ -604,7 +591,8 @@ struct tevent_req *sock_daemon_run_send(TALLOC_CTX *mem_ctx, if (tevent_req_nomem(subreq, req)) { return tevent_req_post(req, ev); } - tevent_req_set_callback(subreq, sock_daemon_socket_fail, req); + tevent_req_set_callback(subreq, sock_daemon_run_socket_fail, + req); sock->req = subreq; } @@ -615,20 +603,30 @@ struct tevent_req *sock_daemon_run_send(TALLOC_CTX *mem_ctx, if (tevent_req_nomem(subreq, req)) { return tevent_req_post(req, ev); } - tevent_req_set_callback(subreq, sock_daemon_watch_pid, req); + tevent_req_set_callback(subreq, sock_daemon_run_watch_pid, + req); } - sockd->req = req; + if (sockd->funcs != NULL && sockd->funcs->wait_send != NULL && + sockd->funcs->wait_recv != NULL) { + subreq = sockd->funcs->wait_send(state, ev, + sockd->private_data); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, sock_daemon_run_wait_done, + req); + } return req; } -static void sock_daemon_started(struct tevent_req *subreq) +static void sock_daemon_run_started(struct tevent_req *subreq) { struct tevent_req *req = tevent_req_callback_data( subreq, struct tevent_req); - struct sock_daemon_start_state *state = tevent_req_data( - req, struct sock_daemon_start_state); + struct sock_daemon_run_state *state = tevent_req_data( + req, struct sock_daemon_run_state); struct sock_daemon_context *sockd = state->sockd; D_NOTICE("daemon started, pid=%u\n", getpid()); @@ -638,31 +636,31 @@ static void sock_daemon_started(struct tevent_req *subreq) } } -static void sock_daemon_signal_handler(struct tevent_context *ev, - struct tevent_signal *se, - int signum, int count, void *siginfo, - void *private_data) +static void sock_daemon_run_signal_handler(struct tevent_context *ev, + struct tevent_signal *se, + int signum, int count, void *siginfo, + void *private_data) { struct tevent_req *req = talloc_get_type_abort( private_data, struct tevent_req); - struct sock_daemon_start_state *state = tevent_req_data( - req, struct sock_daemon_start_state); D_NOTICE("Received signal %d\n", signum); if (signum == SIGHUP || signum == SIGUSR1) { - sock_daemon_reconfigure(state); + sock_daemon_run_reconfigure(req); return; } if (signum == SIGINT || signum == SIGTERM) { - sock_daemon_shutdown(state); + sock_daemon_run_shutdown(req); tevent_req_error(req, EINTR); } } -static void sock_daemon_reconfigure(struct sock_daemon_start_state *state) +static void sock_daemon_run_reconfigure(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; if (sockd->funcs != NULL && sockd->funcs->reconfigure != NULL) { @@ -670,8 +668,10 @@ static void sock_daemon_reconfigure(struct sock_daemon_start_state *state) } } -static void sock_daemon_shutdown(struct sock_daemon_start_state *state) +static void sock_daemon_run_shutdown(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; struct sock_socket *sock; @@ -690,32 +690,29 @@ static void sock_daemon_shutdown(struct sock_daemon_start_state *state) TALLOC_FREE(sockd->pid_ctx); } -static void sock_daemon_socket_fail(struct tevent_req *subreq) +static void sock_daemon_run_socket_fail(struct tevent_req *subreq) { struct tevent_req *req = tevent_req_callback_data( subreq, struct tevent_req); - struct sock_daemon_start_state *state = tevent_req_data( - req, struct sock_daemon_start_state); int ret = 0; bool status; status = sock_socket_start_recv(subreq, &ret); TALLOC_FREE(subreq); + sock_daemon_run_shutdown(req); if (! status) { tevent_req_error(req, ret); } else { tevent_req_done(req); } - - sock_daemon_shutdown(state); } -static void sock_daemon_watch_pid(struct tevent_req *subreq) +static void sock_daemon_run_watch_pid(struct tevent_req *subreq) { struct tevent_req *req = tevent_req_callback_data( subreq, struct tevent_req); - struct sock_daemon_start_state *state = tevent_req_data( - req, struct sock_daemon_start_state); + struct sock_daemon_run_state *state = tevent_req_data( + req, struct sock_daemon_run_state); int ret; bool status; @@ -730,7 +727,7 @@ static void sock_daemon_watch_pid(struct tevent_req *subreq) if (ret == -1) { if (errno == ESRCH) { D_ERR("PID %d gone away, exiting\n", state->pid_watch); - sock_daemon_shutdown(state); + sock_daemon_run_shutdown(req); tevent_req_error(req, ESRCH); return; } else { @@ -744,7 +741,27 @@ static void sock_daemon_watch_pid(struct tevent_req *subreq) if (tevent_req_nomem(subreq, req)) { return; } - tevent_req_set_callback(subreq, sock_daemon_watch_pid, req); + tevent_req_set_callback(subreq, sock_daemon_run_watch_pid, req); +} + +static void sock_daemon_run_wait_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; + int ret; + bool status; + + status = sockd->funcs->wait_recv(subreq, &ret); + TALLOC_FREE(subreq); + sock_daemon_run_shutdown(req); + if (! status) { + tevent_req_error(req, ret); + } else { + tevent_req_done(req); + } } bool sock_daemon_run_recv(struct tevent_req *req, int *perr) @@ -777,7 +794,6 @@ int sock_daemon_run(struct tevent_context *ev, tevent_req_poll(req, ev); status = sock_daemon_run_recv(req, &ret); - sockd->req = NULL; TALLOC_FREE(req); if (! status) { return ret; diff --git a/ctdb/common/sock_daemon.h b/ctdb/common/sock_daemon.h index 6c474ac..81853f6 100644 --- a/ctdb/common/sock_daemon.h +++ b/ctdb/common/sock_daemon.h @@ -50,12 +50,24 @@ struct sock_client_context; * startup() is called when the daemon starts running * either via sock_daemon_run() or via sock_daemon_run_send() * reconfigure() is called when process receives SIGUSR1 or SIGHUP - * shutdown() is called when process receives SIGINT or SIGTERM + * shutdown() is called when process receives SIGINT or SIGTERM or + * when wait computation has finished + * + * wait_send() starts the async computation to keep running the daemon + * wait_recv() ends the async computation to keep running the daemon + * + * If wait_send()/wait_recv() is NULL, then daemon will keep running forever. + * If wait_send() returns req, then when req is over, daemon will shutdown. */ struct sock_daemon_funcs { void (*startup)(void *private_data); void (*reconfigure)(void *private_data); void (*shutdown)(void *private_data); + + struct tevent_req * (*wait_send)(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + void *private_data); + bool (*wait_recv)(struct tevent_req *req, int *perr); }; /** diff --git a/ctdb/tests/cunit/sock_daemon_test_001.sh b/ctdb/tests/cunit/sock_daemon_test_001.sh index 036b6ac..72e5532 100755 --- a/ctdb/tests/cunit/sock_daemon_test_001.sh +++ b/ctdb/tests/cunit/sock_daemon_test_001.sh @@ -47,6 +47,7 @@ unit_test sock_daemon_test "$pidfile" "$sockpath" 3 ok <<EOF test4[PID]: daemon started, pid=PID +test4[PID]: Shutting down EOF unit_test sock_daemon_test "$pidfile" "$sockpath" 4 @@ -61,5 +62,6 @@ unit_test sock_daemon_test "$pidfile" "$sockpath" 5 ok <<EOF test6[PID]: listening on $sockpath test6[PID]: daemon started, pid=PID +test6[PID]: Shutting down EOF unit_test sock_daemon_test "$pidfile" "$sockpath" 6 diff --git a/ctdb/tests/src/sock_daemon_test.c b/ctdb/tests/src/sock_daemon_test.c index 4a085c0..278dcab 100644 --- a/ctdb/tests/src/sock_daemon_test.c +++ b/ctdb/tests/src/sock_daemon_test.c @@ -254,17 +254,68 @@ static void test3(TALLOC_CTX *mem_ctx, const char *pidfile, assert(ret == -1); } -static void test4_handler(struct tevent_context *ev, - struct tevent_timer *te, - struct timeval curtime, - void *private_data) +struct test4_wait_state { +}; + +static void test4_wait_done(struct tevent_req *subreq); + +static struct tevent_req *test4_wait_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + void *private_data) { - struct sock_daemon_context *sockd = talloc_get_type_abort( - private_data, struct sock_daemon_context); + struct tevent_req *req, *subreq; + struct test4_wait_state *state; - talloc_free(sockd); + req = tevent_req_create(mem_ctx, &state, struct test4_wait_state); + if (req == NULL) { + return NULL; + } + + subreq = tevent_wakeup_send(state, ev, + tevent_timeval_current_ofs(10,0)); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, test4_wait_done, req); + + return req; } +static void test4_wait_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + bool status; + + status = tevent_wakeup_recv(subreq); + TALLOC_FREE(subreq); + + if (! status) { + tevent_req_error(req, EIO); + } else { + tevent_req_done(req); + } +} + +static bool test4_wait_recv(struct tevent_req *req, int *perr) +{ + int ret; + + if (tevent_req_is_unix_error(req, &ret)) { + if (perr != NULL) { + *perr = ret; + } + return false; + } + + return true; +} + +static struct sock_daemon_funcs test4_funcs = { + .wait_send = test4_wait_send, + .wait_recv = test4_wait_recv, +}; + static void test4(TALLOC_CTX *mem_ctx, const char *pidfile, const char *sockpath) { @@ -278,19 +329,14 @@ static void test4(TALLOC_CTX *mem_ctx, const char *pidfile, if (pid == 0) { struct tevent_context *ev; struct sock_daemon_context *sockd; - struct tevent_timer *te; ev = tevent_context_init(mem_ctx); assert(ev != NULL); ret = sock_daemon_setup(mem_ctx, "test4", "file:", "NOTICE", - NULL, NULL, NULL, &sockd); + pidfile, &test4_funcs, NULL, &sockd); assert(ret == 0); - te = tevent_add_timer(ev, ev, tevent_timeval_current_ofs(10,0), - test4_handler, sockd); - assert(te != NULL); - ret = sock_daemon_run(ev, sockd, -1); assert(ret == 0); @@ -666,7 +712,7 @@ static void test6_client(const char *sockpath) struct test6_server_state { struct sock_daemon_context *sockd; - int done; + int fd, done; }; struct test6_read_state { @@ -752,35 +798,90 @@ static struct sock_socket_funcs test6_client_funcs = { static void test6_startup(void *private_data) { - int fd = *(int *)private_data; + struct test6_server_state *server_state = + (struct test6_server_state *)private_data; int ret = 1; ssize_t nwritten; - nwritten = write(fd, &ret, sizeof(ret)); + nwritten = write(server_state->fd, &ret, sizeof(ret)); assert(nwritten == sizeof(ret)); - close(fd); + close(server_state->fd); + server_state->fd = -1; } -static struct sock_daemon_funcs test6_funcs = { - .startup = test6_startup, +struct test6_wait_state { + struct test6_server_state *server_state; }; -static void test6_handler(struct tevent_context *ev, - struct tevent_timer *te, - struct timeval curtime, - void *private_data) +static void test6_wait_done(struct tevent_req *subreq); + +static struct tevent_req *test6_wait_send(TALLOC_CTX *mem_ctx, -- Samba Shared Repository