--- os/unix/unixd.c (revision 1809833) +++ os/unix/unixd.c (working copy) @@ -582,7 +582,44 @@ AP_DECLARE(void) ap_unixd_mpm_set_signals(apr_pool apr_pool_cleanup_null); } +static int ap_unixd_mpm_query(int query_code, int *result, apr_status_t *rv) +{ + if (retained_data && retained_data->mpm_query_fn) { + return retained_data->mpm_query_fn(query_code, result, rv); + } + else { + return DECLINED; + } +} +static apr_status_t ap_unixd_mpm_query_cleanup(void *fn) +{ + if (retained_data && retained_data->mpm_query_fn == fn) { + retained_data->mpm_query_fn = NULL; + } + return APR_SUCCESS; +} + +/* To cope with restarts (when the mpm_query function may have been unloaded + * with the DSO), we register the hook once and keep/clear the current function + * in retained_data->mpm_query_fn, according to the pconf's lifetime. + */ +AP_DECLARE(void) ap_unixd_hook_mpm_query(apr_pool_t *pconf, + int (*fn)(int, int*, apr_status_t*)) +{ + void *once = NULL; + apr_pool_userdata_get(&once, "ap_unixd_hook_mpm_query", pconf); + if (!once) { + AP_DEBUG_ASSERT(pconf == apr_hook_global_pool); + apr_pool_userdata_setn("true", "ap_unixd_hook_mpm_query", NULL, pconf); + ap_hook_mpm_query(ap_unixd_mpm_query, NULL, NULL, APR_HOOK_MIDDLE); + } + + ap_unixd_mpm_get_retained_data()->mpm_query_fn = fn; + apr_pool_cleanup_register(pconf, fn, ap_unixd_mpm_query_cleanup, + apr_pool_cleanup_null); +} + #ifdef _OSD_POSIX #include "apr_lib.h" --- os/unix/unixd.h (revision 1809833) +++ os/unix/unixd.h (working copy) @@ -129,11 +129,17 @@ typedef struct { * eg. idle_spawn_rate). */ int num_buckets, max_buckets; + + /* Hooked mpm_query function. */ + int (*mpm_query_fn)(int, int*, apr_status_t*); } 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); +AP_DECLARE(void) ap_unixd_hook_mpm_query(apr_pool_t *pconf, + int (*fn)(int, int *, apr_status_t*)); + #ifdef __cplusplus } #endif --- server/mpm/event/event.c (revision 1809833) +++ server/mpm/event/event.c (working copy) @@ -3597,7 +3597,7 @@ static void event_hooks(apr_pool_t * p) ap_hook_post_config(event_post_config, NULL, NULL, APR_HOOK_MIDDLE); 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_unixd_hook_mpm_query(p, event_query); ap_hook_mpm_register_timed_callback(event_register_timed_callback, NULL, NULL, APR_HOOK_MIDDLE); ap_hook_pre_read_request(event_pre_read_request, NULL, NULL, APR_HOOK_MIDDLE); --- server/mpm/prefork/prefork.c (revision 1809833) +++ server/mpm/prefork/prefork.c (working copy) @@ -1423,7 +1423,7 @@ static void prefork_hooks(apr_pool_t *p) ap_hook_pre_config(prefork_pre_config, NULL, NULL, APR_HOOK_REALLY_FIRST); ap_hook_check_config(prefork_check_config, NULL, NULL, APR_HOOK_MIDDLE); ap_hook_mpm(prefork_run, NULL, NULL, APR_HOOK_MIDDLE); - ap_hook_mpm_query(prefork_query, NULL, NULL, APR_HOOK_MIDDLE); + ap_unixd_hook_mpm_query(p, prefork_query); ap_hook_mpm_get_name(prefork_get_name, NULL, NULL, APR_HOOK_MIDDLE); } --- server/mpm/worker/worker.c (revision 1809833) +++ server/mpm/worker/worker.c (working copy) @@ -2257,7 +2257,7 @@ static void worker_hooks(apr_pool_t *p) ap_hook_pre_config(worker_pre_config, NULL, NULL, APR_HOOK_REALLY_FIRST); ap_hook_check_config(worker_check_config, NULL, NULL, APR_HOOK_MIDDLE); ap_hook_mpm(worker_run, NULL, NULL, APR_HOOK_MIDDLE); - ap_hook_mpm_query(worker_query, NULL, NULL, APR_HOOK_MIDDLE); + ap_unixd_hook_mpm_query(p, worker_query); ap_hook_mpm_get_name(worker_get_name, NULL, NULL, APR_HOOK_MIDDLE); }