s3-prefork: Fix code to retire children
authorSimo Sorce <idra@samba.org>
Thu, 18 Aug 2011 14:31:36 +0000 (10:31 -0400)
committerSimo Sorce <idra@samba.org>
Sun, 21 Aug 2011 13:05:06 +0000 (09:05 -0400)
We have to be more careful when retiring children. We cannot stop
accepting connections as soon as the server tells us to quit because if
max_children is reached and we still have clients connected, the server will
not be able to spawn new children until one exits. And children will not exit
until all the clients closed the connections. So we keep operating past our
recall until we have 0 connections.
Also do not try to recall children that still have >= 1 clients connected, they
couldn't anyway.
Also use messaging to warn children and not SIGHUP.

Signed-off-by: Andreas Schneider <asn@samba.org>
Signed-off-by: Simo Sorce <idra@samba.org>
source3/lib/server_prefork.c
source3/lib/server_prefork.h
source3/lib/server_prefork_util.c

index bcb5e0f19e8858b8935af70d7a401f687495191f..016f65c5c374cc0ae79954c44d52789fdf86fe2f 100644 (file)
@@ -240,9 +240,11 @@ static int prefork_sort_oldest(const void *ap, const void *bp)
        return -1;
 }
 
-int prefork_retire_children(struct prefork_pool *pfp,
+int prefork_retire_children(struct messaging_context *msg_ctx,
+                           struct prefork_pool *pfp,
                            int num_children, time_t age_limit)
 {
+       const DATA_BLOB ping = data_blob_null;
        time_t now = time(NULL);
        struct prefork_oldest *oldest;
        int i, j;
@@ -267,13 +269,15 @@ int prefork_retire_children(struct prefork_pool *pfp,
                prefork_sort_oldest);
 
        for (i = 0, j = 0; i < pfp->pool_size && j < num_children; i++) {
-               if ((pfp->pool[i].status == PF_WORKER_ALIVE ||
-                    pfp->pool[i].status == PF_WORKER_ACCEPTING) &&
-                   pfp->pool[i].started <= age_limit) {
+               if (((pfp->pool[i].status == PF_WORKER_ALIVE) &&
+                    (pfp->pool[i].num_clients < 1)) &&
+                   (pfp->pool[i].started <= age_limit)) {
                        /* tell the child it's time to give up */
                        DEBUG(5, ("Retiring pid %d!\n", pfp->pool[i].pid));
                        pfp->pool[i].cmds = PF_SRV_MSG_EXIT;
-                       kill(pfp->pool[i].pid, SIGHUP);
+                       messaging_send(msg_ctx,
+                                       pid_to_procid(pfp->pool[i].pid),
+                                       MSG_PREFORK_PARENT_EVENT, &ping);
                        j++;
                }
        }
@@ -581,12 +585,11 @@ static void prefork_listen_accept_handler(struct tevent_context *ev,
        req = ctx->req;
        state = tevent_req_data(ctx->req, struct pf_listen_state);
 
-       if (state->pf->cmds == PF_SRV_MSG_EXIT) {
+       if ((state->pf->cmds == PF_SRV_MSG_EXIT) &&
+           (state->pf->num_clients <= 0)) {
                /* We have been asked to exit, so drop here and the next
                 * child will pick it up */
-               if (state->pf->num_clients <= 0) {
-                       state->pf->status = PF_WORKER_EXITING;
-               }
+               state->pf->status = PF_WORKER_EXITING;
                state->error = EINTR;
                goto done;
        }
index 17491536ffbe93b46eabc281aace46ab028e4077..1d203e6317e0a6d69470d74811a824996940e924 100644 (file)
@@ -152,6 +152,7 @@ int prefork_add_children(struct tevent_context *ev_ctx,
 /**
 * @brief Commands a number of children to stop and exit
 *
+* @param msg_ctx       The messaging context.
 * @param pfp           The pool.
 * @param num_children  The number of children we need to retire.
 * @param age_limit     The minimum age a child has been active to be
@@ -165,7 +166,8 @@ int prefork_add_children(struct tevent_context *ev_ctx,
 *      If all the available children are too young or are busy then it
 *      is possible that none will be asked to stop.
 */
-int prefork_retire_children(struct prefork_pool *pfp,
+int prefork_retire_children(struct messaging_context *msg_ctx,
+                           struct prefork_pool *pfp,
                            int num_children, time_t age_limit);
 /**
 * @brief Count the number of children
index 01c7994f601611c5096a8447be1c7b1a1f807d68..3e14015c81ee320c0f65cb680da4163d3826b5a6 100644 (file)
@@ -102,7 +102,7 @@ void pfh_manage_pool(struct tevent_context *ev_ctx,
                        n = total - cfg->min_children;
                }
                if (n >= 0) {
-                       prefork_retire_children(pool, n,
+                       prefork_retire_children(msg_ctx, pool, n,
                                                now - cfg->child_min_life);
                }
        }