Changes with Apache 2.3.12
+ *) worker, event, prefork: Correct several issues when built as
+ DSOs; most notably, the scoreboard was reinitialized during graceful
+ restart, such that processes of the previous generation were not
+ observable. [Jeff Trawick]
Changes with Apache 2.3.11
static fd_queue_t *worker_queue;
static fd_queue_info_t *worker_queue_info;
static int mpm_state = AP_MPMQ_STARTING;
-static int sick_child_detected;
-static ap_generation_t my_generation = 0;
static apr_thread_mutex_t *timeout_mutex;
APR_RING_HEAD(timeout_head_t, conn_state_t);
int first_server_limit;
int first_thread_limit;
int module_loads;
+ int sick_child_detected;
+ ap_generation_t my_generation;
+ int volatile is_graceful; /* set from signal handler */
+ int maxclients_reported;
+ /*
+ * The max child slot ever assigned, preserved across restarts. Necessary
+ * to deal with MaxClients changes across AP_SIG_GRACEFUL restarts. We
+ * use this value to optimize routines that have to scan the entire
+ * scoreboard.
+ */
+ int max_daemons_limit;
+ /*
+ * idle_spawn_rate is the number of children that will be spawned on the
+ * next maintenance cycle if there aren't enough idle servers. It is
+ * doubled up to MAX_SPAWN_RATE, and reset only when a cycle goes by
+ * without the need to spawn.
+ */
+ int idle_spawn_rate;
+#ifndef MAX_SPAWN_RATE
+#define MAX_SPAWN_RATE (32)
+#endif
+ int hold_off_on_exponential_spawning;
} event_retained_data;
static event_retained_data *retained;
#define ID_FROM_CHILD_THREAD(c, t) ((c * thread_limit) + t)
-/*
- * The max child slot ever assigned, preserved across restarts. Necessary
- * to deal with MaxClients changes across AP_SIG_GRACEFUL restarts. We
- * use this value to optimize routines that have to scan the entire
- * scoreboard.
- */
-static int max_daemons_limit = -1;
-
static ap_event_pod_t *pod;
/* The event MPM respects a couple of runtime flags that can aid
*rv = APR_SUCCESS;
switch (query_code) {
case AP_MPMQ_MAX_DAEMON_USED:
- *result = max_daemons_limit;
+ *result = retained->max_daemons_limit;
break;
case AP_MPMQ_IS_THREADED:
*result = AP_MPMQ_STATIC;
*result = mpm_state;
break;
case AP_MPMQ_GENERATION:
- *result = my_generation;
+ *result = retained->my_generation;
break;
default:
*rv = APR_ENOTIMPL;
/* volatile because they're updated from a signal handler */
static int volatile shutdown_pending;
static int volatile restart_pending;
-static int volatile is_graceful;
/*
* ap_start_shutdown() and ap_start_restart(), below, are a first stab at
return;
}
shutdown_pending = 1;
- is_graceful = graceful;
+ retained->is_graceful = graceful;
}
/* do a graceful restart if graceful == 1 */
return;
}
restart_pending = 1;
- is_graceful = graceful;
+ retained->is_graceful = graceful;
}
static void sig_term(int sig)
ap_scoreboard_image->servers[process_slot][thread_slot].pid = ap_my_pid;
ap_scoreboard_image->servers[process_slot][thread_slot].tid = apr_os_thread_current();
- ap_scoreboard_image->servers[process_slot][thread_slot].generation = my_generation;
+ ap_scoreboard_image->servers[process_slot][thread_slot].generation = retained->my_generation;
ap_update_child_status_from_indexes(process_slot, thread_slot,
SERVER_STARTING, NULL);
{
int pid;
- if (slot + 1 > max_daemons_limit) {
- max_daemons_limit = slot + 1;
+ if (slot + 1 > retained->max_daemons_limit) {
+ retained->max_daemons_limit = slot + 1;
}
if (one_process) {
}
}
-
-/*
- * idle_spawn_rate is the number of children that will be spawned on the
- * next maintenance cycle if there aren't enough idle servers. It is
- * doubled up to MAX_SPAWN_RATE, and reset only when a cycle goes by
- * without the need to spawn.
- */
-static int idle_spawn_rate = 1;
-#ifndef MAX_SPAWN_RATE
-#define MAX_SPAWN_RATE (32)
-#endif
-static int hold_off_on_exponential_spawning;
-
static void perform_idle_server_maintenance(void)
{
int i, j;
int any_dead_threads = 0;
int all_dead_threads = 1;
- if (i >= max_daemons_limit
- && totally_free_length == idle_spawn_rate)
+ if (i >= retained->max_daemons_limit
+ && totally_free_length == retained->idle_spawn_rate)
/* short cut if all active processes have been examined and
* enough empty scoreboard slots have been found
*/
if (ps->pid != 0) { /* XXX just set all_dead_threads in outer
for loop if no pid? not much else matters */
if (status <= SERVER_READY &&
- !ps->quiescing && ps->generation == my_generation) {
+ !ps->quiescing && ps->generation == retained->my_generation) {
++idle_thread_count;
}
if (status >= SERVER_READY && status < SERVER_GRACEFUL) {
}
}
if (any_dead_threads
- && totally_free_length < idle_spawn_rate
+ && totally_free_length < retained->idle_spawn_rate
&& free_length < MAX_SPAWN_RATE
&& (!ps->pid /* no process in the slot */
|| ps->quiescing)) { /* or at least one is going away */
}
}
- if (sick_child_detected) {
+ if (retained->sick_child_detected) {
if (active_thread_count > 0) {
/* some child processes appear to be working. don't kill the
* whole server.
*/
- sick_child_detected = 0;
+ retained->sick_child_detected = 0;
}
else {
/* looks like a basket case. give up.
}
}
- max_daemons_limit = last_non_dead + 1;
+ retained->max_daemons_limit = last_non_dead + 1;
if (idle_thread_count > max_spare_threads) {
/* Kill off one child */
ap_event_pod_signal(pod, TRUE);
- idle_spawn_rate = 1;
+ retained->idle_spawn_rate = 1;
}
else if (idle_thread_count < min_spare_threads) {
/* terminate the free list */
if (free_length == 0) { /* scoreboard is full, can't fork */
if (active_thread_count >= ap_daemons_limit * threads_per_child) {
- static int reported = 0;
- if (!reported) {
+ if (!retained->maxclients_reported) {
/* only report this condition once */
ap_log_error(APLOG_MARK, APLOG_ERR, 0,
ap_server_conf,
"server reached MaxClients setting, consider"
" raising the MaxClients setting");
- reported = 1;
+ retained->maxclients_reported = 1;
}
}
else {
ap_server_conf,
"scoreboard is full, not at MaxClients");
}
- idle_spawn_rate = 1;
+ retained->idle_spawn_rate = 1;
}
else {
- if (free_length > idle_spawn_rate) {
- free_length = idle_spawn_rate;
+ if (free_length > retained->idle_spawn_rate) {
+ free_length = retained->idle_spawn_rate;
}
- if (idle_spawn_rate >= 8) {
+ if (retained->idle_spawn_rate >= 8) {
ap_log_error(APLOG_MARK, APLOG_INFO, 0,
ap_server_conf,
"server seems busy, (you may need "
/* the next time around we want to spawn twice as many if this
* wasn't good enough, but not if we've just done a graceful
*/
- if (hold_off_on_exponential_spawning) {
- --hold_off_on_exponential_spawning;
+ if (retained->hold_off_on_exponential_spawning) {
+ --retained->hold_off_on_exponential_spawning;
}
- else if (idle_spawn_rate < MAX_SPAWN_RATE) {
- idle_spawn_rate *= 2;
+ else if (retained->idle_spawn_rate < MAX_SPAWN_RATE) {
+ retained->idle_spawn_rate *= 2;
}
}
}
else {
- idle_spawn_rate = 1;
+ retained->idle_spawn_rate = 1;
}
}
/* tell perform_idle_server_maintenance to check into this
* on the next timer pop
*/
- sick_child_detected = 1;
+ retained->sick_child_detected = 1;
}
/* non-fatal death... note that it's gone in the scoreboard. */
child_slot = ap_find_child_by_pid(&pid);
ap_scoreboard_image->parent[child_slot].quiescing = 0;
if (processed_status == APEXIT_CHILDSICK) {
/* resource shortage, minimize the fork rate */
- idle_spawn_rate = 1;
+ retained->idle_spawn_rate = 1;
}
else if (remaining_children_to_start
&& child_slot < ap_daemons_limit) {
/* handled */
#endif
}
- else if (is_graceful) {
+ else if (retained->is_graceful) {
/* Great, we've probably just lost a slot in the
* scoreboard. Somehow we don't know about this child.
*/
ap_log_pid(pconf, ap_pid_fname);
- if (!is_graceful) {
+ if (!retained->is_graceful) {
if (ap_run_pre_mpm(s->process->pool, SB_SHARED) != OK) {
mpm_state = AP_MPMQ_STOPPING;
return DONE;
/* fix the generation number in the global score; we just got a new,
* cleared scoreboard
*/
- ap_scoreboard_image->global->running_generation = my_generation;
+ ap_scoreboard_image->global->running_generation = retained->my_generation;
}
set_signals();
if (remaining_children_to_start > ap_daemons_limit) {
remaining_children_to_start = ap_daemons_limit;
}
- if (!is_graceful) {
+ if (!retained->is_graceful) {
startup_children(remaining_children_to_start);
remaining_children_to_start = 0;
}
else {
/* give the system some time to recover before kicking into
* exponential mode */
- hold_off_on_exponential_spawning = 10;
+ retained->hold_off_on_exponential_spawning = 10;
}
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
server_main_loop(remaining_children_to_start);
mpm_state = AP_MPMQ_STOPPING;
- if (shutdown_pending && !is_graceful) {
+ if (shutdown_pending && !retained->is_graceful) {
/* Time to shut down:
* Kill child processes, tell them to call child_exit, etc...
*/
/* XXX: we really need to make sure this new generation number isn't in
* use by any of the children.
*/
- ++my_generation;
- ap_scoreboard_image->global->running_generation = my_generation;
+ ++retained->my_generation;
+ ap_scoreboard_image->global->running_generation = retained->my_generation;
- if (is_graceful) {
+ if (retained->is_graceful) {
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
AP_SIG_GRACEFUL_STRING
" received. Doing graceful restart");
retained = ap_retained_data_get(userdata_key);
if (!retained) {
retained = ap_retained_data_create(userdata_key, sizeof(*retained));
+ retained->max_daemons_limit = -1;
+ retained->idle_spawn_rate = 1;
}
++retained->module_loads;
if (retained->module_loads == 2) {
return HTTP_INTERNAL_SERVER_ERROR;
}
}
- parent_pid = ap_my_pid = getpid();
}
+ parent_pid = ap_my_pid = getpid();
+
ap_listen_pre_config();
ap_daemons_to_start = DEFAULT_START_DAEMON;
min_spare_threads = DEFAULT_MIN_FREE_DAEMON * DEFAULT_THREADS_PER_CHILD;
typedef struct prefork_retained_data {
int first_server_limit;
int module_loads;
+ ap_generation_t my_generation;
+ int volatile is_graceful; /* set from signal handler */
+ int maxclients_reported;
+ /*
+ * The max child slot ever assigned, preserved across restarts. Necessary
+ * to deal with MaxClients changes across AP_SIG_GRACEFUL restarts. We
+ * use this value to optimize routines that have to scan the entire scoreboard.
+ */
+ int max_daemons_limit;
+ /*
+ * idle_spawn_rate is the number of children that will be spawned on the
+ * next maintenance cycle if there aren't enough idle servers. It is
+ * doubled up to MAX_SPAWN_RATE, and reset only when a cycle goes by
+ * without the need to spawn.
+ */
+ int idle_spawn_rate;
+#ifndef MAX_SPAWN_RATE
+#define MAX_SPAWN_RATE (32)
+#endif
+ int hold_off_on_exponential_spawning;
} prefork_retained_data;
static prefork_retained_data *retained;
#define MPM_CHILD_PID(i) (ap_scoreboard_image->parent[i].pid)
-/*
- * The max child slot ever assigned, preserved across restarts. Necessary
- * to deal with MaxClients changes across AP_SIG_GRACEFUL restarts. We
- * use this value to optimize routines that have to scan the entire scoreboard.
- */
-static int max_daemons_limit = -1;
-
/* one_process --- debugging mode variable; can be set from the command line
* with the -X flag. If set, this gets you the child_main loop running
* in the process which originally started up (no detach, no make_child),
static pid_t ap_my_pid; /* it seems silly to call getpid all the time */
static pid_t parent_pid;
static int my_child_num;
-static ap_generation_t my_generation=0;
#ifdef GPROF
/*
if (rv != APR_SUCCESS) {
const char *msg = "couldn't grab the accept mutex";
- if (my_generation !=
+ if (retained->my_generation !=
ap_scoreboard_image->global->running_generation) {
ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, ap_server_conf, "%s", msg);
clean_child_exit(0);
if (rv != APR_SUCCESS) {
const char *msg = "couldn't release the accept mutex";
- if (my_generation !=
+ if (retained->my_generation !=
ap_scoreboard_image->global->running_generation) {
ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, ap_server_conf, "%s", msg);
/* don't exit here... we have a connection to
*result = mpm_state;
break;
case AP_MPMQ_GENERATION:
- *result = my_generation;
+ *result = retained->my_generation;
break;
default:
*rv = APR_ENOTIMPL;
/* volatile because they're updated from a signal handler */
static int volatile shutdown_pending;
static int volatile restart_pending;
-static int volatile is_graceful;
static int volatile die_now = 0;
static void stop_listening(int sig)
}
mpm_state = AP_MPMQ_STOPPING;
shutdown_pending = 1;
- is_graceful = (sig == AP_SIG_GRACEFUL_STOP);
+ retained->is_graceful = (sig == AP_SIG_GRACEFUL_STOP);
}
/* restart() is the signal handler for SIGHUP and AP_SIG_GRACEFUL
}
mpm_state = AP_MPMQ_STOPPING;
restart_pending = 1;
- is_graceful = (sig == AP_SIG_GRACEFUL);
+ retained->is_graceful = (sig == AP_SIG_GRACEFUL);
}
static void set_signals(void)
if (ap_mpm_pod_check(pod) == APR_SUCCESS) { /* selected as idle? */
die_now = 1;
}
- else if (my_generation !=
+ else if (retained->my_generation !=
ap_scoreboard_image->global->running_generation) { /* restart? */
/* yeah, this could be non-graceful restart, in which case the
* parent will kill us soon enough, but why bother checking?
{
int pid;
- if (slot + 1 > max_daemons_limit) {
- max_daemons_limit = slot + 1;
+ if (slot + 1 > retained->max_daemons_limit) {
+ retained->max_daemons_limit = slot + 1;
}
if (one_process) {
}
}
-
-/*
- * idle_spawn_rate is the number of children that will be spawned on the
- * next maintenance cycle if there aren't enough idle servers. It is
- * doubled up to MAX_SPAWN_RATE, and reset only when a cycle goes by
- * without the need to spawn.
- */
-static int idle_spawn_rate = 1;
-#ifndef MAX_SPAWN_RATE
-#define MAX_SPAWN_RATE (32)
-#endif
-static int hold_off_on_exponential_spawning;
-
static void perform_idle_server_maintenance(apr_pool_t *p)
{
int i;
for (i = 0; i < ap_daemons_limit; ++i) {
int status;
- if (i >= max_daemons_limit && free_length == idle_spawn_rate)
+ if (i >= retained->max_daemons_limit && free_length == retained->idle_spawn_rate)
break;
ws = &ap_scoreboard_image->servers[i][0];
status = ws->status;
if (status == SERVER_DEAD) {
/* try to keep children numbers as low as possible */
- if (free_length < idle_spawn_rate) {
+ if (free_length < retained->idle_spawn_rate) {
free_slots[free_length] = i;
++free_length;
}
last_non_dead = i;
}
}
- max_daemons_limit = last_non_dead + 1;
+ retained->max_daemons_limit = last_non_dead + 1;
if (idle_count > ap_daemons_max_free) {
/* kill off one child... we use the pod because that'll cause it to
* shut down gracefully, in case it happened to pick up a request
* while we were counting
*/
ap_mpm_pod_signal(pod);
- idle_spawn_rate = 1;
+ retained->idle_spawn_rate = 1;
}
else if (idle_count < ap_daemons_min_free) {
/* terminate the free list */
if (free_length == 0) {
/* only report this condition once */
- static int reported = 0;
-
- if (!reported) {
+ if (!retained->maxclients_reported) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf,
"server reached MaxClients setting, consider"
" raising the MaxClients setting");
- reported = 1;
+ retained->maxclients_reported = 1;
}
- idle_spawn_rate = 1;
+ retained->idle_spawn_rate = 1;
}
else {
- if (idle_spawn_rate >= 8) {
+ if (retained->idle_spawn_rate >= 8) {
ap_log_error(APLOG_MARK, APLOG_INFO, 0, ap_server_conf,
"server seems busy, (you may need "
"to increase StartServers, or Min/MaxSpareServers), "
"spawning %d children, there are %d idle, and "
- "%d total children", idle_spawn_rate,
+ "%d total children", retained->idle_spawn_rate,
idle_count, total_non_dead);
}
for (i = 0; i < free_length; ++i) {
/* the next time around we want to spawn twice as many if this
* wasn't good enough, but not if we've just done a graceful
*/
- if (hold_off_on_exponential_spawning) {
- --hold_off_on_exponential_spawning;
+ if (retained->hold_off_on_exponential_spawning) {
+ --retained->hold_off_on_exponential_spawning;
}
- else if (idle_spawn_rate < MAX_SPAWN_RATE) {
- idle_spawn_rate *= 2;
+ else if (retained->idle_spawn_rate < MAX_SPAWN_RATE) {
+ retained->idle_spawn_rate *= 2;
}
}
}
else {
- idle_spawn_rate = 1;
+ retained->idle_spawn_rate = 1;
}
}
return DONE;
}
- if (!is_graceful) {
+ if (!retained->is_graceful) {
if (ap_run_pre_mpm(s->process->pool, SB_SHARED) != OK) {
mpm_state = AP_MPMQ_STOPPING;
return DONE;
/* fix the generation number in the global score; we just got a new,
* cleared scoreboard
*/
- ap_scoreboard_image->global->running_generation = my_generation;
+ ap_scoreboard_image->global->running_generation = retained->my_generation;
}
set_signals();
if (remaining_children_to_start > ap_daemons_limit) {
remaining_children_to_start = ap_daemons_limit;
}
- if (!is_graceful) {
+ if (!retained->is_graceful) {
startup_children(remaining_children_to_start);
remaining_children_to_start = 0;
}
/* give the system some time to recover before kicking into
* exponential mode
*/
- hold_off_on_exponential_spawning = 10;
+ retained->hold_off_on_exponential_spawning = 10;
}
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
/* child detected a resource shortage (E[NM]FILE, ENOBUFS, etc)
* cut the fork rate to the minimum
*/
- idle_spawn_rate = 1;
+ retained->idle_spawn_rate = 1;
}
else if (remaining_children_to_start
&& child_slot < ap_daemons_limit) {
/* handled */
#endif
}
- else if (is_graceful) {
+ else if (retained->is_graceful) {
/* Great, we've probably just lost a slot in the
* scoreboard. Somehow we don't know about this
* child.
mpm_state = AP_MPMQ_STOPPING;
- if (shutdown_pending && !is_graceful) {
+ if (shutdown_pending && !retained->is_graceful) {
/* Time to shut down:
* Kill child processes, tell them to call child_exit, etc...
*/
ap_close_listeners();
/* kill off the idle ones */
- ap_mpm_pod_killpg(pod, max_daemons_limit);
+ ap_mpm_pod_killpg(pod, retained->max_daemons_limit);
/* Send SIGUSR1 to the active children */
active_children = 0;
/* XXX: we really need to make sure this new generation number isn't in
* use by any of the children.
*/
- ++my_generation;
- ap_scoreboard_image->global->running_generation = my_generation;
+ ++retained->my_generation;
+ ap_scoreboard_image->global->running_generation = retained->my_generation;
- if (is_graceful) {
+ if (retained->is_graceful) {
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
"Graceful restart requested, doing restart");
/* kill off the idle ones */
- ap_mpm_pod_killpg(pod, max_daemons_limit);
+ ap_mpm_pod_killpg(pod, retained->max_daemons_limit);
/* This is mostly for debugging... so that we know what is still
* gracefully dealing with existing request. This will break
retained = ap_retained_data_get(userdata_key);
if (!retained) {
retained = ap_retained_data_create(userdata_key, sizeof(*retained));
+ retained->max_daemons_limit = -1;
+ retained->idle_spawn_rate = 1;
}
++retained->module_loads;
if (retained->module_loads == 2) {
return HTTP_INTERNAL_SERVER_ERROR;
}
}
-
- parent_pid = ap_my_pid = getpid();
}
+ parent_pid = ap_my_pid = getpid();
+
ap_listen_pre_config();
ap_daemons_to_start = DEFAULT_START_DAEMON;
ap_daemons_min_free = DEFAULT_MIN_FREE_DAEMON;
static fd_queue_t *worker_queue;
static fd_queue_info_t *worker_queue_info;
static int mpm_state = AP_MPMQ_STARTING;
-static int sick_child_detected;
-static ap_generation_t my_generation = 0;
/* data retained by worker across load/unload of the module
* allocated on first call to pre-config hook; located on
int first_server_limit;
int first_thread_limit;
int module_loads;
+ int sick_child_detected;
+ ap_generation_t my_generation;
+ int volatile is_graceful; /* set from signal handler */
+ int maxclients_reported;
+ int near_maxclients_reported;
+ /*
+ * The max child slot ever assigned, preserved across restarts. Necessary
+ * to deal with MaxClients changes across AP_SIG_GRACEFUL restarts. We
+ * use this value to optimize routines that have to scan the entire
+ * scoreboard.
+ */
+ int max_daemons_limit;
+ /*
+ * idle_spawn_rate is the number of children that will be spawned on the
+ * next maintenance cycle if there aren't enough idle servers. It is
+ * doubled up to MAX_SPAWN_RATE, and reset only when a cycle goes by
+ * without the need to spawn.
+ */
+ int idle_spawn_rate;
+#ifndef MAX_SPAWN_RATE
+#define MAX_SPAWN_RATE (32)
+#endif
+ int hold_off_on_exponential_spawning;
} worker_retained_data;
static worker_retained_data *retained;
#define ID_FROM_CHILD_THREAD(c, t) ((c * thread_limit) + t)
-/*
- * The max child slot ever assigned, preserved across restarts. Necessary
- * to deal with MaxClients changes across AP_SIG_GRACEFUL restarts. We
- * use this value to optimize routines that have to scan the entire
- * scoreboard.
- */
-static int max_daemons_limit = -1;
-
static ap_worker_pod_t *pod;
/* The worker MPM respects a couple of runtime flags that can aid
*rv = APR_SUCCESS;
switch (query_code) {
case AP_MPMQ_MAX_DAEMON_USED:
- *result = max_daemons_limit;
+ *result = retained->max_daemons_limit;
break;
case AP_MPMQ_IS_THREADED:
*result = AP_MPMQ_STATIC;
*result = mpm_state;
break;
case AP_MPMQ_GENERATION:
- *result = my_generation;
+ *result = retained->my_generation;
break;
default:
*rv = APR_ENOTIMPL;
/* volatile because they're updated from a signal handler */
static int volatile shutdown_pending;
static int volatile restart_pending;
-static int volatile is_graceful;
/*
* ap_start_shutdown() and ap_start_restart(), below, are a first stab at
return;
}
shutdown_pending = 1;
- is_graceful = graceful;
+ retained->is_graceful = graceful;
}
/* do a graceful restart if graceful == 1 */
return;
}
restart_pending = 1;
- is_graceful = graceful;
+ retained->is_graceful = graceful;
}
static void sig_term(int sig)
ap_scoreboard_image->servers[process_slot][thread_slot].pid = ap_my_pid;
ap_scoreboard_image->servers[process_slot][thread_slot].tid = apr_os_thread_current();
- ap_scoreboard_image->servers[process_slot][thread_slot].generation = my_generation;
+ ap_scoreboard_image->servers[process_slot][thread_slot].generation = retained->my_generation;
ap_update_child_status_from_indexes(process_slot, thread_slot, SERVER_STARTING, NULL);
#ifdef HAVE_PTHREAD_KILL
{
int pid;
- if (slot + 1 > max_daemons_limit) {
- max_daemons_limit = slot + 1;
+ if (slot + 1 > retained->max_daemons_limit) {
+ retained->max_daemons_limit = slot + 1;
}
if (one_process) {
}
}
-
-/*
- * idle_spawn_rate is the number of children that will be spawned on the
- * next maintenance cycle if there aren't enough idle servers. It is
- * doubled up to MAX_SPAWN_RATE, and reset only when a cycle goes by
- * without the need to spawn.
- */
-static int idle_spawn_rate = 1;
-#ifndef MAX_SPAWN_RATE
-#define MAX_SPAWN_RATE (32)
-#endif
-static int hold_off_on_exponential_spawning;
-
static void perform_idle_server_maintenance(void)
{
int i, j;
int any_dead_threads = 0;
int all_dead_threads = 1;
- if (i >= max_daemons_limit && totally_free_length == idle_spawn_rate)
+ if (i >= retained->max_daemons_limit && totally_free_length == retained->idle_spawn_rate)
/* short cut if all active processes have been examined and
* enough empty scoreboard slots have been found
*/
loop if no pid? not much else matters */
if (status <= SERVER_READY &&
!ps->quiescing &&
- ps->generation == my_generation) {
+ ps->generation == retained->my_generation) {
++idle_thread_count;
}
if (status >= SERVER_READY && status < SERVER_GRACEFUL) {
}
}
}
- if (any_dead_threads && totally_free_length < idle_spawn_rate
+ if (any_dead_threads && totally_free_length < retained->idle_spawn_rate
&& free_length < MAX_SPAWN_RATE
&& (!ps->pid /* no process in the slot */
|| ps->quiescing)) { /* or at least one is going away */
}
}
- if (sick_child_detected) {
+ if (retained->sick_child_detected) {
if (active_thread_count > 0) {
/* some child processes appear to be working. don't kill the
* whole server.
*/
- sick_child_detected = 0;
+ retained->sick_child_detected = 0;
}
else {
/* looks like a basket case. give up.
}
}
- max_daemons_limit = last_non_dead + 1;
+ retained->max_daemons_limit = last_non_dead + 1;
if (idle_thread_count > max_spare_threads) {
/* Kill off one child */
ap_worker_pod_signal(pod, TRUE);
- idle_spawn_rate = 1;
+ retained->idle_spawn_rate = 1;
}
else if (idle_thread_count < min_spare_threads) {
/* terminate the free list */
/* no threads are "inactive" - starting, stopping, etc. */
/* have we reached MaxClients, or just getting close? */
if (0 == idle_thread_count) {
- static int reported = 0;
- if (!reported) {
+ if (!retained->maxclients_reported) {
/* only report this condition once */
ap_log_error(APLOG_MARK, APLOG_ERR, 0,
ap_server_conf,
"server reached MaxClients setting, consider"
" raising the MaxClients setting");
- reported = 1;
+ retained->maxclients_reported = 1;
}
} else {
- static int reported = 0;
- if (!reported) {
+ if (!retained->near_maxclients_reported) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0,
ap_server_conf,
"server is within MinSpareThreads of MaxClients, "
"consider raising the MaxClients setting");
- reported = 1;
+ retained->near_maxclients_reported = 1;
}
}
}
ap_server_conf,
"scoreboard is full, not at MaxClients");
}
- idle_spawn_rate = 1;
+ retained->idle_spawn_rate = 1;
}
else {
- if (free_length > idle_spawn_rate) {
- free_length = idle_spawn_rate;
+ if (free_length > retained->idle_spawn_rate) {
+ free_length = retained->idle_spawn_rate;
}
- if (idle_spawn_rate >= 8) {
+ if (retained->idle_spawn_rate >= 8) {
ap_log_error(APLOG_MARK, APLOG_INFO, 0,
ap_server_conf,
"server seems busy, (you may need "
/* the next time around we want to spawn twice as many if this
* wasn't good enough, but not if we've just done a graceful
*/
- if (hold_off_on_exponential_spawning) {
- --hold_off_on_exponential_spawning;
+ if (retained->hold_off_on_exponential_spawning) {
+ --retained->hold_off_on_exponential_spawning;
}
- else if (idle_spawn_rate < MAX_SPAWN_RATE) {
- idle_spawn_rate *= 2;
+ else if (retained->idle_spawn_rate < MAX_SPAWN_RATE) {
+ retained->idle_spawn_rate *= 2;
}
}
}
else {
- idle_spawn_rate = 1;
+ retained->idle_spawn_rate = 1;
}
}
/* tell perform_idle_server_maintenance to check into this
* on the next timer pop
*/
- sick_child_detected = 1;
+ retained->sick_child_detected = 1;
}
/* non-fatal death... note that it's gone in the scoreboard. */
child_slot = ap_find_child_by_pid(&pid);
ap_scoreboard_image->parent[child_slot].quiescing = 0;
if (processed_status == APEXIT_CHILDSICK) {
/* resource shortage, minimize the fork rate */
- idle_spawn_rate = 1;
+ retained->idle_spawn_rate = 1;
}
else if (remaining_children_to_start
&& child_slot < ap_daemons_limit) {
/* handled */
#endif
}
- else if (is_graceful) {
+ else if (retained->is_graceful) {
/* Great, we've probably just lost a slot in the
* scoreboard. Somehow we don't know about this child.
*/
return DONE;
}
- if (!is_graceful) {
+ if (!retained->is_graceful) {
if (ap_run_pre_mpm(s->process->pool, SB_SHARED) != OK) {
mpm_state = AP_MPMQ_STOPPING;
return DONE;
/* fix the generation number in the global score; we just got a new,
* cleared scoreboard
*/
- ap_scoreboard_image->global->running_generation = my_generation;
+ ap_scoreboard_image->global->running_generation = retained->my_generation;
}
set_signals();
if (remaining_children_to_start > ap_daemons_limit) {
remaining_children_to_start = ap_daemons_limit;
}
- if (!is_graceful) {
+ if (!retained->is_graceful) {
startup_children(remaining_children_to_start);
remaining_children_to_start = 0;
}
else {
/* give the system some time to recover before kicking into
* exponential mode */
- hold_off_on_exponential_spawning = 10;
+ retained->hold_off_on_exponential_spawning = 10;
}
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
server_main_loop(remaining_children_to_start);
mpm_state = AP_MPMQ_STOPPING;
- if (shutdown_pending && !is_graceful) {
+ if (shutdown_pending && !retained->is_graceful) {
/* Time to shut down:
* Kill child processes, tell them to call child_exit, etc...
*/
/* XXX: we really need to make sure this new generation number isn't in
* use by any of the children.
*/
- ++my_generation;
- ap_scoreboard_image->global->running_generation = my_generation;
+ ++retained->my_generation;
+ ap_scoreboard_image->global->running_generation = retained->my_generation;
- if (is_graceful) {
+ if (retained->is_graceful) {
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
AP_SIG_GRACEFUL_STRING " received. Doing graceful restart");
/* wake up the children...time to die. But we'll have more soon */
retained = ap_retained_data_get(userdata_key);
if (!retained) {
retained = ap_retained_data_create(userdata_key, sizeof(*retained));
+ retained->max_daemons_limit = -1;
+ retained->idle_spawn_rate = 1;
}
++retained->module_loads;
if (retained->module_loads == 2) {
return HTTP_INTERNAL_SERVER_ERROR;
}
}
- parent_pid = ap_my_pid = getpid();
}
+ parent_pid = ap_my_pid = getpid();
+
ap_listen_pre_config();
ap_daemons_to_start = DEFAULT_START_DAEMON;
min_spare_threads = DEFAULT_MIN_FREE_DAEMON * DEFAULT_THREADS_PER_CHILD;
static int worker_check_config(apr_pool_t *p, apr_pool_t *plog,
apr_pool_t *ptemp, server_rec *s)
{
- static int restart_num = 0;
int startup = 0;
/* the reverse of pre_config, we want this only the first time around */
- if (restart_num++ == 0) {
+ if (retained->module_loads == 1) {
startup = 1;
}