summaryrefslogtreecommitdiff
path: root/source3
diff options
context:
space:
mode:
authorRalph Boehme <slow@samba.org>2016-07-14 16:31:44 +0200
committerStefan Metzmacher <metze@samba.org>2016-07-28 05:00:18 +0200
commitda61c970587a131a9754ad642a784467d403fabd (patch)
treed4c4c1049bc649344b860855248f90fdfc5eae40 /source3
parent9c1cd31c0f931b99d79638fbef5e46f01788f3ca (diff)
downloadsamba-da61c970587a131a9754ad642a784467d403fabd.tar.gz
s3/smbd: add cleanupd_init_send()/recv()
Previously, without this patch, if cleanupd died for whatever reason, it would be restarted from smbd. However, if cleanupd 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')
-rw-r--r--source3/smbd/server.c108
1 files changed, 105 insertions, 3 deletions
diff --git a/source3/smbd/server.c b/source3/smbd/server.c
index 9e3c652e16e..a2ac77e638a 100644
--- a/source3/smbd/server.c
+++ b/source3/smbd/server.c
@@ -542,6 +542,89 @@ static void cleanupd_stopped(struct tevent_req *req)
DBG_WARNING("cleanupd stopped: %s\n", nt_errstr(status));
}
+static void cleanupd_init_trigger(struct tevent_req *req);
+
+struct cleanup_init_state {
+ bool ok;
+ struct tevent_context *ev;
+ struct messaging_context *msg;
+ struct server_id *ppid;
+};
+
+static struct tevent_req *cleanupd_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 cleanup_init_state *state = NULL;
+
+ req = tevent_req_create(mem_ctx, &state, struct cleanup_init_state);
+ if (req == NULL) {
+ return NULL;
+ }
+
+ *state = (struct cleanup_init_state) {
+ .msg = msg,
+ .ev = ev,
+ .ppid = ppid
+ };
+
+ subreq = tevent_wakeup_send(req, ev, tevent_timeval_current_ofs(0, 0));
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+
+ tevent_req_set_callback(subreq, cleanupd_init_trigger, req);
+ return req;
+}
+
+static void cleanupd_init_trigger(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct cleanup_init_state *state = tevent_req_data(
+ req, struct cleanup_init_state);
+ bool ok;
+
+ DBG_NOTICE("Triggering cleanupd startup\n");
+
+ ok = tevent_wakeup_recv(subreq);
+ TALLOC_FREE(subreq);
+ if (!ok) {
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+
+ state->ok = cleanupd_init(state->msg, false, state->ppid);
+ if (state->ok) {
+ DBG_WARNING("cleanupd restarted\n");
+ tevent_req_done(req);
+ return;
+ }
+
+ DBG_NOTICE("cleanupd 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 cleanupd restart failed, giving up\n");
+ return;
+ }
+
+ tevent_req_set_callback(subreq, cleanupd_init_trigger, req);
+ return;
+}
+
+static bool cleanupd_init_recv(struct tevent_req *req)
+{
+ struct cleanup_init_state *state = tevent_req_data(
+ req, struct cleanup_init_state);
+
+ return state->ok;
+}
+
/*
at most every smbd:cleanuptime seconds (default 20), we scan the BRL
and locking database for entries to cleanup. As a side effect this
@@ -568,6 +651,18 @@ static void cleanup_timeout_fn(struct tevent_context *event_ctx,
MSG_SMB_UNLOCK, NULL, 0);
}
+static void cleanupd_started(struct tevent_req *req)
+{
+ bool ok;
+
+ ok = cleanupd_init_recv(req);
+ TALLOC_FREE(req);
+ if (!ok) {
+ DBG_ERR("Failed to restart cleanupd, giving up\n");
+ return;
+ }
+}
+
static void remove_child_pid(struct smbd_parent_context *parent,
pid_t pid,
bool unclean_shutdown)
@@ -593,13 +688,20 @@ static void remove_child_pid(struct smbd_parent_context *parent,
}
if (pid == procid_to_pid(&parent->cleanupd)) {
- bool ok;
+ struct tevent_req *req;
+
+ server_id_set_disconnected(&parent->cleanupd);
DBG_WARNING("Restarting cleanupd\n");
- ok = cleanupd_init(parent->msg_ctx, false, &parent->cleanupd);
- if (!ok) {
+ req = cleanupd_init_send(messaging_tevent_context(parent->msg_ctx),
+ parent,
+ parent->msg_ctx,
+ &parent->cleanupd);
+ if (req == NULL) {
DBG_ERR("Failed to restart cleanupd\n");
+ return;
}
+ tevent_req_set_callback(req, cleanupd_started, parent);
return;
}