summaryrefslogtreecommitdiff
path: root/source3
diff options
context:
space:
mode:
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;
}