s3-prefork: Provide a cleanup function
authorSimo Sorce <idra@samba.org>
Mon, 16 May 2011 14:46:35 +0000 (10:46 -0400)
committerAndreas Schneider <asn@samba.org>
Wed, 10 Aug 2011 16:14:04 +0000 (18:14 +0200)
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 <asn@samba.org>
source3/lib/server_prefork.c
source3/lib/server_prefork.h
source3/printing/spoolssd.c

index 211a54b95b30322e96923ec19db8f3892f9f1b2d..ef76a55486fd36d9e2aab383a0948e1f2a85d54d 100644 (file)
@@ -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)
index f5c86b40431293005adefef2a4aa55c7408ea065..f4d03ccca167aba643320bf48296813c35cf3f73 100644 (file)
@@ -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
index 25223c94c553484d962466b252b2010f66f1dc18..27704dab3ca588ef7983dfd79058f3343b66aac0 100644 (file)
@@ -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;