* this MPM has a dedicated thread for handling both the Listenting sockets,
* and all sockets that are in a Keep Alive status.
*
- * The MPM assumes the underlying apr_pollset implmentation is somewhat
+ * The MPM assumes the underlying apr_pollset implementation is somewhat
* threadsafe. This currently is only compatible with KQueue and EPoll. This
* enables the MPM to avoid extra high level locking or having to wake up the
* listener thread when a keep-alive socket needs to be sent to it.
#include <signal.h>
#include <limits.h> /* for INT_MAX */
-#include "mod_serf.h"
-#if AP_HAS_SERF
+#if HAVE_SERF
+#include "mod_serf.h"
#include "serf.h"
#endif
static fd_queue_t *worker_queue;
static fd_queue_info_t *worker_queue_info;
static int mpm_state = AP_MPMQ_STARTING;
-static int sick_child_detected;
-static ap_generation_t volatile my_generation = 0;
static apr_thread_mutex_t *timeout_mutex;
APR_RING_HEAD(timeout_head_t, conn_state_t);
static apr_pollset_t *event_pollset;
-#if AP_HAS_SERF
+#if HAVE_SERF
typedef struct {
apr_pollset_t *pollset;
apr_pool_t *pool;
{
PT_CSD,
PT_ACCEPT
-#if AP_HAS_SERF
+#if HAVE_SERF
, PT_SERF
#endif
} poll_type_e;
int first_server_limit;
int first_thread_limit;
int module_loads;
+ int sick_child_detected;
+ ap_generation_t my_generation;
+ int volatile is_graceful; /* set from signal handler */
+ int maxclients_reported;
+ /*
+ * The max child slot ever assigned, preserved across restarts. Necessary
+ * to deal with MaxClients changes across AP_SIG_GRACEFUL restarts. We
+ * use this value to optimize routines that have to scan the entire
+ * scoreboard.
+ */
+ int max_daemons_limit;
+ /*
+ * idle_spawn_rate is the number of children that will be spawned on the
+ * next maintenance cycle if there aren't enough idle servers. It is
+ * doubled up to MAX_SPAWN_RATE, and reset only when a cycle goes by
+ * without the need to spawn.
+ */
+ int idle_spawn_rate;
+#ifndef MAX_SPAWN_RATE
+#define MAX_SPAWN_RATE (32)
+#endif
+ int hold_off_on_exponential_spawning;
} event_retained_data;
static event_retained_data *retained;
#define ID_FROM_CHILD_THREAD(c, t) ((c * thread_limit) + t)
-/*
- * The max child slot ever assigned, preserved across restarts. Necessary
- * to deal with MaxClients changes across AP_SIG_GRACEFUL restarts. We
- * use this value to optimize routines that have to scan the entire
- * scoreboard.
- */
-static int max_daemons_limit = -1;
-
static ap_event_pod_t *pod;
/* The event MPM respects a couple of runtime flags that can aid
*rv = APR_SUCCESS;
switch (query_code) {
case AP_MPMQ_MAX_DAEMON_USED:
- *result = max_daemons_limit;
+ *result = retained->max_daemons_limit;
break;
case AP_MPMQ_IS_THREADED:
*result = AP_MPMQ_STATIC;
*result = mpm_state;
break;
case AP_MPMQ_GENERATION:
- *result = my_generation;
+ *result = retained->my_generation;
break;
default:
*rv = APR_ENOTIMPL;
return OK;
}
-static apr_status_t event_note_child_killed(int childnum)
+static void event_note_child_killed(int childnum, pid_t pid, ap_generation_t gen)
{
- ap_scoreboard_image->parent[childnum].pid = 0;
- return APR_SUCCESS;
+ if (childnum != -1) { /* child had a scoreboard slot? */
+ ap_run_child_status(ap_server_conf,
+ ap_scoreboard_image->parent[childnum].pid,
+ ap_scoreboard_image->parent[childnum].generation,
+ childnum, MPM_CHILD_EXITED);
+ ap_scoreboard_image->parent[childnum].pid = 0;
+ }
+ else {
+ ap_run_child_status(ap_server_conf, pid, gen, -1, MPM_CHILD_EXITED);
+ }
+}
+
+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);
+}
+
+static void event_note_child_lost_slot(int slot, pid_t newpid)
+{
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
+ "pid %" APR_PID_T_FMT " taking over scoreboard slot from "
+ "%" APR_PID_T_FMT "%s",
+ newpid,
+ ap_scoreboard_image->parent[slot].pid,
+ ap_scoreboard_image->parent[slot].quiescing ?
+ " (quiescing)" : "");
+ ap_run_child_status(ap_server_conf,
+ ap_scoreboard_image->parent[slot].pid,
+ ap_scoreboard_image->parent[slot].generation,
+ slot, MPM_CHILD_LOST_SLOT);
+ /* Don't forget about this exiting child process, or we
+ * won't be able to kill it if it doesn't exit by the
+ * time the server is shut down.
+ */
+ ap_register_extra_mpm_process(ap_scoreboard_image->parent[slot].pid,
+ ap_scoreboard_image->parent[slot].generation);
}
static const char *event_get_name(void)
if (pchild) {
apr_pool_destroy(pchild);
}
+
+ if (one_process) {
+ event_note_child_killed(/* slot */ 0, 0, 0);
+ }
+
exit(code);
}
* Connection structures and accounting...
*/
-/* volatile just in case */
+static int child_fatal;
+
+/* volatile because they're updated from a signal handler */
static int volatile shutdown_pending;
static int volatile restart_pending;
-static int volatile is_graceful;
-static volatile int child_fatal;
/*
* ap_start_shutdown() and ap_start_restart(), below, are a first stab at
return;
}
shutdown_pending = 1;
- is_graceful = graceful;
+ retained->is_graceful = graceful;
}
/* do a graceful restart if graceful == 1 */
return;
}
restart_pending = 1;
- is_graceful = graceful;
+ retained->is_graceful = graceful;
}
static void sig_term(int sig)
"sigaction(SIGXCPU)");
#endif
#ifdef SIGXFSZ
- sa.sa_handler = SIG_DFL;
+ /* 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,
"sigaction(SIGXFSZ)");
apr_signal(SIGXCPU, SIG_DFL);
#endif /* SIGXCPU */
#ifdef SIGXFSZ
- apr_signal(SIGXFSZ, SIG_DFL);
+ apr_signal(SIGXFSZ, SIG_IGN);
#endif /* SIGXFSZ */
}
}
/* requests_this_child has gone to zero or below. See if the admin coded
- "MaxRequestsPerChild 0", and keep going in that case. Doing it this way
+ "MaxConnectionsPerChild 0", and keep going in that case. Doing it this way
simplifies the hot path in worker_thread */
static void check_infinite_requests(void)
{
}
-#if AP_HAS_SERF
+#if HAVE_SERF
static apr_status_t s_socket_add(void *user_baton,
apr_pollfd_t *pfd,
void *serf_baton)
static apr_status_t init_pollset(apr_pool_t *p)
{
-#if AP_HAS_SERF
+#if HAVE_SERF
s_baton_t *baton = NULL;
#endif
- apr_status_t rv;
ap_listen_rec *lr;
listener_poll_type *pt;
- rv = apr_thread_mutex_create(&timeout_mutex, APR_THREAD_MUTEX_DEFAULT, p);
- if (rv != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf,
- "creation of the timeout mutex failed.");
- return rv;
- }
-
APR_RING_INIT(&timeout_head, conn_state_t, timeout_list);
APR_RING_INIT(&keepalive_timeout_head, conn_state_t, timeout_list);
- /* Create the main pollset */
- rv = apr_pollset_create(&event_pollset,
- threads_per_child,
- p, APR_POLLSET_THREADSAFE | APR_POLLSET_NOCOPY);
- if (rv != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf,
- "apr_pollset_create with Thread Safety failed.");
- return rv;
- }
-
for (lr = ap_listeners; lr != NULL; lr = lr->next) {
apr_pollfd_t *pfd = apr_palloc(p, sizeof(*pfd));
pt = apr_pcalloc(p, sizeof(*pt));
lr->accept_func = ap_unixd_accept;
}
-#if AP_HAS_SERF
+#if HAVE_SERF
baton = apr_pcalloc(p, sizeof(*baton));
baton->pollset = event_pollset;
/* TODO: subpools, threads, reuse, etc. -- currently use malloc() inside :( */
apr_thread_mutex_unlock(g_timer_ring_mtx);
}
-#if AP_HAS_SERF
+#if HAVE_SERF
rc = serf_context_prerun(g_serf);
if (rc != APR_SUCCESS) {
/* TOOD: what should do here? ugh. */
ap_push_pool(worker_queue_info, ptrans);
}
} /* if:else on pt->type */
-#if AP_HAS_SERF
+#if HAVE_SERF
else if (pt->type == PT_SERF) {
/* send socket to serf. */
/* XXXX: this doesn't require get_worker(&have_idle_worker) */
ap_scoreboard_image->servers[process_slot][thread_slot].pid = ap_my_pid;
ap_scoreboard_image->servers[process_slot][thread_slot].tid = apr_os_thread_current();
- ap_scoreboard_image->servers[process_slot][thread_slot].generation = my_generation;
+ ap_scoreboard_image->servers[process_slot][thread_slot].generation = retained->my_generation;
ap_update_child_status_from_indexes(process_slot, thread_slot,
SERVER_STARTING, NULL);
clean_child_exit(APEXIT_CHILDFATAL);
}
+ /* Create the timeout mutex and main pollset before the listener
+ * thread starts.
+ */
+ rv = apr_thread_mutex_create(&timeout_mutex, APR_THREAD_MUTEX_DEFAULT,
+ pchild);
+ if (rv != APR_SUCCESS) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf,
+ "creation of the timeout mutex failed.");
+ clean_child_exit(APEXIT_CHILDFATAL);
+ }
+
+ /* Create the main pollset */
+ rv = apr_pollset_create(&event_pollset,
+ threads_per_child,
+ pchild, APR_POLLSET_THREADSAFE | APR_POLLSET_NOCOPY);
+ if (rv != APR_SUCCESS) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf,
+ "apr_pollset_create with Thread Safety failed.");
+ clean_child_exit(APEXIT_CHILDFATAL);
+ }
+
worker_sockets = apr_pcalloc(pchild, threads_per_child
* sizeof(apr_socket_t *));
else { /* !one_process */
/* remove SIGTERM from the set of blocked signals... if one of
* the other threads in the process needs to take us down
- * (e.g., for MaxRequestsPerChild) it will send us SIGTERM
+ * (e.g., for MaxConnectionsPerChild) it will send us SIGTERM
*/
unblock_signal(SIGTERM);
apr_signal(SIGTERM, dummy_signal_handler);
{
int pid;
- if (slot + 1 > max_daemons_limit) {
- max_daemons_limit = slot + 1;
+ if (slot + 1 > retained->max_daemons_limit) {
+ retained->max_daemons_limit = slot + 1;
}
if (one_process) {
set_signals();
- ap_scoreboard_image->parent[slot].pid = getpid();
+ event_note_child_started(slot, getpid());
child_main(slot);
+ /* NOTREACHED */
}
if ((pid = fork()) == -1) {
apr_signal(SIGTERM, just_die);
child_main(slot);
-
- clean_child_exit(0);
+ /* NOTREACHED */
}
/* else */
if (ap_scoreboard_image->parent[slot].pid != 0) {
/* This new child process is squatting on the scoreboard
* entry owned by an exiting child process, which cannot
* exit until all active requests complete.
- * Don't forget about this exiting child process, or we
- * won't be able to kill it if it doesn't exit by the
- * time the server is shut down.
*/
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
- "taking over scoreboard slot from %" APR_PID_T_FMT "%s",
- ap_scoreboard_image->parent[slot].pid,
- ap_scoreboard_image->parent[slot].quiescing ?
- " (quiescing)" : "");
- ap_register_extra_mpm_process(ap_scoreboard_image->parent[slot].pid);
+ event_note_child_lost_slot(slot, pid);
}
ap_scoreboard_image->parent[slot].quiescing = 0;
- ap_scoreboard_image->parent[slot].pid = pid;
+ event_note_child_started(slot, pid);
return 0;
}
}
}
-
-/*
- * idle_spawn_rate is the number of children that will be spawned on the
- * next maintenance cycle if there aren't enough idle servers. It is
- * doubled up to MAX_SPAWN_RATE, and reset only when a cycle goes by
- * without the need to spawn.
- */
-static int idle_spawn_rate = 1;
-#ifndef MAX_SPAWN_RATE
-#define MAX_SPAWN_RATE (32)
-#endif
-static int hold_off_on_exponential_spawning;
-
static void perform_idle_server_maintenance(void)
{
int i, j;
int any_dead_threads = 0;
int all_dead_threads = 1;
- if (i >= max_daemons_limit
- && totally_free_length == idle_spawn_rate)
+ if (i >= retained->max_daemons_limit
+ && totally_free_length == retained->idle_spawn_rate)
/* short cut if all active processes have been examined and
* enough empty scoreboard slots have been found
*/
if (ps->pid != 0) { /* XXX just set all_dead_threads in outer
for loop if no pid? not much else matters */
if (status <= SERVER_READY &&
- !ps->quiescing && ps->generation == my_generation) {
+ !ps->quiescing && ps->generation == retained->my_generation) {
++idle_thread_count;
}
if (status >= SERVER_READY && status < SERVER_GRACEFUL) {
}
}
if (any_dead_threads
- && totally_free_length < idle_spawn_rate
+ && totally_free_length < retained->idle_spawn_rate
&& free_length < MAX_SPAWN_RATE
&& (!ps->pid /* no process in the slot */
|| ps->quiescing)) { /* or at least one is going away */
}
}
- if (sick_child_detected) {
+ if (retained->sick_child_detected) {
if (active_thread_count > 0) {
/* some child processes appear to be working. don't kill the
* whole server.
*/
- sick_child_detected = 0;
+ retained->sick_child_detected = 0;
}
else {
/* looks like a basket case. give up.
}
}
- max_daemons_limit = last_non_dead + 1;
+ retained->max_daemons_limit = last_non_dead + 1;
if (idle_thread_count > max_spare_threads) {
/* Kill off one child */
ap_event_pod_signal(pod, TRUE);
- idle_spawn_rate = 1;
+ retained->idle_spawn_rate = 1;
}
else if (idle_thread_count < min_spare_threads) {
/* terminate the free list */
if (free_length == 0) { /* scoreboard is full, can't fork */
if (active_thread_count >= ap_daemons_limit * threads_per_child) {
- static int reported = 0;
- if (!reported) {
+ if (!retained->maxclients_reported) {
/* only report this condition once */
ap_log_error(APLOG_MARK, APLOG_ERR, 0,
ap_server_conf,
"server reached MaxClients setting, consider"
" raising the MaxClients setting");
- reported = 1;
+ retained->maxclients_reported = 1;
}
}
else {
ap_server_conf,
"scoreboard is full, not at MaxClients");
}
- idle_spawn_rate = 1;
+ retained->idle_spawn_rate = 1;
}
else {
- if (free_length > idle_spawn_rate) {
- free_length = idle_spawn_rate;
+ if (free_length > retained->idle_spawn_rate) {
+ free_length = retained->idle_spawn_rate;
}
- if (idle_spawn_rate >= 8) {
+ if (retained->idle_spawn_rate >= 8) {
ap_log_error(APLOG_MARK, APLOG_INFO, 0,
ap_server_conf,
"server seems busy, (you may need "
/* the next time around we want to spawn twice as many if this
* wasn't good enough, but not if we've just done a graceful
*/
- if (hold_off_on_exponential_spawning) {
- --hold_off_on_exponential_spawning;
+ if (retained->hold_off_on_exponential_spawning) {
+ --retained->hold_off_on_exponential_spawning;
}
- else if (idle_spawn_rate < MAX_SPAWN_RATE) {
- idle_spawn_rate *= 2;
+ else if (retained->idle_spawn_rate < MAX_SPAWN_RATE) {
+ retained->idle_spawn_rate *= 2;
}
}
}
else {
- idle_spawn_rate = 1;
+ retained->idle_spawn_rate = 1;
}
}
static void server_main_loop(int remaining_children_to_start)
{
+ ap_generation_t old_gen;
int child_slot;
apr_exit_why_e exitwhy;
int status, processed_status;
/* tell perform_idle_server_maintenance to check into this
* on the next timer pop
*/
- sick_child_detected = 1;
+ retained->sick_child_detected = 1;
}
/* non-fatal death... note that it's gone in the scoreboard. */
child_slot = ap_find_child_by_pid(&pid);
SERVER_DEAD,
(request_rec *) NULL);
- ap_scoreboard_image->parent[child_slot].pid = 0;
+ event_note_child_killed(child_slot, 0, 0);
ap_scoreboard_image->parent[child_slot].quiescing = 0;
if (processed_status == APEXIT_CHILDSICK) {
/* resource shortage, minimize the fork rate */
- idle_spawn_rate = 1;
+ retained->idle_spawn_rate = 1;
}
else if (remaining_children_to_start
&& child_slot < ap_daemons_limit) {
--remaining_children_to_start;
}
}
- else if (ap_unregister_extra_mpm_process(pid.pid) == 1) {
- /* handled */
+ else if (ap_unregister_extra_mpm_process(pid.pid, &old_gen) == 1) {
+
+ event_note_child_killed(-1, /* already out of the scoreboard */
+ pid.pid, old_gen);
#if APR_HAS_OTHER_CHILD
}
else if (apr_proc_other_child_alert(&pid, APR_OC_REASON_DEATH,
/* handled */
#endif
}
- else if (is_graceful) {
+ else if (retained->is_graceful) {
/* Great, we've probably just lost a slot in the
* scoreboard. Somehow we don't know about this child.
*/
ap_log_pid(pconf, ap_pid_fname);
- if (!is_graceful) {
+ if (!retained->is_graceful) {
if (ap_run_pre_mpm(s->process->pool, SB_SHARED) != OK) {
mpm_state = AP_MPMQ_STOPPING;
return DONE;
/* fix the generation number in the global score; we just got a new,
* cleared scoreboard
*/
- ap_scoreboard_image->global->running_generation = my_generation;
+ ap_scoreboard_image->global->running_generation = retained->my_generation;
}
set_signals();
if (remaining_children_to_start > ap_daemons_limit) {
remaining_children_to_start = ap_daemons_limit;
}
- if (!is_graceful) {
+ if (!retained->is_graceful) {
startup_children(remaining_children_to_start);
remaining_children_to_start = 0;
}
else {
/* give the system some time to recover before kicking into
* exponential mode */
- hold_off_on_exponential_spawning = 10;
+ retained->hold_off_on_exponential_spawning = 10;
}
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
server_main_loop(remaining_children_to_start);
mpm_state = AP_MPMQ_STOPPING;
- if (shutdown_pending && !is_graceful) {
+ if (shutdown_pending && !retained->is_graceful) {
/* Time to shut down:
* Kill child processes, tell them to call child_exit, etc...
*/
ap_event_pod_killpg(pod, ap_daemons_limit, FALSE);
- ap_reclaim_child_processes(1); /* Start with SIGTERM */
+ ap_reclaim_child_processes(1, /* Start with SIGTERM */
+ event_note_child_killed);
if (!child_fatal) {
/* cleanup pid file on normal shutdown */
- const char *pidfile = NULL;
- pidfile = ap_server_root_relative(pconf, ap_pid_fname);
- if (pidfile != NULL && unlink(pidfile) == 0)
- ap_log_error(APLOG_MARK, APLOG_INFO, 0,
- ap_server_conf,
- "removed PID file %s (pid=%ld)",
- pidfile, (long) getpid());
-
+ ap_remove_pid(pconf, ap_pid_fname);
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0,
ap_server_conf, "caught SIGTERM, shutting down");
}
/* Close our listeners, and then ask our children to do same */
ap_close_listeners();
ap_event_pod_killpg(pod, ap_daemons_limit, TRUE);
- ap_relieve_child_processes();
+ ap_relieve_child_processes(event_note_child_killed);
if (!child_fatal) {
/* cleanup pid file on normal shutdown */
- const char *pidfile = NULL;
- pidfile = ap_server_root_relative (pconf, ap_pid_fname);
- if ( pidfile != NULL && unlink(pidfile) == 0)
- ap_log_error(APLOG_MARK, APLOG_INFO, 0,
- ap_server_conf,
- "removed PID file %s (pid=%ld)",
- pidfile, (long)getpid());
-
+ ap_remove_pid(pconf, ap_pid_fname);
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
"caught " AP_SIG_GRACEFUL_STOP_STRING
", shutting down gracefully");
apr_sleep(apr_time_from_sec(1));
/* Relieve any children which have now exited */
- ap_relieve_child_processes();
+ ap_relieve_child_processes(event_note_child_killed);
active_children = 0;
for (index = 0; index < ap_daemons_limit; ++index) {
* really dead.
*/
ap_event_pod_killpg(pod, ap_daemons_limit, FALSE);
- ap_reclaim_child_processes(1);
+ ap_reclaim_child_processes(1, event_note_child_killed);
return DONE;
}
/* XXX: we really need to make sure this new generation number isn't in
* use by any of the children.
*/
- ++my_generation;
- ap_scoreboard_image->global->running_generation = my_generation;
+ ++retained->my_generation;
+ ap_scoreboard_image->global->running_generation = retained->my_generation;
- if (is_graceful) {
+ if (retained->is_graceful) {
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
AP_SIG_GRACEFUL_STRING
" received. Doing graceful restart");
*/
ap_event_pod_killpg(pod, ap_daemons_limit, FALSE);
- ap_reclaim_child_processes(1); /* Start with SIGTERM */
+ ap_reclaim_child_processes(1, /* Start with SIGTERM */
+ event_note_child_killed);
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
"SIGHUP received. Attempting to restart");
}
retained = ap_retained_data_get(userdata_key);
if (!retained) {
retained = ap_retained_data_create(userdata_key, sizeof(*retained));
+ retained->max_daemons_limit = -1;
+ retained->idle_spawn_rate = 1;
}
++retained->module_loads;
if (retained->module_loads == 2) {
- is_graceful = 0;
rv = apr_pollset_create(&event_pollset, 1, plog,
APR_POLLSET_THREADSAFE | APR_POLLSET_NOCOPY);
if (rv != APR_SUCCESS) {
return HTTP_INTERNAL_SERVER_ERROR;
}
}
- parent_pid = ap_my_pid = getpid();
}
+ parent_pid = ap_my_pid = getpid();
+
ap_listen_pre_config();
ap_daemons_to_start = DEFAULT_START_DAEMON;
min_spare_threads = DEFAULT_MIN_FREE_DAEMON * DEFAULT_THREADS_PER_CHILD;
ap_daemons_limit = server_limit;
threads_per_child = DEFAULT_THREADS_PER_CHILD;
max_clients = ap_daemons_limit * threads_per_child;
- ap_pid_fname = DEFAULT_PIDLOG;
- ap_max_requests_per_child = DEFAULT_MAX_REQUESTS_PER_CHILD;
ap_extended_status = 0;
- ap_max_mem_free = APR_ALLOCATOR_MAX_FREE_UNLIMITED;
-
- apr_cpystrn(ap_coredump_dir, ap_server_root, sizeof(ap_coredump_dir));
return OK;
}
ap_hook_check_config(event_check_config, NULL, NULL, APR_HOOK_MIDDLE);
ap_hook_mpm(event_run, NULL, NULL, APR_HOOK_MIDDLE);
ap_hook_mpm_query(event_query, NULL, NULL, APR_HOOK_MIDDLE);
- ap_hook_mpm_note_child_killed(event_note_child_killed, NULL, NULL, APR_HOOK_MIDDLE);
ap_hook_mpm_register_timed_callback(event_register_timed_callback, NULL, NULL,
APR_HOOK_MIDDLE);
ap_hook_mpm_get_name(event_get_name, NULL, NULL, APR_HOOK_MIDDLE);
{NULL}
};
-module AP_MODULE_DECLARE_DATA mpm_event_module = {
+AP_DECLARE_MODULE(mpm_event) = {
MPM20_MODULE_STUFF,
NULL, /* hook to run before apache parses args */
NULL, /* create per-directory config structure */