diff options
author | Ralph Boehme <slow@samba.org> | 2016-07-22 08:29:13 +0200 |
---|---|---|
committer | Stefan Metzmacher <metze@samba.org> | 2016-07-28 05:00:19 +0200 |
commit | 41875c8eab6fe8750c2ddd58df1389f0de88f8ed (patch) | |
tree | 535b4fd916d7a575d19ab28fbd051ce78a484d83 /source3/smbd/server.c | |
parent | 4652a8b911b4c79ca579ab0503bb766548411e2b (diff) | |
download | samba-41875c8eab6fe8750c2ddd58df1389f0de88f8ed.tar.gz |
s3/notifyd: add async send/recv functions
Previously, without this patch, if notifyd died for whatever reason, it
would be restarted from smbd. However, if its initialization failed and
it exitted again, there would be no child entry in smbd for it and it
wouldn't be attempted to restart it again.
This patch adds async send/recv methods for starting cleanupd that will
reschedule restart attempt every second in case initilisation failed.
Bug: https://bugzilla.samba.org/show_bug.cgi?id=12022
Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Volker Lendecke <vl@samba.org>
Diffstat (limited to 'source3/smbd/server.c')
-rw-r--r-- | source3/smbd/server.c | 111 |
1 files changed, 108 insertions, 3 deletions
diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 2e005e6dbba..97c0fdcad92 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -427,6 +427,101 @@ static bool smbd_notifyd_init(struct messaging_context *msg, bool interactive, return tevent_req_poll(req, ev); } +static void notifyd_init_trigger(struct tevent_req *req); + +struct notifyd_init_state { + bool ok; + struct tevent_context *ev; + struct messaging_context *msg; + struct server_id *ppid; +}; + +static struct tevent_req *notifyd_init_send(struct tevent_context *ev, + TALLOC_CTX *mem_ctx, + struct messaging_context *msg, + struct server_id *ppid) +{ + struct tevent_req *req = NULL; + struct tevent_req *subreq = NULL; + struct notifyd_init_state *state = NULL; + + req = tevent_req_create(mem_ctx, &state, struct notifyd_init_state); + if (req == NULL) { + return NULL; + } + + *state = (struct notifyd_init_state) { + .msg = msg, + .ev = ev, + .ppid = ppid + }; + + subreq = tevent_wakeup_send(req, ev, tevent_timeval_current_ofs(1, 0)); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + + tevent_req_set_callback(subreq, notifyd_init_trigger, req); + return req; +} + +static void notifyd_init_trigger(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct notifyd_init_state *state = tevent_req_data( + req, struct notifyd_init_state); + bool ok; + + DBG_NOTICE("Triggering notifyd startup\n"); + + ok = tevent_wakeup_recv(subreq); + TALLOC_FREE(subreq); + if (!ok) { + tevent_req_error(req, ENOMEM); + return; + } + + state->ok = smbd_notifyd_init(state->msg, false, state->ppid); + if (state->ok) { + DBG_WARNING("notifyd restarted\n"); + tevent_req_done(req); + return; + } + + DBG_NOTICE("notifyd startup failed, rescheduling\n"); + + subreq = tevent_wakeup_send(req, state->ev, + tevent_timeval_current_ofs(1, 0)); + if (tevent_req_nomem(subreq, req)) { + DBG_ERR("scheduling notifyd restart failed, giving up\n"); + return; + } + + tevent_req_set_callback(subreq, notifyd_init_trigger, req); + return; +} + +static bool notifyd_init_recv(struct tevent_req *req) +{ + struct notifyd_init_state *state = tevent_req_data( + req, struct notifyd_init_state); + + return state->ok; +} + +static void notifyd_started(struct tevent_req *req) +{ + bool ok; + + ok = notifyd_init_recv(req); + TALLOC_FREE(req); + if (!ok) { + DBG_ERR("Failed to restart notifyd, giving up\n"); + return; + } +} + static void cleanupd_stopped(struct tevent_req *req); static bool cleanupd_init(struct messaging_context *msg, bool interactive, @@ -719,12 +814,22 @@ static void remove_child_pid(struct smbd_parent_context *parent, } if (pid == procid_to_pid(&parent->notifyd)) { + struct tevent_req *req; + struct tevent_context *ev = messaging_tevent_context( + parent->msg_ctx); + + server_id_set_disconnected(&parent->notifyd); + DBG_WARNING("Restarting notifyd\n"); - ok = smbd_notifyd_init(parent->msg_ctx, false, - &parent->notifyd); - if (!ok) { + req = notifyd_init_send(ev, + parent, + parent->msg_ctx, + &parent->notifyd); + if (req == NULL) { DBG_ERR("Failed to restart notifyd\n"); + return; } + tevent_req_set_callback(req, notifyd_started, parent); return; } |