Changes with Apache 2.0.49
+ *) Add AP_MPMQ_MPM_STATE function code for ap_mpm_query. (Not yet
+ supported for BeOS, OS/2, or Win32 MPMs.) [Jeff Trawick,
+ Brad Nicholes]
+
*) Add mod_status hook to allow modules to add to the mod_status
report. [Joe Orton]
APACHE 2.0 STATUS: -*-text-*-
-Last modified at [$Date: 2003/12/27 12:11:37 $]
+Last modified at [$Date: 2003/12/27 13:18:56 $]
Release:
modules/metadata/mod_expires.c r1.45
+1: ken, stoddard, rederpj
- * PREREQ for a couple of fixes (mod_cgid daemon restart, stranded
- piped logger processes) - ap_mpm_query(AP_MPMQ_MPM_STATE)
+ * PREREQ for another fix (stranded piped logger processes) -
+ ap_mpm_query(AP_MPMQ_MPM_STATE)
No updates are available at present for the BeOS or OS/2 MPMs,
but that is not a showstopper for the other changes.
- include/ap_mpm.h r1.36
- server/mpm/prefork/prefork.c r1.284
- server/mpm/worker/worker.c r1.142,r1.143
- server/mpm/experimental/leader/leader.c r1.35
- server/mpm/experimental/threadpool/threadpool.c r1.23
- server/mpm/netware/mpm_netware.c r1.78
- +1: trawick, stoddard, jerenkrantz
-
server/mpm/winnt/mpm_winnt.c r1.303
server/mpm/winnt/mpm_winnt.h r1.44
server/mpm/winnt/child.c r1.21
/* an MPM is using a dynamic # */
/* threads or daemons. */
+/* Values returned for AP_MPMQ_MPM_STATE */
+#define AP_MPMQ_STARTING 0
+#define AP_MPMQ_RUNNING 1
+#define AP_MPMQ_STOPPING 2
+
#define AP_MPMQ_MAX_DAEMON_USED 1 /* Max # of daemons used so far */
#define AP_MPMQ_IS_THREADED 2 /* MPM can do threading */
#define AP_MPMQ_IS_FORKED 3 /* MPM can do forking */
#define AP_MPMQ_MAX_SPARE_THREADS 10 /* Max # of spare threads */
#define AP_MPMQ_MAX_REQUESTS_DAEMON 11 /* Max # of requests per daemon */
#define AP_MPMQ_MAX_DAEMONS 12 /* Max # of daemons by config */
-
+#define AP_MPMQ_MPM_STATE 13 /* starting, running, stopping */
/**
* Query a property of the current MPM.
static int requests_this_child;
static int num_listensocks = 0;
static int resource_shortage = 0;
+static int mpm_state = AP_MPMQ_STARTING;
typedef struct worker_wakeup_info worker_wakeup_info;
return;
}
terminate_mode = mode;
+ mpm_state = AP_MPMQ_STOPPING;
workers_may_exit = 1;
worker_stack_term(idle_worker_stack);
case AP_MPMQ_MAX_DAEMONS:
*result = ap_daemons_limit;
return APR_SUCCESS;
+ case AP_MPMQ_MPM_STATE:
+ *result = mpm_state;
+ return APR_SUCCESS;
}
return APR_ENOTIMPL;
}
static void clean_child_exit(int code) __attribute__ ((noreturn));
static void clean_child_exit(int code)
{
+ mpm_state = AP_MPMQ_STOPPING;
if (pchild) {
apr_pool_destroy(pchild);
}
static void ap_start_shutdown(void)
{
+ 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
/* 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;
apr_threadattr_t *thread_attr;
apr_thread_t *start_thread_id;
+ mpm_state = AP_MPMQ_STARTING; /* for benefit of any hooks that run as this
+ * child initializes
+ */
+
ap_my_pid = getpid();
apr_pool_create(&pchild, pconf);
clean_child_exit(APEXIT_CHILDFATAL);
}
+ mpm_state = AP_MPMQ_RUNNING;
+
/* If we are only running in one_process mode, we will want to
* still handle signals. */
if (one_process) {
if (rv != APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s,
"Couldn't create accept lock");
+ mpm_state = AP_MPMQ_STOPPING;
return 1;
}
ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s,
"Couldn't set permissions on cross-process lock; "
"check User and Group directives");
+ mpm_state = AP_MPMQ_STOPPING;
return 1;
}
}
if (!is_graceful) {
if (ap_run_pre_mpm(s->process->pool, SB_SHARED) != OK) {
+ mpm_state = AP_MPMQ_STOPPING;
return 1;
}
/* fix the generation number in the global score; we just got a new,
apr_proc_mutex_defname());
#endif
restart_pending = shutdown_pending = 0;
+ mpm_state = AP_MPMQ_RUNNING;
server_main_loop(remaining_children_to_start);
+ mpm_state = AP_MPMQ_STOPPING;
if (shutdown_pending) {
/* Time to gracefully shut down:
ap_directive_t *max_clients = NULL;
apr_status_t rv;
+ mpm_state = AP_MPMQ_STARTING;
+
/* make sure that "ThreadsPerChild" gets set before "MaxClients" */
for (pdir = ap_conftree; pdir != NULL; pdir = pdir->next) {
if (strncasecmp(pdir->directive, "ThreadsPerChild", 15) == 0) {
one_process = 0;
ap_hook_open_logs(leader_open_logs, NULL, aszSucc, APR_HOOK_MIDDLE);
- ap_hook_pre_config(leader_pre_config, NULL, NULL, APR_HOOK_MIDDLE);
+ /* we need to set the MPM state before other pre-config hooks use MPM query
+ * to retrieve it, so register as REALLY_FIRST
+ */
+ ap_hook_pre_config(leader_pre_config, NULL, NULL, APR_HOOK_REALLY_FIRST);
}
static const char *set_daemons_to_start(cmd_parms *cmd, void *dummy,
static int requests_this_child;
static int num_listensocks = 0;
static int resource_shortage = 0;
+static int mpm_state = AP_MPMQ_STARTING;
/* The structure used to pass unique initialization info to each thread */
typedef struct {
return;
}
terminate_mode = mode;
+ mpm_state = AP_MPMQ_STOPPING;
/* in case we weren't called from the listener thread, wake up the
* listener thread
case AP_MPMQ_MAX_DAEMONS:
*result = ap_daemons_limit;
return APR_SUCCESS;
+ case AP_MPMQ_MPM_STATE:
+ *result = mpm_state;
+ return APR_SUCCESS;
}
return APR_ENOTIMPL;
}
static void clean_child_exit(int code) __attribute__ ((noreturn));
static void clean_child_exit(int code)
{
+ mpm_state = AP_MPMQ_STOPPING;
if (pchild) {
apr_pool_destroy(pchild);
}
static void ap_start_shutdown(void)
{
+ 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
/* 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;
apr_threadattr_t *thread_attr;
apr_thread_t *start_thread_id;
+ mpm_state = AP_MPMQ_STARTING; /* for benefit of any hooks that run as this
+ * child initializes
+ */
ap_my_pid = getpid();
apr_pool_create(&pchild, pconf);
clean_child_exit(APEXIT_CHILDFATAL);
}
+ mpm_state = AP_MPMQ_RUNNING;
+
/* If we are only running in one_process mode, we will want to
* still handle signals. */
if (one_process) {
if (rv != APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s,
"Couldn't create accept lock");
+ mpm_state = AP_MPMQ_STOPPING;
return 1;
}
ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s,
"Couldn't set permissions on cross-process lock; "
"check User and Group directives");
+ mpm_state = AP_MPMQ_STOPPING;
return 1;
}
}
if (!is_graceful) {
if (ap_run_pre_mpm(s->process->pool, SB_SHARED) != OK) {
+ mpm_state = AP_MPMQ_STOPPING;
return 1;
}
/* fix the generation number in the global score; we just got a new,
apr_proc_mutex_defname());
#endif
restart_pending = shutdown_pending = 0;
+ mpm_state = AP_MPMQ_RUNNING;
server_main_loop(remaining_children_to_start);
+ mpm_state = AP_MPMQ_STOPPING;
if (shutdown_pending) {
/* Time to gracefully shut down:
ap_directive_t *max_clients = NULL;
apr_status_t rv;
+ mpm_state = AP_MPMQ_STARTING;
+
/* make sure that "ThreadsPerChild" gets set before "MaxClients" */
for (pdir = ap_conftree; pdir != NULL; pdir = pdir->next) {
if (strncasecmp(pdir->directive, "ThreadsPerChild", 15) == 0) {
one_process = 0;
ap_hook_open_logs(worker_open_logs, NULL, aszSucc, APR_HOOK_MIDDLE);
- ap_hook_pre_config(worker_pre_config, NULL, NULL, APR_HOOK_MIDDLE);
+ /* we need to set the MPM state before other pre-config hooks use MPM query
+ * to retrieve it, so register as REALLY_FIRST
+ */
+ ap_hook_pre_config(worker_pre_config, NULL, NULL, APR_HOOK_REALLY_FIRST);
}
static const char *set_daemons_to_start(cmd_parms *cmd, void *dummy,
static int ap_threads_min_free=0;
static int ap_threads_max_free=0;
static int ap_threads_limit=0;
+static int mpm_state = AP_MPMQ_STARTING;
/*
* The max child slot ever assigned, preserved across restarts. Necessary
case AP_MPMQ_MAX_DAEMONS:
*result = 1;
return APR_SUCCESS;
+ case AP_MPMQ_MPM_STATE:
+ *result = mpm_state;
+ return APR_SUCCESS;
}
return APR_ENOTIMPL;
}
#endif
show_server_data();
+ mpm_state = AP_MPMQ_RUNNING;
while (!restart_pending && !shutdown_pending) {
perform_idle_server_maintenance(pconf);
if (show_settings)
apr_thread_yield();
apr_sleep(SCOREBOARD_MAINTENANCE_INTERVAL);
}
+ mpm_state = AP_MPMQ_STOPPING;
/* Shutdown the listen sockets so that we don't get stuck in a blocking call.
int debug;
char *addrname = NULL;
+ mpm_state = AP_MPMQ_STARTING;
+
debug = ap_exists_config_define("DEBUG");
is_graceful = 0;
static int server_limit = DEFAULT_SERVER_LIMIT;
static int first_server_limit;
static int changed_limit_at_restart;
-
+static int mpm_state = AP_MPMQ_STARTING;
static ap_pod_t *pod;
/*
static void clean_child_exit(int code) __attribute__ ((noreturn));
static void clean_child_exit(int code)
{
+ mpm_state = AP_MPMQ_STOPPING;
+
if (pchild) {
apr_pool_destroy(pchild);
}
case AP_MPMQ_MAX_DAEMONS:
*result = server_limit;
return APR_SUCCESS;
+ case AP_MPMQ_MPM_STATE:
+ *result = mpm_state;
+ return APR_SUCCESS;
}
return APR_ENOTIMPL;
}
apr_status_t rv;
apr_bucket_alloc_t *bucket_alloc;
+ mpm_state = AP_MPMQ_STARTING; /* for benefit of any hooks that run as this
+ * child initializes
+ */
+
my_child_num = child_num_arg;
ap_my_pid = getpid();
csd = NULL;
pollset[i].reqevents = APR_POLLIN;
}
+ mpm_state = AP_MPMQ_RUNNING;
+
bucket_alloc = apr_bucket_alloc_create(pchild);
while (!die_now) {
if (rv != APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s,
"Couldn't create accept lock");
+ mpm_state = AP_MPMQ_STOPPING;
return 1;
}
ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s,
"Couldn't set permissions on cross-process lock; "
"check User and Group directives");
+ mpm_state = AP_MPMQ_STOPPING;
return 1;
}
}
if (!is_graceful) {
if (ap_run_pre_mpm(s->process->pool, SB_SHARED) != OK) {
+ mpm_state = AP_MPMQ_STOPPING;
return 1;
}
/* fix the generation number in the global score; we just got a new,
#endif
restart_pending = shutdown_pending = 0;
+ mpm_state = AP_MPMQ_RUNNING;
+
while (!restart_pending && !shutdown_pending) {
int child_slot;
apr_exit_why_e exitwhy;
if (pid.pid != -1) {
processed_status = ap_process_child_status(&pid, exitwhy, status);
if (processed_status == APEXIT_CHILDFATAL) {
+ mpm_state = AP_MPMQ_STOPPING;
return 1;
}
#endif /*TPF */
}
+ mpm_state = AP_MPMQ_STOPPING;
+
if (shutdown_pending) {
/* Time to gracefully shut down:
* Kill child processes, tell them to call child_exit, etc...
int no_detach, debug, foreground;
apr_status_t rv;
+ mpm_state = AP_MPMQ_STARTING;
+
debug = ap_exists_config_define("DEBUG");
if (debug) {
#endif
ap_hook_open_logs(prefork_open_logs, NULL, aszSucc, APR_HOOK_MIDDLE);
- ap_hook_pre_config(prefork_pre_config, NULL, NULL, APR_HOOK_MIDDLE);
+ /* we need to set the MPM state before other pre-config hooks use MPM query
+ * to retrieve it, so register as REALLY_FIRST
+ */
+ ap_hook_pre_config(prefork_pre_config, NULL, NULL, APR_HOOK_REALLY_FIRST);
}
static const char *set_daemons_to_start(cmd_parms *cmd, void *dummy, const char *arg)
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;
/* The structure used to pass unique initialization info to each thread */
typedef struct {
return;
}
terminate_mode = mode;
+ mpm_state = AP_MPMQ_STOPPING;
/* in case we weren't called from the listener thread, wake up the
* listener thread
case AP_MPMQ_MAX_DAEMONS:
*result = ap_daemons_limit;
return APR_SUCCESS;
+ case AP_MPMQ_MPM_STATE:
+ *result = mpm_state;
+ return APR_SUCCESS;
}
return APR_ENOTIMPL;
}
static void clean_child_exit(int code) __attribute__ ((noreturn));
static void clean_child_exit(int code)
{
+ mpm_state = AP_MPMQ_STOPPING;
if (pchild) {
apr_pool_destroy(pchild);
}
static void ap_start_shutdown(void)
{
+ 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
/* 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;
continue;
}
- /* apr_poll() will only return errors in catastrophic
+ /* apr_pollset_poll() will only return errors in catastrophic
* circumstances. Let's try exiting gracefully, for now. */
ap_log_error(APLOG_MARK, APLOG_ERR, ret, (const server_rec *)
ap_server_conf, "apr_poll: (listen)");
apr_threadattr_t *thread_attr;
apr_thread_t *start_thread_id;
+ mpm_state = AP_MPMQ_STARTING; /* for benefit of any hooks that run as this
+ * child initializes
+ */
ap_my_pid = getpid();
apr_pool_create(&pchild, pconf);
clean_child_exit(APEXIT_CHILDFATAL);
}
+ mpm_state = AP_MPMQ_RUNNING;
+
/* If we are only running in one_process mode, we will want to
* still handle signals. */
if (one_process) {
if (rv != APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s,
"Couldn't create accept lock");
+ mpm_state = AP_MPMQ_STOPPING;
return 1;
}
ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s,
"Couldn't set permissions on cross-process lock; "
"check User and Group directives");
+ mpm_state = AP_MPMQ_STOPPING;
return 1;
}
}
if (!is_graceful) {
if (ap_run_pre_mpm(s->process->pool, SB_SHARED) != OK) {
+ mpm_state = AP_MPMQ_STOPPING;
return 1;
}
/* fix the generation number in the global score; we just got a new,
apr_proc_mutex_defname());
#endif
restart_pending = shutdown_pending = 0;
-
+ mpm_state = AP_MPMQ_RUNNING;
+
server_main_loop(remaining_children_to_start);
+ mpm_state = AP_MPMQ_STOPPING;
if (shutdown_pending) {
/* Time to gracefully shut down:
ap_directive_t *max_clients = NULL;
apr_status_t rv;
+ mpm_state = AP_MPMQ_STARTING;
+
/* make sure that "ThreadsPerChild" gets set before "MaxClients" */
for (pdir = ap_conftree; pdir != NULL; pdir = pdir->next) {
if (strncasecmp(pdir->directive, "ThreadsPerChild", 15) == 0) {
one_process = 0;
ap_hook_open_logs(worker_open_logs, NULL, aszSucc, APR_HOOK_MIDDLE);
- ap_hook_pre_config(worker_pre_config, NULL, NULL, APR_HOOK_MIDDLE);
+ /* we need to set the MPM state before other pre-config hooks use MPM query
+ * to retrieve it, so register as REALLY_FIRST
+ */
+ ap_hook_pre_config(worker_pre_config, NULL, NULL, APR_HOOK_REALLY_FIRST);
}
static const char *set_daemons_to_start(cmd_parms *cmd, void *dummy,