/* 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 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_bucket_alloc_t *bucket_alloc;
int last_poll_idx = 0;
+ 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();
requests_this_child = 0;
(void) apr_pollset_add(pollset, &pfd);
}
+ 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;
}
}
} /* one_process */
+ 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)