mirror of
https://github.com/apache/httpd.git
synced 2026-10-23 22:49:01 +03:00
MPMs unix: Place signals handlers and helpers out of DSOs to avoid
a possible crash if a signal is caught during (graceful) restart. PR 60487. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1783849 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
4
CHANGES
4
CHANGES
@@ -1,6 +1,10 @@
|
||||
-*- coding: utf-8 -*-
|
||||
Changes with Apache 2.5.0
|
||||
|
||||
*) MPMs unix: Place signals handlers and helpers out of DSOs to avoid
|
||||
a possible crash if a signal is caught during (graceful) restart.
|
||||
PR 60487. [Yann Ylavic]
|
||||
|
||||
*) mod_cache: Fix a regression in 2.4.25 for the forward proxy case by
|
||||
computing and using the same entity key according to when the cache
|
||||
checks, loads and saves the request.
|
||||
|
||||
149
os/unix/unixd.c
149
os/unix/unixd.c
@@ -434,6 +434,155 @@ AP_DECLARE(apr_status_t) ap_unixd_accept(void **accepted, ap_listen_rec *lr,
|
||||
}
|
||||
|
||||
|
||||
/* Unixes MPMs' */
|
||||
|
||||
static ap_unixd_mpm_retained_data *retained_data = NULL;
|
||||
AP_DECLARE(ap_unixd_mpm_retained_data *) ap_unixd_mpm_get_retained_data()
|
||||
{
|
||||
if (!retained_data) {
|
||||
retained_data = ap_retained_data_create("ap_unixd_mpm_retained_data",
|
||||
sizeof(*retained_data));
|
||||
retained_data->mpm_state = AP_MPMQ_STARTING;
|
||||
}
|
||||
return retained_data;
|
||||
}
|
||||
|
||||
static void sig_term(int sig)
|
||||
{
|
||||
retained_data->mpm_state = AP_MPMQ_STOPPING;
|
||||
if (retained_data->shutdown_pending
|
||||
&& (retained_data->is_ungraceful
|
||||
|| sig == AP_SIG_GRACEFUL_STOP)) {
|
||||
/* Already handled */
|
||||
return;
|
||||
}
|
||||
|
||||
retained_data->shutdown_pending = 1;
|
||||
if (sig != AP_SIG_GRACEFUL_STOP) {
|
||||
retained_data->is_ungraceful = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void sig_restart(int sig)
|
||||
{
|
||||
retained_data->mpm_state = AP_MPMQ_STOPPING;
|
||||
if (retained_data->restart_pending
|
||||
&& (retained_data->is_ungraceful
|
||||
|| sig == AP_SIG_GRACEFUL)) {
|
||||
/* Already handled */
|
||||
return;
|
||||
}
|
||||
|
||||
retained_data->restart_pending = 1;
|
||||
if (sig != AP_SIG_GRACEFUL) {
|
||||
retained_data->is_ungraceful = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static apr_status_t unset_signals(void *unused)
|
||||
{
|
||||
retained_data->shutdown_pending = retained_data->restart_pending = 0;
|
||||
retained_data->was_graceful = !retained_data->is_ungraceful;
|
||||
retained_data->is_ungraceful = 0;
|
||||
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
AP_DECLARE(void) ap_unixd_mpm_set_signals(apr_pool_t *pconf, int one_process)
|
||||
{
|
||||
#ifndef NO_USE_SIGACTION
|
||||
struct sigaction sa;
|
||||
#endif
|
||||
|
||||
/* Signals' handlers depend on retained data */
|
||||
(void)ap_unixd_mpm_get_retained_data();
|
||||
|
||||
#ifndef NO_USE_SIGACTION
|
||||
memset(&sa, 0, sizeof sa);
|
||||
sigemptyset(&sa.sa_mask);
|
||||
|
||||
#ifdef SIGPIPE
|
||||
sa.sa_handler = SIG_IGN;
|
||||
if (sigaction(SIGPIPE, &sa, NULL) < 0)
|
||||
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00269)
|
||||
"sigaction(SIGPIPE)");
|
||||
#endif
|
||||
#ifdef SIGXCPU
|
||||
sa.sa_handler = SIG_DFL;
|
||||
if (sigaction(SIGXCPU, &sa, NULL) < 0)
|
||||
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00267)
|
||||
"sigaction(SIGXCPU)");
|
||||
#endif
|
||||
#ifdef SIGXFSZ
|
||||
/* For systems following the LFS standard, ignoring SIGXFSZ allows
|
||||
* a write() beyond the 2GB limit to fail gracefully with E2BIG
|
||||
* rather than terminate the process. */
|
||||
sa.sa_handler = SIG_IGN;
|
||||
if (sigaction(SIGXFSZ, &sa, NULL) < 0)
|
||||
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00268)
|
||||
"sigaction(SIGXFSZ)");
|
||||
#endif
|
||||
|
||||
sa.sa_handler = sig_term;
|
||||
if (sigaction(SIGTERM, &sa, NULL) < 0)
|
||||
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00264)
|
||||
"sigaction(SIGTERM)");
|
||||
#ifdef SIGINT
|
||||
if (sigaction(SIGINT, &sa, NULL) < 0)
|
||||
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00266)
|
||||
"sigaction(SIGINT)");
|
||||
#endif
|
||||
#ifdef AP_SIG_GRACEFUL_STOP
|
||||
if (sigaction(AP_SIG_GRACEFUL_STOP, &sa, NULL) < 0)
|
||||
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00265)
|
||||
"sigaction(" AP_SIG_GRACEFUL_STOP_STRING ")");
|
||||
#endif
|
||||
|
||||
/* Don't catch restart signals in ONE_PROCESS mode :) */
|
||||
if (!one_process) {
|
||||
sa.sa_handler = sig_restart;
|
||||
if (sigaction(SIGHUP, &sa, NULL) < 0)
|
||||
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00270)
|
||||
"sigaction(SIGHUP)");
|
||||
if (sigaction(AP_SIG_GRACEFUL, &sa, NULL) < 0)
|
||||
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00271)
|
||||
"sigaction(" AP_SIG_GRACEFUL_STRING ")");
|
||||
}
|
||||
|
||||
#else /* NO_USE_SIGACTION */
|
||||
|
||||
#ifdef SIGPIPE
|
||||
apr_signal(SIGPIPE, SIG_IGN);
|
||||
#endif /* SIGPIPE */
|
||||
#ifdef SIGXCPU
|
||||
apr_signal(SIGXCPU, SIG_DFL);
|
||||
#endif /* SIGXCPU */
|
||||
#ifdef SIGXFSZ
|
||||
apr_signal(SIGXFSZ, SIG_IGN);
|
||||
#endif /* SIGXFSZ */
|
||||
|
||||
apr_signal(SIGTERM, sig_term);
|
||||
#ifdef AP_SIG_GRACEFUL_STOP
|
||||
apr_signal(AP_SIG_GRACEFUL_STOP, sig_term);
|
||||
#endif /* AP_SIG_GRACEFUL_STOP */
|
||||
|
||||
if (!one_process) {
|
||||
/* Don't restart in ONE_PROCESS mode :) */
|
||||
#ifdef SIGHUP
|
||||
apr_signal(SIGHUP, sig_restart);
|
||||
#endif /* SIGHUP */
|
||||
#ifdef AP_SIG_GRACEFUL
|
||||
apr_signal(AP_SIG_GRACEFUL, sig_restart);
|
||||
#endif /* AP_SIG_GRACEFUL */
|
||||
}
|
||||
|
||||
#endif /* NO_USE_SIGACTION */
|
||||
|
||||
apr_pool_cleanup_register(pconf, NULL, unset_signals,
|
||||
apr_pool_cleanup_null);
|
||||
}
|
||||
|
||||
|
||||
#ifdef _OSD_POSIX
|
||||
|
||||
#include "apr_lib.h"
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
|
||||
#include "httpd.h"
|
||||
#include "http_config.h"
|
||||
#include "scoreboard.h"
|
||||
#include "ap_listen.h"
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
@@ -109,6 +110,30 @@ AP_DECLARE(apr_status_t) ap_unixd_accept(void **accepted, ap_listen_rec *lr, apr
|
||||
#define ap_os_killpg(x, y) (kill (-(x), (y)))
|
||||
#endif /* HAVE_KILLPG */
|
||||
|
||||
typedef struct {
|
||||
void *baton; /* MPM's */
|
||||
|
||||
/* volatile because they're updated from signals' handlers */
|
||||
int volatile mpm_state;
|
||||
int volatile shutdown_pending;
|
||||
int volatile restart_pending;
|
||||
int volatile is_ungraceful;
|
||||
|
||||
ap_generation_t my_generation;
|
||||
int module_loads;
|
||||
int was_graceful;
|
||||
|
||||
/*
|
||||
* Current number of listeners buckets and maximum reached across
|
||||
* restarts (to size retained data according to dynamic num_buckets,
|
||||
* eg. idle_spawn_rate).
|
||||
*/
|
||||
int num_buckets, max_buckets;
|
||||
} ap_unixd_mpm_retained_data;
|
||||
|
||||
AP_DECLARE(ap_unixd_mpm_retained_data *) ap_unixd_mpm_get_retained_data(void);
|
||||
AP_DECLARE(void) ap_unixd_mpm_set_signals(apr_pool_t *pconf, int once_process);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -197,7 +197,6 @@ static apr_uint32_t threads_shutdown = 0; /* Number of threads that have shutd
|
||||
static int resource_shortage = 0;
|
||||
static fd_queue_t *worker_queue;
|
||||
static fd_queue_info_t *worker_queue_info;
|
||||
static int mpm_state = AP_MPMQ_STARTING;
|
||||
|
||||
static apr_thread_mutex_t *timeout_mutex;
|
||||
|
||||
@@ -382,12 +381,11 @@ typedef struct
|
||||
* subsequent calls to pre-config hook
|
||||
*/
|
||||
typedef struct event_retained_data {
|
||||
ap_unixd_mpm_retained_data *mpm;
|
||||
|
||||
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
|
||||
@@ -415,12 +413,6 @@ typedef struct event_retained_data {
|
||||
#define MAX_SPAWN_RATE (32)
|
||||
#endif
|
||||
int hold_off_on_exponential_spawning;
|
||||
/*
|
||||
* Current number of listeners buckets and maximum reached across
|
||||
* restarts (to size retained data according to dynamic num_buckets,
|
||||
* eg. idle_spawn_rate).
|
||||
*/
|
||||
int num_buckets, max_buckets;
|
||||
} event_retained_data;
|
||||
static event_retained_data *retained;
|
||||
|
||||
@@ -566,7 +558,7 @@ static void signal_threads(int mode)
|
||||
return;
|
||||
}
|
||||
terminate_mode = mode;
|
||||
mpm_state = AP_MPMQ_STOPPING;
|
||||
retained->mpm->mpm_state = AP_MPMQ_STOPPING;
|
||||
|
||||
/* in case we weren't called from the listener thread, wake up the
|
||||
* listener thread
|
||||
@@ -631,10 +623,10 @@ static int event_query(int query_code, int *result, apr_status_t *rv)
|
||||
*result = active_daemons_limit;
|
||||
break;
|
||||
case AP_MPMQ_MPM_STATE:
|
||||
*result = mpm_state;
|
||||
*result = retained->mpm->mpm_state;
|
||||
break;
|
||||
case AP_MPMQ_GENERATION:
|
||||
*result = retained->my_generation;
|
||||
*result = retained->mpm->my_generation;
|
||||
break;
|
||||
case AP_MPMQ_CAN_SUSPEND:
|
||||
*result = 1;
|
||||
@@ -668,7 +660,7 @@ static void event_note_child_started(int slot, pid_t pid)
|
||||
ap_scoreboard_image->parent[slot].pid = pid;
|
||||
ap_run_child_status(ap_server_conf,
|
||||
ap_scoreboard_image->parent[slot].pid,
|
||||
retained->my_generation, slot, MPM_CHILD_STARTED);
|
||||
retained->mpm->my_generation, slot, MPM_CHILD_STARTED);
|
||||
}
|
||||
|
||||
static const char *event_get_name(void)
|
||||
@@ -680,7 +672,7 @@ static const char *event_get_name(void)
|
||||
static void clean_child_exit(int code) __attribute__ ((noreturn));
|
||||
static void clean_child_exit(int code)
|
||||
{
|
||||
mpm_state = AP_MPMQ_STOPPING;
|
||||
retained->mpm->mpm_state = AP_MPMQ_STOPPING;
|
||||
if (pchild) {
|
||||
apr_pool_destroy(pchild);
|
||||
}
|
||||
@@ -703,10 +695,6 @@ static void just_die(int sig)
|
||||
|
||||
static int child_fatal;
|
||||
|
||||
/* volatile because they're updated from a signal handler */
|
||||
static int volatile shutdown_pending;
|
||||
static int volatile restart_pending;
|
||||
|
||||
static apr_status_t decrement_connection_count(void *cs_)
|
||||
{
|
||||
event_conn_state_t *cs = cs_;
|
||||
@@ -729,149 +717,6 @@ static apr_status_t decrement_connection_count(void *cs_)
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* ap_start_shutdown() and ap_start_restart(), below, are a first stab at
|
||||
* functions to initiate shutdown or restart without relying on signals.
|
||||
* Previously this was initiated in sig_term() and restart() signal handlers,
|
||||
* but we want to be able to start a shutdown/restart from other sources --
|
||||
* e.g. on Win32, from the service manager. Now the service manager can
|
||||
* call ap_start_shutdown() or ap_start_restart() as appropriate. Note that
|
||||
* these functions can also be called by the child processes, since global
|
||||
* variables are no longer used to pass on the required action to the parent.
|
||||
*
|
||||
* These should only be called from the parent process itself, since the
|
||||
* parent process will use the shutdown_pending and restart_pending variables
|
||||
* to determine whether to shutdown or restart. The child process should
|
||||
* call signal_parent() directly to tell the parent to die -- this will
|
||||
* cause neither of those variable to be set, which the parent will
|
||||
* assume means something serious is wrong (which it will be, for the
|
||||
* child to force an exit) and so do an exit anyway.
|
||||
*/
|
||||
|
||||
static void ap_start_shutdown(int graceful)
|
||||
{
|
||||
mpm_state = AP_MPMQ_STOPPING;
|
||||
if (shutdown_pending == 1) {
|
||||
/* Um, is this _probably_ not an error, if the user has
|
||||
* tried to do a shutdown twice quickly, so we won't
|
||||
* worry about reporting it.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
shutdown_pending = 1;
|
||||
retained->is_graceful = graceful;
|
||||
}
|
||||
|
||||
/* do a graceful restart if graceful == 1 */
|
||||
static void ap_start_restart(int graceful)
|
||||
{
|
||||
mpm_state = AP_MPMQ_STOPPING;
|
||||
if (restart_pending == 1) {
|
||||
/* Probably not an error - don't bother reporting it */
|
||||
return;
|
||||
}
|
||||
restart_pending = 1;
|
||||
retained->is_graceful = graceful;
|
||||
}
|
||||
|
||||
static void sig_term(int sig)
|
||||
{
|
||||
ap_start_shutdown(sig == AP_SIG_GRACEFUL_STOP);
|
||||
}
|
||||
|
||||
static void restart(int sig)
|
||||
{
|
||||
ap_start_restart(sig == AP_SIG_GRACEFUL);
|
||||
}
|
||||
|
||||
static void set_signals(void)
|
||||
{
|
||||
#ifndef NO_USE_SIGACTION
|
||||
struct sigaction sa;
|
||||
#endif
|
||||
|
||||
if (!one_process) {
|
||||
ap_fatal_signal_setup(ap_server_conf, pconf);
|
||||
}
|
||||
|
||||
#ifndef NO_USE_SIGACTION
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_flags = 0;
|
||||
|
||||
sa.sa_handler = sig_term;
|
||||
if (sigaction(SIGTERM, &sa, NULL) < 0)
|
||||
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00459)
|
||||
"sigaction(SIGTERM)");
|
||||
#ifdef AP_SIG_GRACEFUL_STOP
|
||||
if (sigaction(AP_SIG_GRACEFUL_STOP, &sa, NULL) < 0)
|
||||
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00460)
|
||||
"sigaction(" AP_SIG_GRACEFUL_STOP_STRING ")");
|
||||
#endif
|
||||
#ifdef SIGINT
|
||||
if (sigaction(SIGINT, &sa, NULL) < 0)
|
||||
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00461)
|
||||
"sigaction(SIGINT)");
|
||||
#endif
|
||||
#ifdef SIGXCPU
|
||||
sa.sa_handler = SIG_DFL;
|
||||
if (sigaction(SIGXCPU, &sa, NULL) < 0)
|
||||
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00462)
|
||||
"sigaction(SIGXCPU)");
|
||||
#endif
|
||||
#ifdef SIGXFSZ
|
||||
/* For systems following the LFS standard, ignoring SIGXFSZ allows
|
||||
* a write() beyond the 2GB limit to fail gracefully with E2BIG
|
||||
* rather than terminate the process. */
|
||||
sa.sa_handler = SIG_IGN;
|
||||
if (sigaction(SIGXFSZ, &sa, NULL) < 0)
|
||||
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00463)
|
||||
"sigaction(SIGXFSZ)");
|
||||
#endif
|
||||
#ifdef SIGPIPE
|
||||
sa.sa_handler = SIG_IGN;
|
||||
if (sigaction(SIGPIPE, &sa, NULL) < 0)
|
||||
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00464)
|
||||
"sigaction(SIGPIPE)");
|
||||
#endif
|
||||
|
||||
/* we want to ignore HUPs and AP_SIG_GRACEFUL while we're busy
|
||||
* processing one */
|
||||
sigaddset(&sa.sa_mask, SIGHUP);
|
||||
sigaddset(&sa.sa_mask, AP_SIG_GRACEFUL);
|
||||
sa.sa_handler = restart;
|
||||
if (sigaction(SIGHUP, &sa, NULL) < 0)
|
||||
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00465)
|
||||
"sigaction(SIGHUP)");
|
||||
if (sigaction(AP_SIG_GRACEFUL, &sa, NULL) < 0)
|
||||
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00466)
|
||||
"sigaction(" AP_SIG_GRACEFUL_STRING ")");
|
||||
#else
|
||||
if (!one_process) {
|
||||
#ifdef SIGXCPU
|
||||
apr_signal(SIGXCPU, SIG_DFL);
|
||||
#endif /* SIGXCPU */
|
||||
#ifdef SIGXFSZ
|
||||
apr_signal(SIGXFSZ, SIG_IGN);
|
||||
#endif /* SIGXFSZ */
|
||||
}
|
||||
|
||||
apr_signal(SIGTERM, sig_term);
|
||||
#ifdef SIGHUP
|
||||
apr_signal(SIGHUP, restart);
|
||||
#endif /* SIGHUP */
|
||||
#ifdef AP_SIG_GRACEFUL
|
||||
apr_signal(AP_SIG_GRACEFUL, restart);
|
||||
#endif /* AP_SIG_GRACEFUL */
|
||||
#ifdef AP_SIG_GRACEFUL_STOP
|
||||
apr_signal(AP_SIG_GRACEFUL_STOP, sig_term);
|
||||
#endif /* AP_SIG_GRACEFUL_STOP */
|
||||
#ifdef SIGPIPE
|
||||
apr_signal(SIGPIPE, SIG_IGN);
|
||||
#endif /* SIGPIPE */
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
static void notify_suspend(event_conn_state_t *cs)
|
||||
{
|
||||
ap_run_suspend_connection(cs->c, cs->r);
|
||||
@@ -2341,7 +2186,7 @@ static void *APR_THREAD_FUNC worker_thread(apr_thread_t * thd, void *dummy)
|
||||
|
||||
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 = retained->my_generation;
|
||||
ap_scoreboard_image->servers[process_slot][thread_slot].generation = retained->mpm->my_generation;
|
||||
ap_update_child_status_from_indexes(process_slot, thread_slot,
|
||||
SERVER_STARTING, NULL);
|
||||
|
||||
@@ -2701,15 +2546,15 @@ static void child_main(int child_num_arg, int child_bucket)
|
||||
apr_pool_t *pskip;
|
||||
int i;
|
||||
|
||||
mpm_state = AP_MPMQ_STARTING; /* for benefit of any hooks that run as this
|
||||
* child initializes
|
||||
*/
|
||||
/* for benefit of any hooks that run as this child initializes */
|
||||
retained->mpm->mpm_state = AP_MPMQ_STARTING;
|
||||
|
||||
ap_my_pid = getpid();
|
||||
ap_fatal_signal_child_setup(ap_server_conf);
|
||||
apr_pool_create(&pchild, pconf);
|
||||
|
||||
/* close unused listeners and pods */
|
||||
for (i = 0; i < retained->num_buckets; i++) {
|
||||
for (i = 0; i < retained->mpm->num_buckets; i++) {
|
||||
if (i != child_bucket) {
|
||||
ap_close_listeners_ex(all_buckets[i].listeners);
|
||||
ap_mpm_podx_close(all_buckets[i].pod);
|
||||
@@ -2787,7 +2632,7 @@ static void child_main(int child_num_arg, int child_bucket)
|
||||
clean_child_exit(APEXIT_CHILDSICK);
|
||||
}
|
||||
|
||||
mpm_state = AP_MPMQ_RUNNING;
|
||||
retained->mpm->mpm_state = AP_MPMQ_RUNNING;
|
||||
|
||||
/* If we are only running in one_process mode, we will want to
|
||||
* still handle signals. */
|
||||
@@ -2884,7 +2729,6 @@ static int make_child(server_rec * s, int slot, int bucket)
|
||||
if (one_process) {
|
||||
my_bucket = &all_buckets[0];
|
||||
|
||||
set_signals();
|
||||
event_note_child_started(slot, getpid());
|
||||
child_main(slot, 0);
|
||||
/* NOTREACHED */
|
||||
@@ -2952,7 +2796,7 @@ static void startup_children(int number_to_start)
|
||||
if (ap_scoreboard_image->parent[i].pid != 0) {
|
||||
continue;
|
||||
}
|
||||
if (make_child(ap_server_conf, i, i % retained->num_buckets) < 0) {
|
||||
if (make_child(ap_server_conf, i, i % retained->mpm->num_buckets) < 0) {
|
||||
break;
|
||||
}
|
||||
--number_to_start;
|
||||
@@ -2997,7 +2841,7 @@ static void perform_idle_server_maintenance(int child_bucket, int num_buckets)
|
||||
* This depends on the ordering of SERVER_READY and SERVER_STARTING.
|
||||
*/
|
||||
if (status <= SERVER_READY && !ps->quiescing && !ps->not_accepting
|
||||
&& ps->generation == retained->my_generation
|
||||
&& ps->generation == retained->mpm->my_generation
|
||||
&& ps->bucket == child_bucket)
|
||||
{
|
||||
++idle_thread_count;
|
||||
@@ -3026,7 +2870,7 @@ static void perform_idle_server_maintenance(int child_bucket, int num_buckets)
|
||||
else {
|
||||
/* looks like a basket case, as no child ever fully initialized; give up.
|
||||
*/
|
||||
shutdown_pending = 1;
|
||||
retained->mpm->shutdown_pending = 1;
|
||||
child_fatal = 1;
|
||||
ap_log_error(APLOG_MARK, APLOG_ALERT, 0,
|
||||
ap_server_conf, APLOGNO(02324)
|
||||
@@ -3138,7 +2982,7 @@ static void server_main_loop(int remaining_children_to_start, int num_buckets)
|
||||
apr_proc_t pid;
|
||||
int i;
|
||||
|
||||
while (!restart_pending && !shutdown_pending) {
|
||||
while (!retained->mpm->restart_pending && !retained->mpm->shutdown_pending) {
|
||||
ap_wait_or_timeout(&exitwhy, &status, &pid, pconf, ap_server_conf);
|
||||
|
||||
if (pid.pid != -1) {
|
||||
@@ -3152,8 +2996,8 @@ static void server_main_loop(int remaining_children_to_start, int num_buckets)
|
||||
*/
|
||||
if (child_slot < 0
|
||||
|| ap_get_scoreboard_process(child_slot)->generation
|
||||
== retained->my_generation) {
|
||||
shutdown_pending = 1;
|
||||
== retained->mpm->my_generation) {
|
||||
retained->mpm->shutdown_pending = 1;
|
||||
child_fatal = 1;
|
||||
/*
|
||||
* total_daemons counting will be off now, but as we
|
||||
@@ -3208,7 +3052,7 @@ static void server_main_loop(int remaining_children_to_start, int num_buckets)
|
||||
/* handled */
|
||||
}
|
||||
#endif
|
||||
else if (retained->is_graceful) {
|
||||
else if (retained->mpm->was_graceful) {
|
||||
/* Great, we've probably just lost a slot in the
|
||||
* scoreboard. Somehow we don't know about this child.
|
||||
*/
|
||||
@@ -3246,25 +3090,27 @@ static void server_main_loop(int remaining_children_to_start, int num_buckets)
|
||||
|
||||
static int event_run(apr_pool_t * _pconf, apr_pool_t * plog, server_rec * s)
|
||||
{
|
||||
int num_buckets = retained->num_buckets;
|
||||
int num_buckets = retained->mpm->num_buckets;
|
||||
int remaining_children_to_start;
|
||||
int i;
|
||||
|
||||
ap_log_pid(pconf, ap_pid_fname);
|
||||
|
||||
if (!retained->is_graceful) {
|
||||
if (!retained->mpm->was_graceful) {
|
||||
if (ap_run_pre_mpm(s->process->pool, SB_SHARED) != OK) {
|
||||
mpm_state = AP_MPMQ_STOPPING;
|
||||
retained->mpm->mpm_state = AP_MPMQ_STOPPING;
|
||||
return !OK;
|
||||
}
|
||||
/* fix the generation number in the global score; we just got a new,
|
||||
* cleared scoreboard
|
||||
*/
|
||||
ap_scoreboard_image->global->running_generation = retained->my_generation;
|
||||
ap_scoreboard_image->global->running_generation = retained->mpm->my_generation;
|
||||
}
|
||||
|
||||
restart_pending = shutdown_pending = 0;
|
||||
set_signals();
|
||||
if (!one_process) {
|
||||
ap_fatal_signal_setup(ap_server_conf, pconf);
|
||||
}
|
||||
ap_unixd_mpm_set_signals(pconf, one_process);
|
||||
|
||||
/* Don't thrash since num_buckets depends on the
|
||||
* system and the number of online CPU cores...
|
||||
@@ -3297,7 +3143,7 @@ static int event_run(apr_pool_t * _pconf, apr_pool_t * plog, server_rec * s)
|
||||
if (remaining_children_to_start > active_daemons_limit) {
|
||||
remaining_children_to_start = active_daemons_limit;
|
||||
}
|
||||
if (!retained->is_graceful) {
|
||||
if (!retained->mpm->was_graceful) {
|
||||
startup_children(remaining_children_to_start);
|
||||
remaining_children_to_start = 0;
|
||||
}
|
||||
@@ -3315,12 +3161,12 @@ static int event_run(apr_pool_t * _pconf, apr_pool_t * plog, server_rec * s)
|
||||
ap_log_command_line(plog, s);
|
||||
ap_log_mpm_common(s);
|
||||
|
||||
mpm_state = AP_MPMQ_RUNNING;
|
||||
retained->mpm->mpm_state = AP_MPMQ_RUNNING;
|
||||
|
||||
server_main_loop(remaining_children_to_start, num_buckets);
|
||||
mpm_state = AP_MPMQ_STOPPING;
|
||||
retained->mpm->mpm_state = AP_MPMQ_STOPPING;
|
||||
|
||||
if (shutdown_pending && !retained->is_graceful) {
|
||||
if (retained->mpm->shutdown_pending && retained->mpm->is_ungraceful) {
|
||||
/* Time to shut down:
|
||||
* Kill child processes, tell them to call child_exit, etc...
|
||||
*/
|
||||
@@ -3337,8 +3183,11 @@ static int event_run(apr_pool_t * _pconf, apr_pool_t * plog, server_rec * s)
|
||||
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0,
|
||||
ap_server_conf, APLOGNO(00491) "caught SIGTERM, shutting down");
|
||||
}
|
||||
|
||||
return DONE;
|
||||
} else if (shutdown_pending) {
|
||||
}
|
||||
|
||||
if (retained->mpm->shutdown_pending) {
|
||||
/* Time to gracefully shut down:
|
||||
* Kill child processes, tell them to call child_exit, etc...
|
||||
*/
|
||||
@@ -3368,7 +3217,7 @@ static int event_run(apr_pool_t * _pconf, apr_pool_t * plog, server_rec * s)
|
||||
}
|
||||
|
||||
/* Don't really exit until each child has finished */
|
||||
shutdown_pending = 0;
|
||||
retained->mpm->shutdown_pending = 0;
|
||||
do {
|
||||
/* Pause for a second */
|
||||
apr_sleep(apr_time_from_sec(1));
|
||||
@@ -3384,7 +3233,7 @@ static int event_run(apr_pool_t * _pconf, apr_pool_t * plog, server_rec * s)
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (!shutdown_pending && active_children &&
|
||||
} while (!retained->mpm->shutdown_pending && active_children &&
|
||||
(!ap_graceful_shutdown_timeout || apr_time_now() < cutoff));
|
||||
|
||||
/* We might be here because we received SIGTERM, either
|
||||
@@ -3401,8 +3250,6 @@ static int event_run(apr_pool_t * _pconf, apr_pool_t * plog, server_rec * s)
|
||||
}
|
||||
|
||||
/* we've been told to restart */
|
||||
apr_signal(SIGHUP, SIG_IGN);
|
||||
|
||||
if (one_process) {
|
||||
/* not worth thinking about */
|
||||
return DONE;
|
||||
@@ -3412,10 +3259,10 @@ static int event_run(apr_pool_t * _pconf, apr_pool_t * plog, server_rec * s)
|
||||
/* XXX: we really need to make sure this new generation number isn't in
|
||||
* use by any of the children.
|
||||
*/
|
||||
++retained->my_generation;
|
||||
ap_scoreboard_image->global->running_generation = retained->my_generation;
|
||||
++retained->mpm->my_generation;
|
||||
ap_scoreboard_image->global->running_generation = retained->mpm->my_generation;
|
||||
|
||||
if (retained->is_graceful) {
|
||||
if (!retained->mpm->is_ungraceful) {
|
||||
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, APLOGNO(00493)
|
||||
AP_SIG_GRACEFUL_STRING
|
||||
" received. Doing graceful restart");
|
||||
@@ -3516,7 +3363,7 @@ static int event_open_logs(apr_pool_t * p, apr_pool_t * plog,
|
||||
pconf = p;
|
||||
|
||||
/* the reverse of pre_config, we want this only the first time around */
|
||||
if (retained->module_loads == 1) {
|
||||
if (retained->mpm->module_loads == 1) {
|
||||
startup = 1;
|
||||
level_flags |= APLOG_STARTUP;
|
||||
}
|
||||
@@ -3531,9 +3378,9 @@ static int event_open_logs(apr_pool_t * p, apr_pool_t * plog,
|
||||
if (one_process) {
|
||||
num_buckets = 1;
|
||||
}
|
||||
else if (retained->is_graceful) {
|
||||
else if (retained->mpm->was_graceful) {
|
||||
/* Preserve the number of buckets on graceful restarts. */
|
||||
num_buckets = retained->num_buckets;
|
||||
num_buckets = retained->mpm->num_buckets;
|
||||
}
|
||||
if ((rv = ap_duplicate_listeners(pconf, ap_server_conf,
|
||||
&listen_buckets, &num_buckets))) {
|
||||
@@ -3555,25 +3402,25 @@ static int event_open_logs(apr_pool_t * p, apr_pool_t * plog,
|
||||
all_buckets[i].listeners = listen_buckets[i];
|
||||
}
|
||||
|
||||
if (retained->max_buckets < num_buckets) {
|
||||
if (retained->mpm->max_buckets < num_buckets) {
|
||||
int new_max, *new_ptr;
|
||||
new_max = retained->max_buckets * 2;
|
||||
new_max = retained->mpm->max_buckets * 2;
|
||||
if (new_max < num_buckets) {
|
||||
new_max = num_buckets;
|
||||
}
|
||||
new_ptr = (int *)apr_palloc(ap_pglobal, new_max * sizeof(int));
|
||||
memcpy(new_ptr, retained->idle_spawn_rate,
|
||||
retained->num_buckets * sizeof(int));
|
||||
retained->mpm->num_buckets * sizeof(int));
|
||||
retained->idle_spawn_rate = new_ptr;
|
||||
retained->max_buckets = new_max;
|
||||
retained->mpm->max_buckets = new_max;
|
||||
}
|
||||
if (retained->num_buckets < num_buckets) {
|
||||
if (retained->mpm->num_buckets < num_buckets) {
|
||||
int rate_max = 1;
|
||||
/* If new buckets are added, set their idle spawn rate to
|
||||
* the highest so far, so that they get filled as quickly
|
||||
* as the existing ones.
|
||||
*/
|
||||
for (i = 0; i < retained->num_buckets; i++) {
|
||||
for (i = 0; i < retained->mpm->num_buckets; i++) {
|
||||
if (rate_max < retained->idle_spawn_rate[i]) {
|
||||
rate_max = retained->idle_spawn_rate[i];
|
||||
}
|
||||
@@ -3582,7 +3429,7 @@ static int event_open_logs(apr_pool_t * p, apr_pool_t * plog,
|
||||
retained->idle_spawn_rate[i] = rate_max;
|
||||
}
|
||||
}
|
||||
retained->num_buckets = num_buckets;
|
||||
retained->mpm->num_buckets = num_buckets;
|
||||
|
||||
/* for skiplist */
|
||||
srand((unsigned int)apr_time_now());
|
||||
@@ -3595,8 +3442,7 @@ static int event_pre_config(apr_pool_t * pconf, apr_pool_t * plog,
|
||||
int no_detach, debug, foreground;
|
||||
apr_status_t rv;
|
||||
const char *userdata_key = "mpm_event_module";
|
||||
|
||||
mpm_state = AP_MPMQ_STARTING;
|
||||
int test_atomics = 0;
|
||||
|
||||
debug = ap_exists_config_define("DEBUG");
|
||||
|
||||
@@ -3610,15 +3456,24 @@ static int event_pre_config(apr_pool_t * pconf, apr_pool_t * plog,
|
||||
foreground = ap_exists_config_define("FOREGROUND");
|
||||
}
|
||||
|
||||
/* sigh, want this only the second time around */
|
||||
retained = ap_retained_data_get(userdata_key);
|
||||
if (!retained) {
|
||||
retained = ap_retained_data_create(userdata_key, sizeof(*retained));
|
||||
retained->mpm = ap_unixd_mpm_get_retained_data();
|
||||
retained->max_daemons_limit = -1;
|
||||
if (retained->mpm->module_loads) {
|
||||
test_atomics = 1;
|
||||
}
|
||||
}
|
||||
++retained->module_loads;
|
||||
if (retained->module_loads == 2) {
|
||||
/* test for correct operation of fdqueue */
|
||||
retained->mpm->mpm_state = AP_MPMQ_STARTING;
|
||||
if (retained->mpm->baton != retained) {
|
||||
retained->mpm->was_graceful = 0;
|
||||
retained->mpm->baton = retained;
|
||||
}
|
||||
++retained->mpm->module_loads;
|
||||
|
||||
/* test once for correct operation of fdqueue */
|
||||
if (test_atomics || retained->mpm->module_loads == 2) {
|
||||
static apr_uint32_t foo1, foo2;
|
||||
|
||||
apr_atomic_set32(&foo1, 100);
|
||||
@@ -3628,7 +3483,10 @@ static int event_pre_config(apr_pool_t * pconf, apr_pool_t * plog,
|
||||
"atomics not working as expected - add32 of negative number");
|
||||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* sigh, want this only the second time around */
|
||||
if (retained->mpm->module_loads == 2) {
|
||||
rv = apr_pollset_create(&event_pollset, 1, plog,
|
||||
APR_POLLSET_THREADSAFE | APR_POLLSET_NOCOPY);
|
||||
if (rv != APR_SUCCESS) {
|
||||
@@ -3739,7 +3597,7 @@ static int event_check_config(apr_pool_t *p, apr_pool_t *plog,
|
||||
int startup = 0;
|
||||
|
||||
/* the reverse of pre_config, we want this only the first time around */
|
||||
if (retained->module_loads == 1) {
|
||||
if (retained->mpm->module_loads == 1) {
|
||||
startup = 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,6 @@ static motorz_core_t *g_motorz_core;
|
||||
static int threads_per_child = 16;
|
||||
static int ap_num_kids = DEFAULT_START_DAEMON;
|
||||
static int thread_limit = MAX_THREAD_LIMIT/10;
|
||||
static int mpm_state = AP_MPMQ_STARTING;
|
||||
|
||||
/* 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
|
||||
@@ -43,7 +42,6 @@ static apr_pool_t *pchild; /* Pool for httpd child stuff */
|
||||
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 int num_buckets; /* Number of listeners buckets */
|
||||
static motorz_child_bucket *all_buckets, /* All listeners buckets */
|
||||
*my_bucket; /* Current child bucket */
|
||||
|
||||
@@ -579,13 +577,15 @@ static void motorz_note_child_started(motorz_core_t *mz, int slot, pid_t pid)
|
||||
ap_scoreboard_image->parent[slot].pid = pid;
|
||||
ap_run_child_status(ap_server_conf,
|
||||
ap_scoreboard_image->parent[slot].pid,
|
||||
mz->my_generation, slot, MPM_CHILD_STARTED);
|
||||
mz->mpm->my_generation, slot, MPM_CHILD_STARTED);
|
||||
}
|
||||
|
||||
/* a clean exit from a child with proper cleanup */
|
||||
static void clean_child_exit(int code)
|
||||
{
|
||||
mpm_state = AP_MPMQ_STOPPING;
|
||||
motorz_core_t *mz = motorz_core_get();
|
||||
|
||||
mz->mpm->mpm_state = AP_MPMQ_STOPPING;
|
||||
|
||||
apr_signal(SIGHUP, SIG_IGN);
|
||||
apr_signal(SIGTERM, SIG_IGN);
|
||||
@@ -610,7 +610,7 @@ static apr_status_t accept_mutex_on(void)
|
||||
if (rv != APR_SUCCESS) {
|
||||
const char *msg = "couldn't grab the accept mutex";
|
||||
|
||||
if (mz->my_generation !=
|
||||
if (mz->mpm->my_generation !=
|
||||
ap_scoreboard_image->global->running_generation) {
|
||||
ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, ap_server_conf, APLOGNO(02855) "%s", msg);
|
||||
clean_child_exit(0);
|
||||
@@ -630,7 +630,7 @@ static apr_status_t accept_mutex_off(void)
|
||||
if (rv != APR_SUCCESS) {
|
||||
const char *msg = "couldn't release the accept mutex";
|
||||
|
||||
if (mz->my_generation !=
|
||||
if (mz->mpm->my_generation !=
|
||||
ap_scoreboard_image->global->running_generation) {
|
||||
ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, ap_server_conf, APLOGNO(02857) "%s", msg);
|
||||
/* don't exit here... we have a connection to
|
||||
@@ -703,10 +703,10 @@ static int motorz_query(int query_code, int *result, apr_status_t *rv)
|
||||
*result = ap_num_kids;
|
||||
break;
|
||||
case AP_MPMQ_MPM_STATE:
|
||||
*result = mpm_state;
|
||||
*result = mz->mpm->mpm_state;
|
||||
break;
|
||||
case AP_MPMQ_GENERATION:
|
||||
*result = mz->my_generation;
|
||||
*result = mz->mpm->my_generation;
|
||||
break;
|
||||
default:
|
||||
*rv = APR_ENOTIMPL;
|
||||
@@ -729,132 +729,20 @@ static void just_die(int sig)
|
||||
clean_child_exit(0);
|
||||
}
|
||||
|
||||
/* volatile because they're updated from a signal handler */
|
||||
static int volatile shutdown_pending;
|
||||
static int volatile restart_pending;
|
||||
/* volatile because it's updated from a signal handler */
|
||||
static int volatile die_now = 0;
|
||||
|
||||
static void stop_listening(int sig)
|
||||
{
|
||||
mpm_state = AP_MPMQ_STOPPING;
|
||||
motorz_core_t *mz = motorz_core_get();
|
||||
|
||||
mz->mpm->mpm_state = AP_MPMQ_STOPPING;
|
||||
ap_close_listeners_ex(my_bucket->listeners);
|
||||
|
||||
/* For a graceful stop, we want the child to exit when done */
|
||||
die_now = 1;
|
||||
}
|
||||
|
||||
static void sig_term(int sig)
|
||||
{
|
||||
motorz_core_t *mz = motorz_core_get();
|
||||
if (shutdown_pending == 1) {
|
||||
/* Um, is this _probably_ not an error, if the user has
|
||||
* tried to do a shutdown twice quickly, so we won't
|
||||
* worry about reporting it.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
mpm_state = AP_MPMQ_STOPPING;
|
||||
shutdown_pending = 1;
|
||||
mz->is_graceful = (sig == AP_SIG_GRACEFUL_STOP);
|
||||
}
|
||||
|
||||
/* restart() is the signal handler for SIGHUP and AP_SIG_GRACEFUL
|
||||
* in the parent process, unless running in ONE_PROCESS mode
|
||||
*/
|
||||
static void restart(int sig)
|
||||
{
|
||||
motorz_core_t *mz = motorz_core_get();
|
||||
if (restart_pending == 1) {
|
||||
/* Probably not an error - don't bother reporting it */
|
||||
return;
|
||||
}
|
||||
mpm_state = AP_MPMQ_STOPPING;
|
||||
restart_pending = 1;
|
||||
mz->is_graceful = (sig == AP_SIG_GRACEFUL);
|
||||
}
|
||||
|
||||
static void set_signals(void)
|
||||
{
|
||||
#ifndef NO_USE_SIGACTION
|
||||
struct sigaction sa;
|
||||
#endif
|
||||
|
||||
if (!one_process) {
|
||||
ap_fatal_signal_setup(ap_server_conf, pconf);
|
||||
}
|
||||
|
||||
#ifndef NO_USE_SIGACTION
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_flags = 0;
|
||||
|
||||
sa.sa_handler = sig_term;
|
||||
if (sigaction(SIGTERM, &sa, NULL) < 0)
|
||||
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(02859) "sigaction(SIGTERM)");
|
||||
#ifdef AP_SIG_GRACEFUL_STOP
|
||||
if (sigaction(AP_SIG_GRACEFUL_STOP, &sa, NULL) < 0)
|
||||
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(02860)
|
||||
"sigaction(" AP_SIG_GRACEFUL_STOP_STRING ")");
|
||||
#endif
|
||||
#ifdef SIGINT
|
||||
if (sigaction(SIGINT, &sa, NULL) < 0)
|
||||
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(02861) "sigaction(SIGINT)");
|
||||
#endif
|
||||
#ifdef SIGXCPU
|
||||
sa.sa_handler = SIG_DFL;
|
||||
if (sigaction(SIGXCPU, &sa, NULL) < 0)
|
||||
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(02862) "sigaction(SIGXCPU)");
|
||||
#endif
|
||||
#ifdef SIGXFSZ
|
||||
/* For systems following the LFS standard, ignoring SIGXFSZ allows
|
||||
* a write() beyond the 2GB limit to fail gracefully with E2BIG
|
||||
* rather than terminate the process. */
|
||||
sa.sa_handler = SIG_IGN;
|
||||
if (sigaction(SIGXFSZ, &sa, NULL) < 0)
|
||||
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(02863) "sigaction(SIGXFSZ)");
|
||||
#endif
|
||||
#ifdef SIGPIPE
|
||||
sa.sa_handler = SIG_IGN;
|
||||
if (sigaction(SIGPIPE, &sa, NULL) < 0)
|
||||
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(02864) "sigaction(SIGPIPE)");
|
||||
#endif
|
||||
|
||||
/* we want to ignore HUPs and AP_SIG_GRACEFUL while we're busy
|
||||
* processing one
|
||||
*/
|
||||
sigaddset(&sa.sa_mask, SIGHUP);
|
||||
sigaddset(&sa.sa_mask, AP_SIG_GRACEFUL);
|
||||
sa.sa_handler = restart;
|
||||
if (sigaction(SIGHUP, &sa, NULL) < 0)
|
||||
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(02865) "sigaction(SIGHUP)");
|
||||
if (sigaction(AP_SIG_GRACEFUL, &sa, NULL) < 0)
|
||||
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(02866) "sigaction(" AP_SIG_GRACEFUL_STRING ")");
|
||||
#else
|
||||
if (!one_process) {
|
||||
#ifdef SIGXCPU
|
||||
apr_signal(SIGXCPU, SIG_DFL);
|
||||
#endif /* SIGXCPU */
|
||||
#ifdef SIGXFSZ
|
||||
apr_signal(SIGXFSZ, SIG_IGN);
|
||||
#endif /* SIGXFSZ */
|
||||
}
|
||||
|
||||
apr_signal(SIGTERM, sig_term);
|
||||
#ifdef SIGHUP
|
||||
apr_signal(SIGHUP, restart);
|
||||
#endif /* SIGHUP */
|
||||
#ifdef AP_SIG_GRACEFUL
|
||||
apr_signal(AP_SIG_GRACEFUL, restart);
|
||||
#endif /* AP_SIG_GRACEFUL */
|
||||
#ifdef AP_SIG_GRACEFUL_STOP
|
||||
apr_signal(AP_SIG_GRACEFUL_STOP, sig_term);
|
||||
#endif /* AP_SIG_GRACEFUL */
|
||||
#ifdef SIGPIPE
|
||||
apr_signal(SIGPIPE, SIG_IGN);
|
||||
#endif /* SIGPIPE */
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
* Child process main loop.
|
||||
* The following vars are static to avoid getting clobbered by longjmp();
|
||||
@@ -876,9 +764,8 @@ static void child_main(motorz_core_t *mz, int child_num_arg, int child_bucket)
|
||||
ap_sb_handle_t *sbh;
|
||||
const char *lockfile;
|
||||
|
||||
mpm_state = AP_MPMQ_STARTING; /* for benefit of any hooks that run as this
|
||||
* child initializes
|
||||
*/
|
||||
/* for benefit of any hooks that run as this child initializes */
|
||||
mz->mpm->mpm_state = AP_MPMQ_STARTING;
|
||||
|
||||
my_child_num = child_num_arg;
|
||||
ap_my_pid = getpid();
|
||||
@@ -898,7 +785,7 @@ static void child_main(motorz_core_t *mz, int child_num_arg, int child_bucket)
|
||||
#endif
|
||||
|
||||
/* close unused listeners and pods */
|
||||
for (i = 0; i < num_buckets; i++) {
|
||||
for (i = 0; i < mz->mpm->num_buckets; i++) {
|
||||
if (i != child_bucket) {
|
||||
ap_close_listeners_ex(all_buckets[i].listeners);
|
||||
ap_mpm_pod_close(all_buckets[i].pod);
|
||||
@@ -984,12 +871,15 @@ static void child_main(motorz_core_t *mz, int child_num_arg, int child_bucket)
|
||||
lr->accept_func = ap_unixd_accept;
|
||||
}
|
||||
|
||||
mpm_state = AP_MPMQ_RUNNING;
|
||||
mz->mpm->mpm_state = AP_MPMQ_RUNNING;
|
||||
|
||||
/* die_now is set when AP_SIG_GRACEFUL is received in the child;
|
||||
* shutdown_pending is set when SIGTERM is received when running
|
||||
* in single process mode. */
|
||||
while (!die_now && !shutdown_pending) {
|
||||
* {shutdown,restart}_pending are set when a signal is received while
|
||||
* running in single process mode.
|
||||
*/
|
||||
while (!die_now
|
||||
&& !mz->mpm->shutdown_pending
|
||||
&& !mz->mpm->restart_pending) {
|
||||
/*
|
||||
* (Re)initialize this child to a pre-connection state.
|
||||
*/
|
||||
@@ -1047,7 +937,7 @@ static void child_main(motorz_core_t *mz, int child_num_arg, int child_bucket)
|
||||
if (ap_mpm_pod_check(my_bucket->pod) == APR_SUCCESS) { /* selected as idle? */
|
||||
die_now = 1;
|
||||
}
|
||||
else if (mz->my_generation !=
|
||||
else if (mz->mpm->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?
|
||||
@@ -1070,13 +960,6 @@ static int make_child(motorz_core_t *mz, server_rec *s, int slot, int bucket)
|
||||
if (one_process) {
|
||||
my_bucket = &all_buckets[0];
|
||||
|
||||
apr_signal(SIGHUP, sig_term);
|
||||
/* Don't catch AP_SIG_GRACEFUL in ONE_PROCESS mode :) */
|
||||
apr_signal(SIGINT, sig_term);
|
||||
#ifdef SIGQUIT
|
||||
apr_signal(SIGQUIT, SIG_DFL);
|
||||
#endif
|
||||
apr_signal(SIGTERM, sig_term);
|
||||
motorz_note_child_started(mz, slot, getpid());
|
||||
child_main(mz, slot, 0);
|
||||
/* NOTREACHED */
|
||||
@@ -1154,7 +1037,7 @@ static void startup_children(motorz_core_t *mz, int number_to_start)
|
||||
if (ap_scoreboard_image->servers[i][0].status != SERVER_DEAD) {
|
||||
continue;
|
||||
}
|
||||
if (make_child(mz, ap_server_conf, i, i % num_buckets) < 0) {
|
||||
if (make_child(mz, ap_server_conf, i, i % mz->mpm->num_buckets) < 0) {
|
||||
break;
|
||||
}
|
||||
--number_to_start;
|
||||
@@ -1192,12 +1075,12 @@ static void perform_idle_server_maintenance(motorz_core_t *mz, apr_pool_t *p)
|
||||
* shut down gracefully, in case it happened to pick up a request
|
||||
* while we were counting
|
||||
*/
|
||||
bucket_kill_child_record = (bucket_kill_child_record + 1) % num_buckets;
|
||||
bucket_kill_child_record = (bucket_kill_child_record + 1) % mz->mpm->num_buckets;
|
||||
ap_mpm_pod_signal(all_buckets[bucket_kill_child_record].pod);
|
||||
}
|
||||
else if (active < ap_num_kids) {
|
||||
bucket_make_child_record++;
|
||||
bucket_make_child_record %= num_buckets;
|
||||
bucket_make_child_record %= mz->mpm->num_buckets;
|
||||
make_child(mz, ap_server_conf, free_slots[0],
|
||||
bucket_make_child_record);
|
||||
}
|
||||
@@ -1216,19 +1099,21 @@ static int motorz_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
|
||||
|
||||
ap_log_pid(pconf, ap_pid_fname);
|
||||
|
||||
if (!mz->is_graceful) {
|
||||
if (!mz->mpm->was_graceful) {
|
||||
if (ap_run_pre_mpm(s->process->pool, SB_SHARED) != OK) {
|
||||
mpm_state = AP_MPMQ_STOPPING;
|
||||
mz->mpm->mpm_state = AP_MPMQ_STOPPING;
|
||||
return !OK;
|
||||
}
|
||||
/* fix the generation number in the global score; we just got a new,
|
||||
* cleared scoreboard
|
||||
*/
|
||||
ap_scoreboard_image->global->running_generation = mz->my_generation;
|
||||
ap_scoreboard_image->global->running_generation = mz->mpm->my_generation;
|
||||
}
|
||||
|
||||
restart_pending = shutdown_pending = 0;
|
||||
set_signals();
|
||||
if (!one_process) {
|
||||
ap_fatal_signal_setup(ap_server_conf, pconf);
|
||||
}
|
||||
ap_unixd_mpm_set_signals(pconf, one_process);
|
||||
|
||||
if (one_process) {
|
||||
AP_MONCONTROL(1);
|
||||
@@ -1241,8 +1126,8 @@ static int motorz_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
|
||||
/* Don't thrash since num_buckets depends on the
|
||||
* system and the number of online CPU cores...
|
||||
*/
|
||||
if (ap_num_kids < num_buckets)
|
||||
ap_num_kids = num_buckets;
|
||||
if (ap_num_kids < mz->mpm->num_buckets)
|
||||
ap_num_kids = mz->mpm->num_buckets;
|
||||
|
||||
/* If we're doing a graceful_restart then we're going to see a lot
|
||||
* of children exiting immediately when we get into the main loop
|
||||
@@ -1253,7 +1138,7 @@ static int motorz_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
|
||||
* supposed to start up without the 1 second penalty between each fork.
|
||||
*/
|
||||
remaining_children_to_start = ap_num_kids;
|
||||
if (!mz->is_graceful) {
|
||||
if (!mz->mpm->was_graceful) {
|
||||
startup_children(mz, remaining_children_to_start);
|
||||
remaining_children_to_start = 0;
|
||||
}
|
||||
@@ -1272,9 +1157,9 @@ static int motorz_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
|
||||
: "none",
|
||||
apr_proc_mutex_defname());
|
||||
|
||||
mpm_state = AP_MPMQ_RUNNING;
|
||||
mz->mpm->mpm_state = AP_MPMQ_RUNNING;
|
||||
|
||||
while (!restart_pending && !shutdown_pending) {
|
||||
while (!mz->mpm->restart_pending && !mz->mpm->shutdown_pending) {
|
||||
int child_slot;
|
||||
apr_exit_why_e exitwhy;
|
||||
int status, processed_status;
|
||||
@@ -1298,8 +1183,8 @@ static int motorz_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
|
||||
*/
|
||||
if (child_slot < 0
|
||||
|| ap_get_scoreboard_process(child_slot)->generation
|
||||
== mz->my_generation) {
|
||||
mpm_state = AP_MPMQ_STOPPING;
|
||||
== mz->mpm->my_generation) {
|
||||
mz->mpm->mpm_state = AP_MPMQ_STOPPING;
|
||||
return !OK;
|
||||
}
|
||||
else {
|
||||
@@ -1330,7 +1215,7 @@ static int motorz_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
|
||||
/* handled */
|
||||
#endif
|
||||
}
|
||||
else if (mz->is_graceful) {
|
||||
else if (mz->mpm->was_graceful) {
|
||||
/* Great, we've probably just lost a slot in the
|
||||
* scoreboard. Somehow we don't know about this
|
||||
* child.
|
||||
@@ -1363,9 +1248,9 @@ static int motorz_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
|
||||
perform_idle_server_maintenance(mz, pconf);
|
||||
}
|
||||
|
||||
mpm_state = AP_MPMQ_STOPPING;
|
||||
mz->mpm->mpm_state = AP_MPMQ_STOPPING;
|
||||
|
||||
if (shutdown_pending && !mz->is_graceful) {
|
||||
if (mz->mpm->shutdown_pending && mz->mpm->is_ungraceful) {
|
||||
/* Time to shut down:
|
||||
* Kill child processes, tell them to call child_exit, etc...
|
||||
*/
|
||||
@@ -1381,7 +1266,9 @@ static int motorz_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
|
||||
"caught SIGTERM, shutting down");
|
||||
|
||||
return DONE;
|
||||
} else if (shutdown_pending) {
|
||||
}
|
||||
|
||||
if (mz->mpm->shutdown_pending) {
|
||||
/* Time to perform a graceful shut down:
|
||||
* Reap the inactive children, and ask the active ones
|
||||
* to close their listeners, then wait until they are
|
||||
@@ -1394,7 +1281,7 @@ static int motorz_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
|
||||
ap_close_listeners();
|
||||
|
||||
/* kill off the idle ones */
|
||||
for (i = 0; i < num_buckets; i++) {
|
||||
for (i = 0; i < mz->mpm->num_buckets; i++) {
|
||||
ap_mpm_pod_killpg(all_buckets[i].pod, mz->max_daemons_limit);
|
||||
}
|
||||
|
||||
@@ -1422,7 +1309,7 @@ static int motorz_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
|
||||
}
|
||||
|
||||
/* Don't really exit until each child has finished */
|
||||
shutdown_pending = 0;
|
||||
mz->mpm->shutdown_pending = 0;
|
||||
do {
|
||||
/* Pause for a second */
|
||||
sleep(1);
|
||||
@@ -1438,7 +1325,7 @@ static int motorz_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (!shutdown_pending && active_children &&
|
||||
} while (!mz->mpm->shutdown_pending && active_children &&
|
||||
(!ap_graceful_shutdown_timeout || apr_time_now() < cutoff));
|
||||
|
||||
/* We might be here because we received SIGTERM, either
|
||||
@@ -1451,8 +1338,6 @@ static int motorz_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
|
||||
}
|
||||
|
||||
/* we've been told to restart */
|
||||
apr_signal(SIGHUP, SIG_IGN);
|
||||
apr_signal(AP_SIG_GRACEFUL, SIG_IGN);
|
||||
if (one_process) {
|
||||
/* not worth thinking about */
|
||||
return DONE;
|
||||
@@ -1462,15 +1347,15 @@ static int motorz_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
|
||||
/* XXX: we really need to make sure this new generation number isn't in
|
||||
* use by any of the children.
|
||||
*/
|
||||
++mz->my_generation;
|
||||
ap_scoreboard_image->global->running_generation = mz->my_generation;
|
||||
++mz->mpm->my_generation;
|
||||
ap_scoreboard_image->global->running_generation = mz->mpm->my_generation;
|
||||
|
||||
if (mz->is_graceful) {
|
||||
if (!mz->mpm->is_ungraceful) {
|
||||
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, APLOGNO(02882)
|
||||
"Graceful restart requested, doing restart");
|
||||
|
||||
/* kill off the idle ones */
|
||||
for (i = 0; i < num_buckets; i++) {
|
||||
for (i = 0; i < mz->mpm->num_buckets; i++) {
|
||||
ap_mpm_pod_killpg(all_buckets[i].pod, mz->max_daemons_limit);
|
||||
}
|
||||
|
||||
@@ -1523,7 +1408,7 @@ static int motorz_open_logs(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp,
|
||||
pconf = p;
|
||||
|
||||
/* the reverse of pre_config, we want this only the first time around */
|
||||
if (mz->module_loads == 1) {
|
||||
if (mz->mpm->module_loads == 1) {
|
||||
startup = 1;
|
||||
level_flags |= APLOG_STARTUP;
|
||||
}
|
||||
@@ -1536,22 +1421,22 @@ static int motorz_open_logs(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp,
|
||||
}
|
||||
|
||||
if (one_process) {
|
||||
num_buckets = 1;
|
||||
mz->mpm->num_buckets = 1;
|
||||
}
|
||||
else if (!mz->is_graceful) { /* Preserve the number of buckets
|
||||
on graceful restarts. */
|
||||
num_buckets = 0;
|
||||
else if (!mz->mpm->was_graceful) {
|
||||
/* Preserve the number of buckets on graceful restarts. */
|
||||
mz->mpm->num_buckets = 0;
|
||||
}
|
||||
if ((rv = ap_duplicate_listeners(pconf, ap_server_conf,
|
||||
&listen_buckets, &num_buckets))) {
|
||||
&listen_buckets, &mz->mpm->num_buckets))) {
|
||||
ap_log_error(APLOG_MARK, APLOG_CRIT | level_flags, rv,
|
||||
(startup ? NULL : s), APLOGNO(03276)
|
||||
"could not duplicate listeners");
|
||||
return !OK;
|
||||
}
|
||||
all_buckets = apr_pcalloc(pconf, num_buckets *
|
||||
all_buckets = apr_pcalloc(pconf, mz->mpm->num_buckets *
|
||||
sizeof(motorz_child_bucket));
|
||||
for (i = 0; i < num_buckets; i++) {
|
||||
for (i = 0; i < mz->mpm->num_buckets; i++) {
|
||||
if ((rv = ap_mpm_pod_open(pconf, &all_buckets[i].pod))) {
|
||||
ap_log_error(APLOG_MARK, APLOG_CRIT | level_flags, rv,
|
||||
(startup ? NULL : s), APLOGNO(03277)
|
||||
@@ -1581,8 +1466,6 @@ static int motorz_pre_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp)
|
||||
const char *userdata_key = "mpm_motorz_module";
|
||||
motorz_core_t *mz;
|
||||
|
||||
mpm_state = AP_MPMQ_STARTING;
|
||||
|
||||
debug = ap_exists_config_define("DEBUG");
|
||||
|
||||
if (debug) {
|
||||
@@ -1598,16 +1481,23 @@ static int motorz_pre_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp)
|
||||
|
||||
ap_mutex_register(p, AP_ACCEPT_MUTEX_TYPE, NULL, APR_LOCK_DEFAULT, 0);
|
||||
|
||||
/* sigh, want this only the second time around */
|
||||
mz = g_motorz_core = ap_retained_data_get(userdata_key);
|
||||
if (!g_motorz_core) {
|
||||
mz = g_motorz_core = ap_retained_data_create(userdata_key, sizeof(*g_motorz_core));
|
||||
mz->mpm = ap_unixd_mpm_get_retained_data();
|
||||
mz->max_daemons_limit = -1;
|
||||
mz->timeout_ring = motorz_timer_ring;
|
||||
mz->pollset = motorz_pollset;
|
||||
}
|
||||
++mz->module_loads;
|
||||
if (mz->module_loads == 2) {
|
||||
mz->mpm->mpm_state = AP_MPMQ_STARTING;
|
||||
if (mz->mpm->baton != mz) {
|
||||
mz->mpm->was_graceful = 0;
|
||||
mz->mpm->baton = mz;
|
||||
}
|
||||
++mz->mpm->module_loads;
|
||||
|
||||
/* sigh, want this only the second time around */
|
||||
if (mz->mpm->module_loads == 2) {
|
||||
if (!one_process && !foreground) {
|
||||
/* before we detach, setup crash handlers to log to errorlog */
|
||||
ap_fatal_signal_setup(ap_server_conf, pconf);
|
||||
@@ -1645,7 +1535,7 @@ static int motorz_check_config(apr_pool_t *p, apr_pool_t *plog,
|
||||
motorz_core_t *mz = motorz_core_get();
|
||||
|
||||
/* the reverse of pre_config, we want this only the first time around */
|
||||
if (mz->module_loads == 1) {
|
||||
if (mz->mpm->module_loads == 1) {
|
||||
startup = 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -115,10 +115,9 @@
|
||||
*/
|
||||
typedef struct motorz_core_t motorz_core_t;
|
||||
struct motorz_core_t {
|
||||
ap_unixd_mpm_retained_data *mpm;
|
||||
|
||||
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
|
||||
|
||||
@@ -94,17 +94,15 @@ static int ap_daemons_min_free=0;
|
||||
static int ap_daemons_max_free=0;
|
||||
static int ap_daemons_limit=0; /* MaxRequestWorkers */
|
||||
static int server_limit = 0;
|
||||
static int mpm_state = AP_MPMQ_STARTING;
|
||||
|
||||
/* data retained by prefork across load/unload of the module
|
||||
* allocated on first call to pre-config hook; located on
|
||||
* subsequent calls to pre-config hook
|
||||
*/
|
||||
typedef struct prefork_retained_data {
|
||||
ap_unixd_mpm_retained_data *mpm;
|
||||
|
||||
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
|
||||
@@ -131,7 +129,6 @@ typedef struct prefork_child_bucket {
|
||||
ap_listen_rec *listeners;
|
||||
apr_proc_mutex_t *mutex;
|
||||
} prefork_child_bucket;
|
||||
static int num_buckets; /* Number of listeners buckets */
|
||||
static prefork_child_bucket *all_buckets, /* All listeners buckets */
|
||||
*my_bucket; /* Current child bucket */
|
||||
|
||||
@@ -215,14 +212,14 @@ static void prefork_note_child_started(int slot, pid_t pid)
|
||||
ap_scoreboard_image->parent[slot].pid = pid;
|
||||
ap_run_child_status(ap_server_conf,
|
||||
ap_scoreboard_image->parent[slot].pid,
|
||||
retained->my_generation, slot, MPM_CHILD_STARTED);
|
||||
retained->mpm->my_generation, slot, MPM_CHILD_STARTED);
|
||||
}
|
||||
|
||||
/* a clean exit from a child with proper cleanup */
|
||||
static void clean_child_exit(int code) __attribute__ ((noreturn));
|
||||
static void clean_child_exit(int code)
|
||||
{
|
||||
mpm_state = AP_MPMQ_STOPPING;
|
||||
retained->mpm->mpm_state = AP_MPMQ_STOPPING;
|
||||
|
||||
apr_signal(SIGHUP, SIG_IGN);
|
||||
apr_signal(SIGTERM, SIG_IGN);
|
||||
@@ -246,7 +243,7 @@ static apr_status_t accept_mutex_on(void)
|
||||
if (rv != APR_SUCCESS) {
|
||||
const char *msg = "couldn't grab the accept mutex";
|
||||
|
||||
if (retained->my_generation !=
|
||||
if (retained->mpm->my_generation !=
|
||||
ap_scoreboard_image->global->running_generation) {
|
||||
ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, ap_server_conf, APLOGNO(00143) "%s", msg);
|
||||
clean_child_exit(0);
|
||||
@@ -265,7 +262,7 @@ static apr_status_t accept_mutex_off(void)
|
||||
if (rv != APR_SUCCESS) {
|
||||
const char *msg = "couldn't release the accept mutex";
|
||||
|
||||
if (retained->my_generation !=
|
||||
if (retained->mpm->my_generation !=
|
||||
ap_scoreboard_image->global->running_generation) {
|
||||
ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, ap_server_conf, APLOGNO(00145) "%s", msg);
|
||||
/* don't exit here... we have a connection to
|
||||
@@ -333,10 +330,10 @@ static int prefork_query(int query_code, int *result, apr_status_t *rv)
|
||||
*result = ap_daemons_limit;
|
||||
break;
|
||||
case AP_MPMQ_MPM_STATE:
|
||||
*result = mpm_state;
|
||||
*result = retained->mpm->mpm_state;
|
||||
break;
|
||||
case AP_MPMQ_GENERATION:
|
||||
*result = retained->my_generation;
|
||||
*result = retained->mpm->my_generation;
|
||||
break;
|
||||
default:
|
||||
*rv = APR_ENOTIMPL;
|
||||
@@ -359,130 +356,18 @@ static void just_die(int sig)
|
||||
clean_child_exit(0);
|
||||
}
|
||||
|
||||
/* volatile because they're updated from a signal handler */
|
||||
static int volatile shutdown_pending;
|
||||
static int volatile restart_pending;
|
||||
/* volatile because it's updated from a signal handler */
|
||||
static int volatile die_now = 0;
|
||||
|
||||
static void stop_listening(int sig)
|
||||
{
|
||||
mpm_state = AP_MPMQ_STOPPING;
|
||||
retained->mpm->mpm_state = AP_MPMQ_STOPPING;
|
||||
ap_close_listeners_ex(my_bucket->listeners);
|
||||
|
||||
/* For a graceful stop, we want the child to exit when done */
|
||||
die_now = 1;
|
||||
}
|
||||
|
||||
static void sig_term(int sig)
|
||||
{
|
||||
if (shutdown_pending == 1) {
|
||||
/* Um, is this _probably_ not an error, if the user has
|
||||
* tried to do a shutdown twice quickly, so we won't
|
||||
* worry about reporting it.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
mpm_state = AP_MPMQ_STOPPING;
|
||||
shutdown_pending = 1;
|
||||
retained->is_graceful = (sig == AP_SIG_GRACEFUL_STOP);
|
||||
}
|
||||
|
||||
/* restart() is the signal handler for SIGHUP and AP_SIG_GRACEFUL
|
||||
* in the parent process, unless running in ONE_PROCESS mode
|
||||
*/
|
||||
static void restart(int sig)
|
||||
{
|
||||
if (restart_pending == 1) {
|
||||
/* Probably not an error - don't bother reporting it */
|
||||
return;
|
||||
}
|
||||
mpm_state = AP_MPMQ_STOPPING;
|
||||
restart_pending = 1;
|
||||
retained->is_graceful = (sig == AP_SIG_GRACEFUL);
|
||||
}
|
||||
|
||||
static void set_signals(void)
|
||||
{
|
||||
#ifndef NO_USE_SIGACTION
|
||||
struct sigaction sa;
|
||||
#endif
|
||||
|
||||
if (!one_process) {
|
||||
ap_fatal_signal_setup(ap_server_conf, pconf);
|
||||
}
|
||||
|
||||
#ifndef NO_USE_SIGACTION
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_flags = 0;
|
||||
|
||||
sa.sa_handler = sig_term;
|
||||
if (sigaction(SIGTERM, &sa, NULL) < 0)
|
||||
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00147) "sigaction(SIGTERM)");
|
||||
#ifdef AP_SIG_GRACEFUL_STOP
|
||||
if (sigaction(AP_SIG_GRACEFUL_STOP, &sa, NULL) < 0)
|
||||
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00148)
|
||||
"sigaction(" AP_SIG_GRACEFUL_STOP_STRING ")");
|
||||
#endif
|
||||
#ifdef SIGINT
|
||||
if (sigaction(SIGINT, &sa, NULL) < 0)
|
||||
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00149) "sigaction(SIGINT)");
|
||||
#endif
|
||||
#ifdef SIGXCPU
|
||||
sa.sa_handler = SIG_DFL;
|
||||
if (sigaction(SIGXCPU, &sa, NULL) < 0)
|
||||
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00150) "sigaction(SIGXCPU)");
|
||||
#endif
|
||||
#ifdef SIGXFSZ
|
||||
/* For systems following the LFS standard, ignoring SIGXFSZ allows
|
||||
* a write() beyond the 2GB limit to fail gracefully with E2BIG
|
||||
* rather than terminate the process. */
|
||||
sa.sa_handler = SIG_IGN;
|
||||
if (sigaction(SIGXFSZ, &sa, NULL) < 0)
|
||||
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00151) "sigaction(SIGXFSZ)");
|
||||
#endif
|
||||
#ifdef SIGPIPE
|
||||
sa.sa_handler = SIG_IGN;
|
||||
if (sigaction(SIGPIPE, &sa, NULL) < 0)
|
||||
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00152) "sigaction(SIGPIPE)");
|
||||
#endif
|
||||
|
||||
/* we want to ignore HUPs and AP_SIG_GRACEFUL while we're busy
|
||||
* processing one
|
||||
*/
|
||||
sigaddset(&sa.sa_mask, SIGHUP);
|
||||
sigaddset(&sa.sa_mask, AP_SIG_GRACEFUL);
|
||||
sa.sa_handler = restart;
|
||||
if (sigaction(SIGHUP, &sa, NULL) < 0)
|
||||
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00153) "sigaction(SIGHUP)");
|
||||
if (sigaction(AP_SIG_GRACEFUL, &sa, NULL) < 0)
|
||||
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00154) "sigaction(" AP_SIG_GRACEFUL_STRING ")");
|
||||
#else
|
||||
if (!one_process) {
|
||||
#ifdef SIGXCPU
|
||||
apr_signal(SIGXCPU, SIG_DFL);
|
||||
#endif /* SIGXCPU */
|
||||
#ifdef SIGXFSZ
|
||||
apr_signal(SIGXFSZ, SIG_IGN);
|
||||
#endif /* SIGXFSZ */
|
||||
}
|
||||
|
||||
apr_signal(SIGTERM, sig_term);
|
||||
#ifdef SIGHUP
|
||||
apr_signal(SIGHUP, restart);
|
||||
#endif /* SIGHUP */
|
||||
#ifdef AP_SIG_GRACEFUL
|
||||
apr_signal(AP_SIG_GRACEFUL, restart);
|
||||
#endif /* AP_SIG_GRACEFUL */
|
||||
#ifdef AP_SIG_GRACEFUL_STOP
|
||||
apr_signal(AP_SIG_GRACEFUL_STOP, sig_term);
|
||||
#endif /* AP_SIG_GRACEFUL */
|
||||
#ifdef SIGPIPE
|
||||
apr_signal(SIGPIPE, SIG_IGN);
|
||||
#endif /* SIGPIPE */
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
* Child process main loop.
|
||||
* The following vars are static to avoid getting clobbered by longjmp();
|
||||
@@ -509,9 +394,8 @@ static void child_main(int child_num_arg, int child_bucket)
|
||||
int last_poll_idx = 0;
|
||||
const char *lockfile;
|
||||
|
||||
mpm_state = AP_MPMQ_STARTING; /* for benefit of any hooks that run as this
|
||||
* child initializes
|
||||
*/
|
||||
/* for benefit of any hooks that run as this child initializes */
|
||||
retained->mpm->mpm_state = AP_MPMQ_STARTING;
|
||||
|
||||
my_child_num = child_num_arg;
|
||||
ap_my_pid = getpid();
|
||||
@@ -537,7 +421,7 @@ static void child_main(int child_num_arg, int child_bucket)
|
||||
apr_pool_tag(ptrans, "transaction");
|
||||
|
||||
/* close unused listeners and pods */
|
||||
for (i = 0; i < num_buckets; i++) {
|
||||
for (i = 0; i < retained->mpm->num_buckets; i++) {
|
||||
if (i != child_bucket) {
|
||||
ap_close_listeners_ex(all_buckets[i].listeners);
|
||||
ap_mpm_pod_close(all_buckets[i].pod);
|
||||
@@ -603,14 +487,17 @@ static void child_main(int child_num_arg, int child_bucket)
|
||||
lr->accept_func = ap_unixd_accept;
|
||||
}
|
||||
|
||||
mpm_state = AP_MPMQ_RUNNING;
|
||||
retained->mpm->mpm_state = AP_MPMQ_RUNNING;
|
||||
|
||||
bucket_alloc = apr_bucket_alloc_create(pchild);
|
||||
|
||||
/* die_now is set when AP_SIG_GRACEFUL is received in the child;
|
||||
* shutdown_pending is set when SIGTERM is received when running
|
||||
* in single process mode. */
|
||||
while (!die_now && !shutdown_pending) {
|
||||
* {shutdown,restart}_pending are set when a signal is received while
|
||||
* running in single process mode.
|
||||
*/
|
||||
while (!die_now
|
||||
&& !retained->mpm->shutdown_pending
|
||||
&& !retained->mpm->restart_pending) {
|
||||
conn_rec *current_conn;
|
||||
void *csd;
|
||||
|
||||
@@ -648,7 +535,8 @@ static void child_main(int child_num_arg, int child_bucket)
|
||||
* poll if already signalled
|
||||
*/
|
||||
if (die_now /* in graceful stop/restart */
|
||||
|| (one_process && shutdown_pending)) {
|
||||
|| retained->mpm->shutdown_pending
|
||||
|| retained->mpm->restart_pending) {
|
||||
SAFE_ACCEPT(accept_mutex_off());
|
||||
clean_child_exit(0);
|
||||
}
|
||||
@@ -737,7 +625,7 @@ static void child_main(int child_num_arg, int child_bucket)
|
||||
if (ap_mpm_pod_check(my_bucket->pod) == APR_SUCCESS) { /* selected as idle? */
|
||||
die_now = 1;
|
||||
}
|
||||
else if (retained->my_generation !=
|
||||
else if (retained->mpm->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?
|
||||
@@ -761,13 +649,6 @@ static int make_child(server_rec *s, int slot, int bucket)
|
||||
if (one_process) {
|
||||
my_bucket = &all_buckets[0];
|
||||
|
||||
apr_signal(SIGHUP, sig_term);
|
||||
/* Don't catch AP_SIG_GRACEFUL in ONE_PROCESS mode :) */
|
||||
apr_signal(SIGINT, sig_term);
|
||||
#ifdef SIGQUIT
|
||||
apr_signal(SIGQUIT, SIG_DFL);
|
||||
#endif
|
||||
apr_signal(SIGTERM, sig_term);
|
||||
prefork_note_child_started(slot, getpid());
|
||||
child_main(slot, 0);
|
||||
/* NOTREACHED */
|
||||
@@ -852,7 +733,7 @@ static void startup_children(int number_to_start)
|
||||
if (ap_scoreboard_image->servers[i][0].status != SERVER_DEAD) {
|
||||
continue;
|
||||
}
|
||||
if (make_child(ap_server_conf, i, i % num_buckets) < 0) {
|
||||
if (make_child(ap_server_conf, i, i % retained->mpm->num_buckets) < 0) {
|
||||
break;
|
||||
}
|
||||
--number_to_start;
|
||||
@@ -913,7 +794,7 @@ static void perform_idle_server_maintenance(apr_pool_t *p)
|
||||
* shut down gracefully, in case it happened to pick up a request
|
||||
* while we were counting
|
||||
*/
|
||||
bucket_kill_child_record = (bucket_kill_child_record + 1) % num_buckets;
|
||||
bucket_kill_child_record = (bucket_kill_child_record + 1) % retained->mpm->num_buckets;
|
||||
ap_mpm_pod_signal(all_buckets[bucket_kill_child_record].pod);
|
||||
retained->idle_spawn_rate = 1;
|
||||
}
|
||||
@@ -940,7 +821,7 @@ static void perform_idle_server_maintenance(apr_pool_t *p)
|
||||
}
|
||||
for (i = 0; i < free_length; ++i) {
|
||||
bucket_make_child_record++;
|
||||
bucket_make_child_record %= num_buckets;
|
||||
bucket_make_child_record %= retained->mpm->num_buckets;
|
||||
make_child(ap_server_conf, free_slots[i],
|
||||
bucket_make_child_record);
|
||||
}
|
||||
@@ -972,19 +853,21 @@ static int prefork_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
|
||||
|
||||
ap_log_pid(pconf, ap_pid_fname);
|
||||
|
||||
if (!retained->is_graceful) {
|
||||
if (!retained->mpm->was_graceful) {
|
||||
if (ap_run_pre_mpm(s->process->pool, SB_SHARED) != OK) {
|
||||
mpm_state = AP_MPMQ_STOPPING;
|
||||
retained->mpm->mpm_state = AP_MPMQ_STOPPING;
|
||||
return !OK;
|
||||
}
|
||||
/* fix the generation number in the global score; we just got a new,
|
||||
* cleared scoreboard
|
||||
*/
|
||||
ap_scoreboard_image->global->running_generation = retained->my_generation;
|
||||
ap_scoreboard_image->global->running_generation = retained->mpm->my_generation;
|
||||
}
|
||||
|
||||
restart_pending = shutdown_pending = 0;
|
||||
set_signals();
|
||||
if (!one_process) {
|
||||
ap_fatal_signal_setup(ap_server_conf, pconf);
|
||||
}
|
||||
ap_unixd_mpm_set_signals(pconf, one_process);
|
||||
|
||||
if (one_process) {
|
||||
AP_MONCONTROL(1);
|
||||
@@ -997,14 +880,14 @@ static int prefork_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
|
||||
/* Don't thrash since num_buckets depends on the
|
||||
* system and the number of online CPU cores...
|
||||
*/
|
||||
if (ap_daemons_limit < num_buckets)
|
||||
ap_daemons_limit = num_buckets;
|
||||
if (ap_daemons_to_start < num_buckets)
|
||||
ap_daemons_to_start = num_buckets;
|
||||
if (ap_daemons_min_free < num_buckets)
|
||||
ap_daemons_min_free = num_buckets;
|
||||
if (ap_daemons_max_free < ap_daemons_min_free + num_buckets)
|
||||
ap_daemons_max_free = ap_daemons_min_free + num_buckets;
|
||||
if (ap_daemons_limit < retained->mpm->num_buckets)
|
||||
ap_daemons_limit = retained->mpm->num_buckets;
|
||||
if (ap_daemons_to_start < retained->mpm->num_buckets)
|
||||
ap_daemons_to_start = retained->mpm->num_buckets;
|
||||
if (ap_daemons_min_free < retained->mpm->num_buckets)
|
||||
ap_daemons_min_free = retained->mpm->num_buckets;
|
||||
if (ap_daemons_max_free < ap_daemons_min_free + retained->mpm->num_buckets)
|
||||
ap_daemons_max_free = ap_daemons_min_free + retained->mpm->num_buckets;
|
||||
|
||||
/* If we're doing a graceful_restart then we're going to see a lot
|
||||
* of children exiting immediately when we get into the main loop
|
||||
@@ -1018,7 +901,7 @@ static int prefork_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
|
||||
if (remaining_children_to_start > ap_daemons_limit) {
|
||||
remaining_children_to_start = ap_daemons_limit;
|
||||
}
|
||||
if (!retained->is_graceful) {
|
||||
if (!retained->mpm->was_graceful) {
|
||||
startup_children(remaining_children_to_start);
|
||||
remaining_children_to_start = 0;
|
||||
}
|
||||
@@ -1043,9 +926,9 @@ static int prefork_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
|
||||
: "none",
|
||||
apr_proc_mutex_defname());
|
||||
|
||||
mpm_state = AP_MPMQ_RUNNING;
|
||||
retained->mpm->mpm_state = AP_MPMQ_RUNNING;
|
||||
|
||||
while (!restart_pending && !shutdown_pending) {
|
||||
while (!retained->mpm->restart_pending && !retained->mpm->shutdown_pending) {
|
||||
int child_slot;
|
||||
apr_exit_why_e exitwhy;
|
||||
int status, processed_status;
|
||||
@@ -1069,8 +952,8 @@ static int prefork_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
|
||||
*/
|
||||
if (child_slot < 0
|
||||
|| ap_get_scoreboard_process(child_slot)->generation
|
||||
== retained->my_generation) {
|
||||
mpm_state = AP_MPMQ_STOPPING;
|
||||
== retained->mpm->my_generation) {
|
||||
retained->mpm->mpm_state = AP_MPMQ_STOPPING;
|
||||
return !OK;
|
||||
}
|
||||
else {
|
||||
@@ -1107,7 +990,7 @@ static int prefork_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
|
||||
/* handled */
|
||||
#endif
|
||||
}
|
||||
else if (retained->is_graceful) {
|
||||
else if (retained->mpm->was_graceful) {
|
||||
/* Great, we've probably just lost a slot in the
|
||||
* scoreboard. Somehow we don't know about this
|
||||
* child.
|
||||
@@ -1140,9 +1023,9 @@ static int prefork_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
|
||||
perform_idle_server_maintenance(pconf);
|
||||
}
|
||||
|
||||
mpm_state = AP_MPMQ_STOPPING;
|
||||
retained->mpm->mpm_state = AP_MPMQ_STOPPING;
|
||||
|
||||
if (shutdown_pending && !retained->is_graceful) {
|
||||
if (retained->mpm->shutdown_pending && retained->mpm->is_ungraceful) {
|
||||
/* Time to shut down:
|
||||
* Kill child processes, tell them to call child_exit, etc...
|
||||
*/
|
||||
@@ -1158,7 +1041,9 @@ static int prefork_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
|
||||
"caught SIGTERM, shutting down");
|
||||
|
||||
return DONE;
|
||||
} else if (shutdown_pending) {
|
||||
}
|
||||
|
||||
if (retained->mpm->shutdown_pending) {
|
||||
/* Time to perform a graceful shut down:
|
||||
* Reap the inactive children, and ask the active ones
|
||||
* to close their listeners, then wait until they are
|
||||
@@ -1171,7 +1056,7 @@ static int prefork_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
|
||||
ap_close_listeners();
|
||||
|
||||
/* kill off the idle ones */
|
||||
for (i = 0; i < num_buckets; i++) {
|
||||
for (i = 0; i < retained->mpm->num_buckets; i++) {
|
||||
ap_mpm_pod_killpg(all_buckets[i].pod, retained->max_daemons_limit);
|
||||
}
|
||||
|
||||
@@ -1199,7 +1084,7 @@ static int prefork_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
|
||||
}
|
||||
|
||||
/* Don't really exit until each child has finished */
|
||||
shutdown_pending = 0;
|
||||
retained->mpm->shutdown_pending = 0;
|
||||
do {
|
||||
/* Pause for a second */
|
||||
sleep(1);
|
||||
@@ -1215,7 +1100,7 @@ static int prefork_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (!shutdown_pending && active_children &&
|
||||
} while (!retained->mpm->shutdown_pending && active_children &&
|
||||
(!ap_graceful_shutdown_timeout || apr_time_now() < cutoff));
|
||||
|
||||
/* We might be here because we received SIGTERM, either
|
||||
@@ -1228,8 +1113,6 @@ static int prefork_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
|
||||
}
|
||||
|
||||
/* we've been told to restart */
|
||||
apr_signal(SIGHUP, SIG_IGN);
|
||||
apr_signal(AP_SIG_GRACEFUL, SIG_IGN);
|
||||
if (one_process) {
|
||||
/* not worth thinking about */
|
||||
return DONE;
|
||||
@@ -1239,15 +1122,15 @@ static int prefork_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
|
||||
/* XXX: we really need to make sure this new generation number isn't in
|
||||
* use by any of the children.
|
||||
*/
|
||||
++retained->my_generation;
|
||||
ap_scoreboard_image->global->running_generation = retained->my_generation;
|
||||
++retained->mpm->my_generation;
|
||||
ap_scoreboard_image->global->running_generation = retained->mpm->my_generation;
|
||||
|
||||
if (retained->is_graceful) {
|
||||
if (!retained->mpm->is_ungraceful) {
|
||||
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, APLOGNO(00171)
|
||||
"Graceful restart requested, doing restart");
|
||||
|
||||
/* kill off the idle ones */
|
||||
for (i = 0; i < num_buckets; i++) {
|
||||
for (i = 0; i < retained->mpm->num_buckets; i++) {
|
||||
ap_mpm_pod_killpg(all_buckets[i].pod, retained->max_daemons_limit);
|
||||
}
|
||||
|
||||
@@ -1299,7 +1182,7 @@ static int prefork_open_logs(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp,
|
||||
pconf = p;
|
||||
|
||||
/* the reverse of pre_config, we want this only the first time around */
|
||||
if (retained->module_loads == 1) {
|
||||
if (retained->mpm->module_loads == 1) {
|
||||
startup = 1;
|
||||
level_flags |= APLOG_STARTUP;
|
||||
}
|
||||
@@ -1312,22 +1195,22 @@ static int prefork_open_logs(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp,
|
||||
}
|
||||
|
||||
if (one_process) {
|
||||
num_buckets = 1;
|
||||
retained->mpm->num_buckets = 1;
|
||||
}
|
||||
else if (!retained->is_graceful) { /* Preserve the number of buckets
|
||||
on graceful restarts. */
|
||||
num_buckets = 0;
|
||||
else if (!retained->mpm->was_graceful) {
|
||||
/* Preserve the number of buckets on graceful restarts. */
|
||||
retained->mpm->num_buckets = 0;
|
||||
}
|
||||
if ((rv = ap_duplicate_listeners(pconf, ap_server_conf,
|
||||
&listen_buckets, &num_buckets))) {
|
||||
&listen_buckets, &retained->mpm->num_buckets))) {
|
||||
ap_log_error(APLOG_MARK, APLOG_CRIT | level_flags, rv,
|
||||
(startup ? NULL : s), APLOGNO(03280)
|
||||
"could not duplicate listeners");
|
||||
return !OK;
|
||||
}
|
||||
all_buckets = apr_pcalloc(pconf, num_buckets *
|
||||
all_buckets = apr_pcalloc(pconf, retained->mpm->num_buckets *
|
||||
sizeof(prefork_child_bucket));
|
||||
for (i = 0; i < num_buckets; i++) {
|
||||
for (i = 0; i < retained->mpm->num_buckets; i++) {
|
||||
if ((rv = ap_mpm_pod_open(pconf, &all_buckets[i].pod))) {
|
||||
ap_log_error(APLOG_MARK, APLOG_CRIT | level_flags, rv,
|
||||
(startup ? NULL : s), APLOGNO(03281)
|
||||
@@ -1356,8 +1239,6 @@ static int prefork_pre_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp
|
||||
apr_status_t rv;
|
||||
const char *userdata_key = "mpm_prefork_module";
|
||||
|
||||
mpm_state = AP_MPMQ_STARTING;
|
||||
|
||||
debug = ap_exists_config_define("DEBUG");
|
||||
|
||||
if (debug) {
|
||||
@@ -1373,15 +1254,22 @@ static int prefork_pre_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp
|
||||
|
||||
ap_mutex_register(p, AP_ACCEPT_MUTEX_TYPE, NULL, APR_LOCK_DEFAULT, 0);
|
||||
|
||||
/* sigh, want this only the second time around */
|
||||
retained = ap_retained_data_get(userdata_key);
|
||||
if (!retained) {
|
||||
retained = ap_retained_data_create(userdata_key, sizeof(*retained));
|
||||
retained->mpm = ap_unixd_mpm_get_retained_data();
|
||||
retained->max_daemons_limit = -1;
|
||||
retained->idle_spawn_rate = 1;
|
||||
}
|
||||
++retained->module_loads;
|
||||
if (retained->module_loads == 2) {
|
||||
retained->mpm->mpm_state = AP_MPMQ_STARTING;
|
||||
if (retained->mpm->baton != retained) {
|
||||
retained->mpm->was_graceful = 0;
|
||||
retained->mpm->baton = retained;
|
||||
}
|
||||
++retained->mpm->module_loads;
|
||||
|
||||
/* sigh, want this only the second time around */
|
||||
if (retained->mpm->module_loads == 2) {
|
||||
if (!one_process && !foreground) {
|
||||
/* before we detach, setup crash handlers to log to errorlog */
|
||||
ap_fatal_signal_setup(ap_server_conf, pconf);
|
||||
@@ -1414,7 +1302,7 @@ static int prefork_check_config(apr_pool_t *p, apr_pool_t *plog,
|
||||
int startup = 0;
|
||||
|
||||
/* the reverse of pre_config, we want this only the first time around */
|
||||
if (retained->module_loads == 1) {
|
||||
if (retained->mpm->module_loads == 1) {
|
||||
startup = 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -135,19 +135,17 @@ static int num_listensocks = 0;
|
||||
static int resource_shortage = 0;
|
||||
static fd_queue_t *worker_queue;
|
||||
static fd_queue_info_t *worker_queue_info;
|
||||
static int mpm_state = AP_MPMQ_STARTING;
|
||||
|
||||
/* data retained by worker across load/unload of the module
|
||||
* allocated on first call to pre-config hook; located on
|
||||
* subsequent calls to pre-config hook
|
||||
*/
|
||||
typedef struct worker_retained_data {
|
||||
ap_unixd_mpm_retained_data *mpm;
|
||||
|
||||
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;
|
||||
/*
|
||||
@@ -168,12 +166,6 @@ typedef struct worker_retained_data {
|
||||
#define MAX_SPAWN_RATE (32)
|
||||
#endif
|
||||
int hold_off_on_exponential_spawning;
|
||||
/*
|
||||
* Current number of listeners buckets and maximum reached across
|
||||
* restarts (to size retained data according to dynamic num_buckets,
|
||||
* eg. idle_spawn_rate).
|
||||
*/
|
||||
int num_buckets, max_buckets;
|
||||
} worker_retained_data;
|
||||
static worker_retained_data *retained;
|
||||
|
||||
@@ -314,7 +306,7 @@ static void signal_threads(int mode)
|
||||
return;
|
||||
}
|
||||
terminate_mode = mode;
|
||||
mpm_state = AP_MPMQ_STOPPING;
|
||||
retained->mpm->mpm_state = AP_MPMQ_STOPPING;
|
||||
|
||||
/* in case we weren't called from the listener thread, wake up the
|
||||
* listener thread
|
||||
@@ -373,10 +365,10 @@ static int worker_query(int query_code, int *result, apr_status_t *rv)
|
||||
*result = ap_daemons_limit;
|
||||
break;
|
||||
case AP_MPMQ_MPM_STATE:
|
||||
*result = mpm_state;
|
||||
*result = retained->mpm->mpm_state;
|
||||
break;
|
||||
case AP_MPMQ_GENERATION:
|
||||
*result = retained->my_generation;
|
||||
*result = retained->mpm->my_generation;
|
||||
break;
|
||||
default:
|
||||
*rv = APR_ENOTIMPL;
|
||||
@@ -404,7 +396,7 @@ static void worker_note_child_started(int slot, pid_t pid)
|
||||
ap_scoreboard_image->parent[slot].pid = pid;
|
||||
ap_run_child_status(ap_server_conf,
|
||||
ap_scoreboard_image->parent[slot].pid,
|
||||
retained->my_generation, slot, MPM_CHILD_STARTED);
|
||||
retained->mpm->my_generation, slot, MPM_CHILD_STARTED);
|
||||
}
|
||||
|
||||
static void worker_note_child_lost_slot(int slot, pid_t newpid)
|
||||
@@ -437,7 +429,7 @@ static const char *worker_get_name(void)
|
||||
static void clean_child_exit(int code) __attribute__ ((noreturn));
|
||||
static void clean_child_exit(int code)
|
||||
{
|
||||
mpm_state = AP_MPMQ_STOPPING;
|
||||
retained->mpm->mpm_state = AP_MPMQ_STOPPING;
|
||||
if (pchild) {
|
||||
apr_pool_destroy(pchild);
|
||||
}
|
||||
@@ -460,153 +452,6 @@ static void just_die(int sig)
|
||||
|
||||
static int child_fatal;
|
||||
|
||||
/* volatile because they're updated from a signal handler */
|
||||
static int volatile shutdown_pending;
|
||||
static int volatile restart_pending;
|
||||
|
||||
/*
|
||||
* ap_start_shutdown() and ap_start_restart(), below, are a first stab at
|
||||
* functions to initiate shutdown or restart without relying on signals.
|
||||
* Previously this was initiated in sig_term() and restart() signal handlers,
|
||||
* but we want to be able to start a shutdown/restart from other sources --
|
||||
* e.g. on Win32, from the service manager. Now the service manager can
|
||||
* call ap_start_shutdown() or ap_start_restart() as appropriate. Note that
|
||||
* these functions can also be called by the child processes, since global
|
||||
* variables are no longer used to pass on the required action to the parent.
|
||||
*
|
||||
* These should only be called from the parent process itself, since the
|
||||
* parent process will use the shutdown_pending and restart_pending variables
|
||||
* to determine whether to shutdown or restart. The child process should
|
||||
* call signal_parent() directly to tell the parent to die -- this will
|
||||
* cause neither of those variable to be set, which the parent will
|
||||
* assume means something serious is wrong (which it will be, for the
|
||||
* child to force an exit) and so do an exit anyway.
|
||||
*/
|
||||
|
||||
static void ap_start_shutdown(int graceful)
|
||||
{
|
||||
mpm_state = AP_MPMQ_STOPPING;
|
||||
if (shutdown_pending == 1) {
|
||||
/* Um, is this _probably_ not an error, if the user has
|
||||
* tried to do a shutdown twice quickly, so we won't
|
||||
* worry about reporting it.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
shutdown_pending = 1;
|
||||
retained->is_graceful = graceful;
|
||||
}
|
||||
|
||||
/* do a graceful restart if graceful == 1 */
|
||||
static void ap_start_restart(int graceful)
|
||||
{
|
||||
mpm_state = AP_MPMQ_STOPPING;
|
||||
if (restart_pending == 1) {
|
||||
/* Probably not an error - don't bother reporting it */
|
||||
return;
|
||||
}
|
||||
restart_pending = 1;
|
||||
retained->is_graceful = graceful;
|
||||
}
|
||||
|
||||
static void sig_term(int sig)
|
||||
{
|
||||
ap_start_shutdown(sig == AP_SIG_GRACEFUL_STOP);
|
||||
}
|
||||
|
||||
static void restart(int sig)
|
||||
{
|
||||
ap_start_restart(sig == AP_SIG_GRACEFUL);
|
||||
}
|
||||
|
||||
static void set_signals(void)
|
||||
{
|
||||
#ifndef NO_USE_SIGACTION
|
||||
struct sigaction sa;
|
||||
#endif
|
||||
|
||||
if (!one_process) {
|
||||
ap_fatal_signal_setup(ap_server_conf, pconf);
|
||||
}
|
||||
|
||||
#ifndef NO_USE_SIGACTION
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_flags = 0;
|
||||
|
||||
sa.sa_handler = sig_term;
|
||||
if (sigaction(SIGTERM, &sa, NULL) < 0)
|
||||
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00264)
|
||||
"sigaction(SIGTERM)");
|
||||
#ifdef AP_SIG_GRACEFUL_STOP
|
||||
if (sigaction(AP_SIG_GRACEFUL_STOP, &sa, NULL) < 0)
|
||||
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00265)
|
||||
"sigaction(" AP_SIG_GRACEFUL_STOP_STRING ")");
|
||||
#endif
|
||||
#ifdef SIGINT
|
||||
if (sigaction(SIGINT, &sa, NULL) < 0)
|
||||
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00266)
|
||||
"sigaction(SIGINT)");
|
||||
#endif
|
||||
#ifdef SIGXCPU
|
||||
sa.sa_handler = SIG_DFL;
|
||||
if (sigaction(SIGXCPU, &sa, NULL) < 0)
|
||||
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00267)
|
||||
"sigaction(SIGXCPU)");
|
||||
#endif
|
||||
#ifdef SIGXFSZ
|
||||
/* For systems following the LFS standard, ignoring SIGXFSZ allows
|
||||
* a write() beyond the 2GB limit to fail gracefully with E2BIG
|
||||
* rather than terminate the process. */
|
||||
sa.sa_handler = SIG_IGN;
|
||||
if (sigaction(SIGXFSZ, &sa, NULL) < 0)
|
||||
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00268)
|
||||
"sigaction(SIGXFSZ)");
|
||||
#endif
|
||||
#ifdef SIGPIPE
|
||||
sa.sa_handler = SIG_IGN;
|
||||
if (sigaction(SIGPIPE, &sa, NULL) < 0)
|
||||
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00269)
|
||||
"sigaction(SIGPIPE)");
|
||||
#endif
|
||||
|
||||
/* we want to ignore HUPs and AP_SIG_GRACEFUL while we're busy
|
||||
* processing one */
|
||||
sigaddset(&sa.sa_mask, SIGHUP);
|
||||
sigaddset(&sa.sa_mask, AP_SIG_GRACEFUL);
|
||||
sa.sa_handler = restart;
|
||||
if (sigaction(SIGHUP, &sa, NULL) < 0)
|
||||
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00270)
|
||||
"sigaction(SIGHUP)");
|
||||
if (sigaction(AP_SIG_GRACEFUL, &sa, NULL) < 0)
|
||||
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00271)
|
||||
"sigaction(" AP_SIG_GRACEFUL_STRING ")");
|
||||
#else
|
||||
if (!one_process) {
|
||||
#ifdef SIGXCPU
|
||||
apr_signal(SIGXCPU, SIG_DFL);
|
||||
#endif /* SIGXCPU */
|
||||
#ifdef SIGXFSZ
|
||||
apr_signal(SIGXFSZ, SIG_IGN);
|
||||
#endif /* SIGXFSZ */
|
||||
}
|
||||
|
||||
apr_signal(SIGTERM, sig_term);
|
||||
#ifdef SIGHUP
|
||||
apr_signal(SIGHUP, restart);
|
||||
#endif /* SIGHUP */
|
||||
#ifdef AP_SIG_GRACEFUL
|
||||
apr_signal(AP_SIG_GRACEFUL, restart);
|
||||
#endif /* AP_SIG_GRACEFUL */
|
||||
#ifdef AP_SIG_GRACEFUL_STOP
|
||||
apr_signal(AP_SIG_GRACEFUL_STOP, sig_term);
|
||||
#endif /* AP_SIG_GRACEFUL_STOP */
|
||||
#ifdef SIGPIPE
|
||||
apr_signal(SIGPIPE, SIG_IGN);
|
||||
#endif /* SIGPIPE */
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
* Here follows a long bunch of generic server bookkeeping stuff...
|
||||
*/
|
||||
@@ -956,7 +801,7 @@ static void * APR_THREAD_FUNC worker_thread(apr_thread_t *thd, void * dummy)
|
||||
|
||||
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 = retained->my_generation;
|
||||
ap_scoreboard_image->servers[process_slot][thread_slot].generation = retained->mpm->my_generation;
|
||||
ap_update_child_status_from_indexes(process_slot, thread_slot,
|
||||
SERVER_STARTING, NULL);
|
||||
|
||||
@@ -1262,15 +1107,15 @@ static void child_main(int child_num_arg, int child_bucket)
|
||||
apr_thread_t *start_thread_id;
|
||||
int i;
|
||||
|
||||
mpm_state = AP_MPMQ_STARTING; /* for benefit of any hooks that run as this
|
||||
* child initializes
|
||||
*/
|
||||
/* for benefit of any hooks that run as this child initializes */
|
||||
retained->mpm->mpm_state = AP_MPMQ_STARTING;
|
||||
|
||||
ap_my_pid = getpid();
|
||||
ap_fatal_signal_child_setup(ap_server_conf);
|
||||
apr_pool_create(&pchild, pconf);
|
||||
|
||||
/* close unused listeners and pods */
|
||||
for (i = 0; i < retained->num_buckets; i++) {
|
||||
for (i = 0; i < retained->mpm->num_buckets; i++) {
|
||||
if (i != child_bucket) {
|
||||
ap_close_listeners_ex(all_buckets[i].listeners);
|
||||
ap_mpm_podx_close(all_buckets[i].pod);
|
||||
@@ -1353,7 +1198,7 @@ static void child_main(int child_num_arg, int child_bucket)
|
||||
clean_child_exit(APEXIT_CHILDSICK);
|
||||
}
|
||||
|
||||
mpm_state = AP_MPMQ_RUNNING;
|
||||
retained->mpm->mpm_state = AP_MPMQ_RUNNING;
|
||||
|
||||
/* If we are only running in one_process mode, we will want to
|
||||
* still handle signals. */
|
||||
@@ -1439,7 +1284,6 @@ static int make_child(server_rec *s, int slot, int bucket)
|
||||
if (one_process) {
|
||||
my_bucket = &all_buckets[0];
|
||||
|
||||
set_signals();
|
||||
worker_note_child_started(slot, getpid());
|
||||
child_main(slot, 0);
|
||||
/* NOTREACHED */
|
||||
@@ -1510,7 +1354,7 @@ static void startup_children(int number_to_start)
|
||||
if (ap_scoreboard_image->parent[i].pid != 0) {
|
||||
continue;
|
||||
}
|
||||
if (make_child(ap_server_conf, i, i % retained->num_buckets) < 0) {
|
||||
if (make_child(ap_server_conf, i, i % retained->mpm->num_buckets) < 0) {
|
||||
break;
|
||||
}
|
||||
--number_to_start;
|
||||
@@ -1576,7 +1420,7 @@ static void perform_idle_server_maintenance(int child_bucket, int num_buckets)
|
||||
loop if no pid? not much else matters */
|
||||
if (status <= SERVER_READY &&
|
||||
!ps->quiescing &&
|
||||
ps->generation == retained->my_generation &&
|
||||
ps->generation == retained->mpm->my_generation &&
|
||||
ps->bucket == child_bucket) {
|
||||
++idle_thread_count;
|
||||
}
|
||||
@@ -1630,7 +1474,7 @@ static void perform_idle_server_maintenance(int child_bucket, int num_buckets)
|
||||
else {
|
||||
/* looks like a basket case, as no child ever fully initialized; give up.
|
||||
*/
|
||||
shutdown_pending = 1;
|
||||
retained->mpm->shutdown_pending = 1;
|
||||
child_fatal = 1;
|
||||
ap_log_error(APLOG_MARK, APLOG_ALERT, 0,
|
||||
ap_server_conf, APLOGNO(02325)
|
||||
@@ -1726,7 +1570,7 @@ static void server_main_loop(int remaining_children_to_start, int num_buckets)
|
||||
apr_proc_t pid;
|
||||
int i;
|
||||
|
||||
while (!restart_pending && !shutdown_pending) {
|
||||
while (!retained->mpm->restart_pending && !retained->mpm->shutdown_pending) {
|
||||
ap_wait_or_timeout(&exitwhy, &status, &pid, pconf, ap_server_conf);
|
||||
|
||||
if (pid.pid != -1) {
|
||||
@@ -1740,8 +1584,8 @@ static void server_main_loop(int remaining_children_to_start, int num_buckets)
|
||||
*/
|
||||
if (child_slot < 0
|
||||
|| ap_get_scoreboard_process(child_slot)->generation
|
||||
== retained->my_generation) {
|
||||
shutdown_pending = 1;
|
||||
== retained->mpm->my_generation) {
|
||||
retained->mpm->shutdown_pending = 1;
|
||||
child_fatal = 1;
|
||||
return;
|
||||
}
|
||||
@@ -1787,7 +1631,7 @@ static void server_main_loop(int remaining_children_to_start, int num_buckets)
|
||||
worker_note_child_killed(-1, /* already out of the scoreboard */
|
||||
pid.pid, old_gen);
|
||||
if (processed_status == APEXIT_CHILDSICK
|
||||
&& old_gen == retained->my_generation) {
|
||||
&& old_gen == retained->mpm->my_generation) {
|
||||
/* resource shortage, minimize the fork rate */
|
||||
for (i = 0; i < num_buckets; i++) {
|
||||
retained->idle_spawn_rate[i] = 1;
|
||||
@@ -1800,7 +1644,7 @@ static void server_main_loop(int remaining_children_to_start, int num_buckets)
|
||||
/* handled */
|
||||
#endif
|
||||
}
|
||||
else if (retained->is_graceful) {
|
||||
else if (retained->mpm->was_graceful) {
|
||||
/* Great, we've probably just lost a slot in the
|
||||
* scoreboard. Somehow we don't know about this child.
|
||||
*/
|
||||
@@ -1838,25 +1682,27 @@ static void server_main_loop(int remaining_children_to_start, int num_buckets)
|
||||
|
||||
static int worker_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
|
||||
{
|
||||
int num_buckets = retained->num_buckets;
|
||||
int num_buckets = retained->mpm->num_buckets;
|
||||
int remaining_children_to_start;
|
||||
int i;
|
||||
|
||||
ap_log_pid(pconf, ap_pid_fname);
|
||||
|
||||
if (!retained->is_graceful) {
|
||||
if (!retained->mpm->was_graceful) {
|
||||
if (ap_run_pre_mpm(s->process->pool, SB_SHARED) != OK) {
|
||||
mpm_state = AP_MPMQ_STOPPING;
|
||||
retained->mpm->mpm_state = AP_MPMQ_STOPPING;
|
||||
return !OK;
|
||||
}
|
||||
/* fix the generation number in the global score; we just got a new,
|
||||
* cleared scoreboard
|
||||
*/
|
||||
ap_scoreboard_image->global->running_generation = retained->my_generation;
|
||||
ap_scoreboard_image->global->running_generation = retained->mpm->my_generation;
|
||||
}
|
||||
|
||||
restart_pending = shutdown_pending = 0;
|
||||
set_signals();
|
||||
if (!one_process) {
|
||||
ap_fatal_signal_setup(ap_server_conf, pconf);
|
||||
}
|
||||
ap_unixd_mpm_set_signals(pconf, one_process);
|
||||
|
||||
/* Don't thrash since num_buckets depends on the
|
||||
* system and the number of online CPU cores...
|
||||
@@ -1889,7 +1735,7 @@ static int worker_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
|
||||
if (remaining_children_to_start > ap_daemons_limit) {
|
||||
remaining_children_to_start = ap_daemons_limit;
|
||||
}
|
||||
if (!retained->is_graceful) {
|
||||
if (!retained->mpm->was_graceful) {
|
||||
startup_children(remaining_children_to_start);
|
||||
remaining_children_to_start = 0;
|
||||
}
|
||||
@@ -1912,12 +1758,12 @@ static int worker_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
|
||||
? apr_proc_mutex_name(all_buckets[0].mutex)
|
||||
: "none",
|
||||
apr_proc_mutex_defname());
|
||||
mpm_state = AP_MPMQ_RUNNING;
|
||||
retained->mpm->mpm_state = AP_MPMQ_RUNNING;
|
||||
|
||||
server_main_loop(remaining_children_to_start, num_buckets);
|
||||
mpm_state = AP_MPMQ_STOPPING;
|
||||
retained->mpm->mpm_state = AP_MPMQ_STOPPING;
|
||||
|
||||
if (shutdown_pending && !retained->is_graceful) {
|
||||
if (retained->mpm->shutdown_pending && retained->mpm->is_ungraceful) {
|
||||
/* Time to shut down:
|
||||
* Kill child processes, tell them to call child_exit, etc...
|
||||
*/
|
||||
@@ -1935,7 +1781,9 @@ static int worker_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
|
||||
ap_server_conf, APLOGNO(00295) "caught SIGTERM, shutting down");
|
||||
}
|
||||
return DONE;
|
||||
} else if (shutdown_pending) {
|
||||
}
|
||||
|
||||
if (retained->mpm->shutdown_pending) {
|
||||
/* Time to gracefully shut down:
|
||||
* Kill child processes, tell them to call child_exit, etc...
|
||||
*/
|
||||
@@ -1966,7 +1814,7 @@ static int worker_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
|
||||
}
|
||||
|
||||
/* Don't really exit until each child has finished */
|
||||
shutdown_pending = 0;
|
||||
retained->mpm->shutdown_pending = 0;
|
||||
do {
|
||||
/* Pause for a second */
|
||||
apr_sleep(apr_time_from_sec(1));
|
||||
@@ -1982,7 +1830,7 @@ static int worker_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (!shutdown_pending && active_children &&
|
||||
} while (!retained->mpm->shutdown_pending && active_children &&
|
||||
(!ap_graceful_shutdown_timeout || apr_time_now() < cutoff));
|
||||
|
||||
/* We might be here because we received SIGTERM, either
|
||||
@@ -1999,8 +1847,6 @@ static int worker_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
|
||||
}
|
||||
|
||||
/* we've been told to restart */
|
||||
apr_signal(SIGHUP, SIG_IGN);
|
||||
|
||||
if (one_process) {
|
||||
/* not worth thinking about */
|
||||
return DONE;
|
||||
@@ -2010,10 +1856,10 @@ static int worker_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
|
||||
/* XXX: we really need to make sure this new generation number isn't in
|
||||
* use by any of the children.
|
||||
*/
|
||||
++retained->my_generation;
|
||||
ap_scoreboard_image->global->running_generation = retained->my_generation;
|
||||
++retained->mpm->my_generation;
|
||||
ap_scoreboard_image->global->running_generation = retained->mpm->my_generation;
|
||||
|
||||
if (retained->is_graceful) {
|
||||
if (!retained->mpm->is_ungraceful) {
|
||||
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, APLOGNO(00297)
|
||||
AP_SIG_GRACEFUL_STRING " received. Doing graceful restart");
|
||||
/* wake up the children...time to die. But we'll have more soon */
|
||||
@@ -2062,7 +1908,7 @@ static int worker_open_logs(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp,
|
||||
pconf = p;
|
||||
|
||||
/* the reverse of pre_config, we want this only the first time around */
|
||||
if (retained->module_loads == 1) {
|
||||
if (retained->mpm->module_loads == 1) {
|
||||
startup = 1;
|
||||
level_flags |= APLOG_STARTUP;
|
||||
}
|
||||
@@ -2077,9 +1923,9 @@ static int worker_open_logs(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp,
|
||||
if (one_process) {
|
||||
num_buckets = 1;
|
||||
}
|
||||
else if (retained->is_graceful) {
|
||||
else if (retained->mpm->was_graceful) {
|
||||
/* Preserve the number of buckets on graceful restarts. */
|
||||
num_buckets = retained->num_buckets;
|
||||
num_buckets = retained->mpm->num_buckets;
|
||||
}
|
||||
if ((rv = ap_duplicate_listeners(pconf, ap_server_conf,
|
||||
&listen_buckets, &num_buckets))) {
|
||||
@@ -2111,25 +1957,25 @@ static int worker_open_logs(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp,
|
||||
all_buckets[i].listeners = listen_buckets[i];
|
||||
}
|
||||
|
||||
if (retained->max_buckets < num_buckets) {
|
||||
if (retained->mpm->max_buckets < num_buckets) {
|
||||
int new_max, *new_ptr;
|
||||
new_max = retained->max_buckets * 2;
|
||||
new_max = retained->mpm->max_buckets * 2;
|
||||
if (new_max < num_buckets) {
|
||||
new_max = num_buckets;
|
||||
}
|
||||
new_ptr = (int *)apr_palloc(ap_pglobal, new_max * sizeof(int));
|
||||
memcpy(new_ptr, retained->idle_spawn_rate,
|
||||
retained->num_buckets * sizeof(int));
|
||||
retained->mpm->num_buckets * sizeof(int));
|
||||
retained->idle_spawn_rate = new_ptr;
|
||||
retained->max_buckets = new_max;
|
||||
retained->mpm->max_buckets = new_max;
|
||||
}
|
||||
if (retained->num_buckets < num_buckets) {
|
||||
if (retained->mpm->num_buckets < num_buckets) {
|
||||
int rate_max = 1;
|
||||
/* If new buckets are added, set their idle spawn rate to
|
||||
* the highest so far, so that they get filled as quickly
|
||||
* as the existing ones.
|
||||
*/
|
||||
for (i = 0; i < retained->num_buckets; i++) {
|
||||
for (i = 0; i < retained->mpm->num_buckets; i++) {
|
||||
if (rate_max < retained->idle_spawn_rate[i]) {
|
||||
rate_max = retained->idle_spawn_rate[i];
|
||||
}
|
||||
@@ -2138,7 +1984,7 @@ static int worker_open_logs(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp,
|
||||
retained->idle_spawn_rate[i] = rate_max;
|
||||
}
|
||||
}
|
||||
retained->num_buckets = num_buckets;
|
||||
retained->mpm->num_buckets = num_buckets;
|
||||
|
||||
return OK;
|
||||
}
|
||||
@@ -2150,8 +1996,6 @@ static int worker_pre_config(apr_pool_t *pconf, apr_pool_t *plog,
|
||||
apr_status_t rv;
|
||||
const char *userdata_key = "mpm_worker_module";
|
||||
|
||||
mpm_state = AP_MPMQ_STARTING;
|
||||
|
||||
debug = ap_exists_config_define("DEBUG");
|
||||
|
||||
if (debug) {
|
||||
@@ -2166,14 +2010,21 @@ static int worker_pre_config(apr_pool_t *pconf, apr_pool_t *plog,
|
||||
|
||||
ap_mutex_register(pconf, AP_ACCEPT_MUTEX_TYPE, NULL, APR_LOCK_DEFAULT, 0);
|
||||
|
||||
/* sigh, want this only the second time around */
|
||||
retained = ap_retained_data_get(userdata_key);
|
||||
if (!retained) {
|
||||
retained = ap_retained_data_create(userdata_key, sizeof(*retained));
|
||||
retained->mpm = ap_unixd_mpm_get_retained_data();
|
||||
retained->max_daemons_limit = -1;
|
||||
}
|
||||
++retained->module_loads;
|
||||
if (retained->module_loads == 2) {
|
||||
retained->mpm->mpm_state = AP_MPMQ_STARTING;
|
||||
if (retained->mpm->baton != retained) {
|
||||
retained->mpm->was_graceful = 0;
|
||||
retained->mpm->baton = retained;
|
||||
}
|
||||
++retained->mpm->module_loads;
|
||||
|
||||
/* sigh, want this only the second time around */
|
||||
if (retained->mpm->module_loads == 2) {
|
||||
if (!one_process && !foreground) {
|
||||
/* before we detach, setup crash handlers to log to errorlog */
|
||||
ap_fatal_signal_setup(ap_server_conf, pconf);
|
||||
@@ -2210,7 +2061,7 @@ static int worker_check_config(apr_pool_t *p, apr_pool_t *plog,
|
||||
int startup = 0;
|
||||
|
||||
/* the reverse of pre_config, we want this only the first time around */
|
||||
if (retained->module_loads == 1) {
|
||||
if (retained->mpm->module_loads == 1) {
|
||||
startup = 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -1015,14 +1015,13 @@ AP_DECLARE(apr_status_t) ap_fatal_signal_setup(server_rec *s,
|
||||
#ifndef NO_USE_SIGACTION
|
||||
struct sigaction sa;
|
||||
|
||||
memset(&sa, 0, sizeof sa);
|
||||
sigemptyset(&sa.sa_mask);
|
||||
|
||||
#if defined(SA_ONESHOT)
|
||||
sa.sa_flags = SA_ONESHOT;
|
||||
#elif defined(SA_RESETHAND)
|
||||
sa.sa_flags = SA_RESETHAND;
|
||||
#else
|
||||
sa.sa_flags = 0;
|
||||
#endif
|
||||
|
||||
sa.sa_handler = sig_coredump;
|
||||
|
||||
Reference in New Issue
Block a user