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>
-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)
{
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;
time_t now = time(NULL);
struct prefork_oldest *oldest;
int i, j;
prefork_sort_oldest);
for (i = 0, j = 0; i < pfp->pool_size && j < num_children; i++) {
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;
/* 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);
req = ctx->req;
state = tevent_req_data(ctx->req, struct pf_listen_state);
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 */
/* 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;
}
state->error = EINTR;
goto done;
}
/**
* @brief Commands a number of children to stop and exit
*
/**
* @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
* @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
* If all the available children are too young or are busy then it
* is possible that none will be asked to stop.
*/
* 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
int num_children, time_t age_limit);
/**
* @brief Count the number of children
n = total - cfg->min_children;
}
if (n >= 0) {
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);
}
}
now - cfg->child_min_life);
}
}