From 0a910c93472e1e4aff120219e09866d4a20ec2b2 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 16 May 2011 10:46:35 -0400 Subject: s3-prefork: Provide a cleanup function This way the parent doesn't need to know how to handle dead children and keeps all of that within the prefork abstraction. Signed-off-by: Andreas Schneider --- source3/lib/server_prefork.c | 26 +++++++++++++++++--------- source3/lib/server_prefork.h | 12 ++++-------- source3/printing/spoolssd.c | 15 ++++----------- 3 files changed, 25 insertions(+), 28 deletions(-) (limited to 'source3') diff --git a/source3/lib/server_prefork.c b/source3/lib/server_prefork.c index 211a54b95b..ef76a55486 100644 --- a/source3/lib/server_prefork.c +++ b/source3/lib/server_prefork.c @@ -291,29 +291,37 @@ int prefork_count_active_children(struct prefork_pool *pfp, int *total) return a; } -/* to be used to finally mark a children as dead, so that it's slot can - * be reused */ -bool prefork_mark_pid_dead(struct prefork_pool *pfp, pid_t pid) +void prefork_cleanup_loop(struct prefork_pool *pfp) { + int status; + pid_t pid; int i; + /* TODO: should we use a process group id wait instead of looping ? */ for (i = 0; i < pfp->pool_size; i++) { - if (pfp->pool[i].pid == pid) { + if (pfp->pool[i].status == PF_WORKER_NONE || + pfp->pool[i].pid == 0) { + continue; + } + + pid = sys_waitpid(pfp->pool[i].pid, &status, WNOHANG); + if (pid > 0) { + if (pfp->pool[i].status != PF_WORKER_EXITING) { - DEBUG(2, ("pid %d terminated abnormally!\n", - (int)pid)); + DEBUG(3, ("Child (%d) terminated abnormally:" + " %d\n", (int)pid, status)); + } else { + DEBUG(10, ("Child (%d) terminated with status:" + " %d\n", (int)pid, status)); } /* reset all fields, * this makes status = PF_WORK_NONE */ memset(&pfp->pool[i], 0, sizeof(struct pf_worker_data)); - - return true; } } - return false; } void prefork_increase_allowed_clients(struct prefork_pool *pfp, int max) diff --git a/source3/lib/server_prefork.h b/source3/lib/server_prefork.h index f5c86b4043..f4d03ccca1 100644 --- a/source3/lib/server_prefork.h +++ b/source3/lib/server_prefork.h @@ -160,18 +160,14 @@ int prefork_retire_children(struct prefork_pool *pfp, * @return The number of children actually serving clients */ int prefork_count_active_children(struct prefork_pool *pfp, int *total); + /** -* @brief Mark a child structure as free, based on the dead child pid. -* This function is called when the parent gets back notice a child -* has died through waitpid. It is critical to call this function -* when children are reaped so that memory slots can be freed. +* @brief Perform cleanups, like waiting (WNOHANG) dead children. +* MUST be called regularly from the parent main loop. * * @param pfp The pool. -* @param pid The child pid. -* -* @return True if the slot was clared. False if the pid is not listed. */ -bool prefork_mark_pid_dead(struct prefork_pool *pfp, pid_t pid); +void prefork_cleanup_loop(struct prefork_pool *pfp); /** * @brief Inform all children that they are allowed to accept 'max' clients diff --git a/source3/printing/spoolssd.c b/source3/printing/spoolssd.c index 25223c94c5..27704dab3c 100644 --- a/source3/printing/spoolssd.c +++ b/source3/printing/spoolssd.c @@ -524,23 +524,16 @@ static void spoolssd_sig_chld_handler(struct tevent_context *ev_ctx, void *siginfo, void *pvt) { struct prefork_pool *pfp; - pid_t pid; - int status; - bool ok; int active, total; int n, r; pfp = talloc_get_type_abort(pvt, struct prefork_pool); - while ((pid = sys_waitpid(-1, &status, WNOHANG)) > 0) { - ok = prefork_mark_pid_dead(pfp, pid); - if (!ok) { - DEBUG(1, ("Pid %d was not found in children pool!\n", - (int)pid)); - } - } + /* run the cleanup function to make sure all dead children are + * properly and timely retired. */ + prefork_cleanup_loop(pfp); - /* now check we do not descent below the minimum */ + /* now check we do not descend below the minimum */ active = prefork_count_active_children(pfp, &total); n = 0; -- cgit