diff options
author | Jeff Trawick <trawick@apache.org> | 2009-03-24 15:43:59 +0000 |
---|---|---|
committer | Jeff Trawick <trawick@apache.org> | 2009-03-24 15:43:59 +0000 |
commit | e0eb7d1eefed28fe08a44c5078f8725bd236dd96 (patch) | |
tree | 61627ec7b8079601e353a1a12256a2059bbc86dc | |
parent | 367d5a782948b624dc7daa5a8cb74c779d0c2ddd (diff) | |
download | httpd-e0eb7d1eefed28fe08a44c5078f8725bd236dd96.tar.gz |
Introduce a new set of APIs to allow MPMs to be proper modules instead
of integral parts which share global variables, functions, and macros
with the rest of httpd.
Converted now:
prefork, worker, event, simple, WinNT*
*WinNT hasn't been built or tested, and relies on a hack to include the
WinNT mpm.h to disable Unixy MPM support routines in mpm_common.c
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@757853 13f79535-47bb-0310-9956-ffa450edef68
29 files changed, 451 insertions, 535 deletions
diff --git a/configure.in b/configure.in index eb9b00ea1b..99cad25cf5 100644 --- a/configure.in +++ b/configure.in @@ -211,7 +211,7 @@ if test "$abs_builddir" != "$abs_srcdir"; then APR_ADDTO(INCLUDES, [-I\$(top_builddir)/include]) fi -APR_ADDTO(INCLUDES, [-I\$(top_srcdir)/os/\$(OS_DIR) -I\$(top_srcdir)/server/mpm/\$(MPM_SUBDIR_NAME) -I\$(top_srcdir)/modules/http -I\$(top_srcdir)/modules/aaa -I\$(top_srcdir)/modules/filters -I\$(top_srcdir)/modules/proxy -I\$(top_srcdir)/modules/session -I\$(top_srcdir)/include -I\$(top_srcdir)/modules/generators -I\$(top_srcdir)/modules/mappers -I\$(top_srcdir)/modules/database]) +APR_ADDTO(INCLUDES, [-I\$(top_srcdir)/os/\$(OS_DIR) -I\$(top_srcdir)/modules/http -I\$(top_srcdir)/modules/aaa -I\$(top_srcdir)/modules/filters -I\$(top_srcdir)/modules/proxy -I\$(top_srcdir)/modules/session -I\$(top_srcdir)/include -I\$(top_srcdir)/modules/generators -I\$(top_srcdir)/modules/mappers -I\$(top_srcdir)/modules/database]) # apr/apr-util --includes may pick up system paths for dependent # libraries, so ensure these are later in INCLUDES than local source diff --git a/include/ap_mpm.h b/include/ap_mpm.h index 787ceeca96..b764e6e278 100644 --- a/include/ap_mpm.h +++ b/include/ap_mpm.h @@ -27,6 +27,7 @@ #define AP_MPM_H #include "apr_thread_proc.h" +#include "httpd.h" #ifdef __cplusplus extern "C" { @@ -79,9 +80,9 @@ extern "C" { */ /** - * This is the function that MPMs must create. This function is responsible - * for controlling the parent and child processes. It will run until a - * restart/shutdown is indicated. + * This is the function that passes control to the MPM for steady-state + * processing. It is responsible for controlling the parent and child + * processes. It will run until a restart/shutdown is indicated. * @param pconf the configuration pool, reset before the config file is read * @param plog the log pool, reset after the config file is read * @param server_conf the global server config. @@ -142,6 +143,7 @@ AP_DECLARE(apr_status_t) ap_os_create_privileged_process( #define AP_MPMQ_MAX_DAEMONS 12 /* Max # of daemons by config */ #define AP_MPMQ_MPM_STATE 13 /* starting, running, stopping */ #define AP_MPMQ_IS_ASYNC 14 /* MPM can process async connections */ +#define AP_MPMQ_GENERATION 15 /* MPM generation */ /** * Query a property of the current MPM. @@ -155,10 +157,10 @@ AP_DECLARE(apr_status_t) ap_mpm_query(int query_code, int *result); typedef void (ap_mpm_callback_fn_t)(void *baton); -/* XXXXXXX: only added support in the Event MPM.... */ -AP_DECLARE(void) ap_mpm_register_timed_callback(apr_time_t t, - ap_mpm_callback_fn_t *cbfn, - void *baton); +/* only added support in the Event MPM.... check for APR_ENOTIMPL */ +AP_DECLARE(apr_status_t) ap_mpm_register_timed_callback(apr_time_t t, + ap_mpm_callback_fn_t *cbfn, + void *baton); /* Defining GPROF when compiling uses the moncontrol() function to * disable gprof profiling in the parent, and enable it only for diff --git a/include/http_main.h b/include/http_main.h index d70e0d2937..38739496ef 100644 --- a/include/http_main.h +++ b/include/http_main.h @@ -26,6 +26,7 @@ #ifndef APACHE_HTTP_MAIN_H #define APACHE_HTTP_MAIN_H +#include "httpd.h" #include "apr_optional.h" /** AP_SERVER_BASEARGS is the command argument list parsed by http_main.c @@ -42,6 +43,8 @@ extern "C" { AP_DECLARE_DATA extern const char *ap_server_argv0; /** The global server's ServerRoot */ AP_DECLARE_DATA extern const char *ap_server_root; +/** The global server's server_rec */ +AP_DECLARE_DATA extern server_rec *ap_server_conf; /* for -C, -c and -D switches */ /** An array of all -C directives. These are processed before the server's diff --git a/include/mpm_common.h b/include/mpm_common.h index ee3634e52c..ebf193ad6b 100644 --- a/include/mpm_common.h +++ b/include/mpm_common.h @@ -38,12 +38,22 @@ #define APACHE_MPM_COMMON_H #include "ap_config.h" +#include "ap_mpm.h" #if APR_HAVE_NETINET_TCP_H #include <netinet/tcp.h> /* for TCP_NODELAY */ #endif +#ifdef WIN32 +/* XXX temporary mitigation for Windows; other non-Unix MPMs need this hack too + * include mpm.h to pick up the AP_MPM_NO_foo definitions + */ #include "mpm.h" +#endif + +#ifndef AP_MPM_NO_SET_ACCEPT_LOCK_MECH +#include "apr_proc_mutex.h" +#endif #ifdef __cplusplus extern "C" { @@ -95,7 +105,7 @@ extern "C" { * in the scoreboard as well as those currently registered via * ap_register_extra_mpm_process(). */ -#ifdef AP_MPM_WANT_RECLAIM_CHILD_PROCESSES +#ifndef AP_MPM_NO_RECLAIM_CHILD_PROCESSES void ap_reclaim_child_processes(int terminate); #endif @@ -112,7 +122,7 @@ void ap_reclaim_child_processes(int terminate); * in the scoreboard as well as those currently registered via * ap_register_extra_mpm_process(). */ -#ifdef AP_MPM_WANT_RECLAIM_CHILD_PROCESSES +#ifndef AP_MPM_NO_RECLAIM_CHILD_PROCESSES void ap_relieve_child_processes(void); #endif @@ -127,7 +137,7 @@ void ap_relieve_child_processes(void); * ap_reclaim_child_processes(), remove it from the list of such processes * by calling ap_unregister_extra_mpm_process(). */ -#ifdef AP_MPM_WANT_RECLAIM_CHILD_PROCESSES +#ifndef AP_MPM_NO_RECLAIM_CHILD_PROCESSES void ap_register_extra_mpm_process(pid_t pid); #endif @@ -140,7 +150,7 @@ void ap_register_extra_mpm_process(pid_t pid); * be reclaimed. * @return 1 if the process was found and removed, 0 otherwise */ -#ifdef AP_MPM_WANT_RECLAIM_CHILD_PROCESSES +#ifndef AP_MPM_NO_RECLAIM_CHILD_PROCESSES int ap_unregister_extra_mpm_process(pid_t pid); #endif @@ -153,7 +163,7 @@ int ap_unregister_extra_mpm_process(pid_t pid); * APR_EINVAL is returned if passed either an invalid (< 1) pid, or if * the pid is not in the current process group */ -#ifdef AP_MPM_WANT_RECLAIM_CHILD_PROCESSES +#ifndef AP_MPM_NO_RECLAIM_CHILD_PROCESSES apr_status_t ap_mpm_safe_kill(pid_t pid, int sig); #endif @@ -165,7 +175,7 @@ apr_status_t ap_mpm_safe_kill(pid_t pid, int sig); * @param ret The process id of the process that died * @param p The pool to allocate out of */ -#ifdef AP_MPM_WANT_WAIT_OR_TIMEOUT +#ifndef AP_MPM_NO_WAIT_OR_TIMEOUT void ap_wait_or_timeout(apr_exit_why_e *status, int *exitcode, apr_proc_t *ret, apr_pool_t *p); #endif @@ -177,7 +187,7 @@ void ap_wait_or_timeout(apr_exit_why_e *status, int *exitcode, apr_proc_t *ret, * @param status The status returned from ap_wait_or_timeout * @return 0 on success, APEXIT_CHILDFATAL if MPM should terminate */ -#ifdef AP_MPM_WANT_PROCESS_CHILD_STATUS +#ifndef AP_MPM_NO_PROCESS_CHILD_STATUS int ap_process_child_status(apr_proc_t *pid, apr_exit_why_e why, int status); #endif @@ -216,7 +226,7 @@ AP_DECLARE(gid_t) ap_gname2id(const char *name); #define AP_MPM_HARD_LIMITS_FILE APACHE_MPM_DIR "/mpm_default.h" -#ifdef AP_MPM_USES_POD +#ifndef AP_MPM_NO_POD typedef struct ap_pod_t ap_pod_t; @@ -270,7 +280,7 @@ AP_DECLARE(void) ap_mpm_pod_killpg(ap_pod_t *pod, int num); * The maximum number of requests each child thread or * process handles before dying off */ -#ifdef AP_MPM_WANT_SET_MAX_REQUESTS +#ifndef AP_MPM_NO_SET_MAX_REQUESTS extern int ap_max_requests_per_child; const char *ap_mpm_set_max_requests(cmd_parms *cmd, void *dummy, const char *arg); @@ -279,7 +289,7 @@ const char *ap_mpm_set_max_requests(cmd_parms *cmd, void *dummy, /** * The filename used to store the process id. */ -#ifdef AP_MPM_WANT_SET_PIDFILE +#ifndef AP_MPM_NO_SET_PIDFILE extern const char *ap_pid_fname; const char *ap_mpm_set_pidfile(cmd_parms *cmd, void *dummy, const char *arg); @@ -288,7 +298,7 @@ const char *ap_mpm_set_pidfile(cmd_parms *cmd, void *dummy, /** * The name of lockfile used when Apache needs to lock the accept() call. */ -#ifdef AP_MPM_WANT_SET_LOCKFILE +#ifndef AP_MPM_NO_SET_LOCKFILE extern const char *ap_lock_fname; const char *ap_mpm_set_lockfile(cmd_parms *cmd, void *dummy, const char *arg); @@ -297,7 +307,7 @@ const char *ap_mpm_set_lockfile(cmd_parms *cmd, void *dummy, /** * The system mutex implementation to use for the accept mutex. */ -#ifdef AP_MPM_WANT_SET_ACCEPT_LOCK_MECH +#ifndef AP_MPM_NO_SET_ACCEPT_LOCK_MECH extern apr_lockmech_e ap_accept_lock_mech; const char *ap_mpm_set_accept_lock_mech(cmd_parms *cmd, void *dummy, const char *arg); @@ -306,7 +316,7 @@ const char *ap_mpm_set_accept_lock_mech(cmd_parms *cmd, void *dummy, /* * Set the scorboard file. */ -#ifdef AP_MPM_WANT_SET_SCOREBOARD +#ifndef AP_MPM_NO_SET_SCOREBOARD const char *ap_mpm_set_scoreboard(cmd_parms *cmd, void *dummy, const char *arg); #endif @@ -314,7 +324,7 @@ const char *ap_mpm_set_scoreboard(cmd_parms *cmd, void *dummy, /* * The directory that the server changes directory to dump core. */ -#ifdef AP_MPM_WANT_SET_COREDUMPDIR +#ifndef AP_MPM_NO_SET_COREDUMPDIR extern char ap_coredump_dir[MAX_STRING_LEN]; extern int ap_coredumpdir_configured; const char *ap_mpm_set_coredumpdir(cmd_parms *cmd, void *dummy, @@ -324,7 +334,7 @@ const char *ap_mpm_set_coredumpdir(cmd_parms *cmd, void *dummy, /** * Set the timeout period for a graceful shutdown. */ -#ifdef AP_MPM_WANT_SET_GRACEFUL_SHUTDOWN +#ifndef AP_MPM_NO_SET_GRACEFUL_SHUTDOWN extern int ap_graceful_shutdown_timeout; const char *ap_mpm_set_graceful_shutdown(cmd_parms *cmd, void *dummy, const char *arg); @@ -335,24 +345,24 @@ AP_INIT_TAKE1("GracefulShutdownTimeout", ap_mpm_set_graceful_shutdown, NULL, \ #endif -#ifdef AP_MPM_WANT_SIGNAL_SERVER +#ifndef AP_MPM_NO_SIGNAL_SERVER int ap_signal_server(int *, apr_pool_t *); void ap_mpm_rewrite_args(process_rec *); #endif -#ifdef AP_MPM_WANT_SET_MAX_MEM_FREE +#ifndef AP_MPM_NO_SET_MAX_MEM_FREE extern apr_uint32_t ap_max_mem_free; extern const char *ap_mpm_set_max_mem_free(cmd_parms *cmd, void *dummy, const char *arg); #endif -#ifdef AP_MPM_WANT_SET_STACKSIZE +#ifndef AP_MPM_NO_SET_STACKSIZE extern apr_size_t ap_thread_stacksize; extern const char *ap_mpm_set_thread_stacksize(cmd_parms *cmd, void *dummy, const char *arg); #endif -#ifdef AP_MPM_WANT_FATAL_SIGNAL_HANDLER +#ifndef AP_MPM_NO_FATAL_SIGNAL_HANDLER extern apr_status_t ap_fatal_signal_setup(server_rec *s, apr_pool_t *pconf); extern apr_status_t ap_fatal_signal_child_setup(server_rec *s); #endif @@ -362,12 +372,33 @@ extern const char *ap_mpm_set_exception_hook(cmd_parms *cmd, void *dummy, const char *arg); #endif +#ifndef AP_MPM_NO_CHILD_PID +extern pid_t ap_mpm_get_child_pid(int childnum); +extern pid_t ap_mpm_note_child_killed(int childnum); +#endif + AP_DECLARE_HOOK(int,monitor,(apr_pool_t *p)) /* register modules that undertake to manage system security */ AP_DECLARE(int) ap_sys_privileges_handlers(int inc); AP_DECLARE_HOOK(int, drop_privileges, (apr_pool_t * pchild, server_rec * s)) +/* pass control to the MPM */ +AP_DECLARE_HOOK(int, mpm, (apr_pool_t *pconf, apr_pool_t *plog, server_rec *s)); + +/* implement the mpm query function */ +AP_DECLARE_HOOK(apr_status_t, mpm_query, (int query_code, int *result)); + +/* get pid of child by index */ +AP_DECLARE_HOOK(pid_t, mpm_get_child_pid, (int childnum)); + +/* child specified by index has been killed */ +AP_DECLARE_HOOK(apr_status_t, mpm_note_child_killed, (int childnum)); + +/* register the specified callback */ +AP_DECLARE_HOOK(apr_status_t, mpm_register_timed_callback, + (apr_time_t t, ap_mpm_callback_fn_t *cbfn, void *baton)); + #ifdef __cplusplus } #endif diff --git a/modules/generators/mod_status.c b/modules/generators/mod_status.c index 3c341b0670..291ec9bc73 100644 --- a/modules/generators/mod_status.c +++ b/modules/generators/mod_status.c @@ -245,13 +245,15 @@ static int status_handler(request_rec *r) char *stat_buffer; pid_t *pid_buffer, worker_pid; clock_t tu, ts, tcu, tcs; - ap_generation_t worker_generation; + ap_generation_t mpm_generation, worker_generation; if (strcmp(r->handler, STATUS_MAGIC_TYPE) && strcmp(r->handler, "server-status")) { return DECLINED; } + ap_mpm_query(AP_MPMQ_GENERATION, &mpm_generation); + #ifdef HAVE_TIMES #ifdef _SC_CLK_TCK tick = sysconf(_SC_CLK_TCK); @@ -339,7 +341,7 @@ static int status_handler(request_rec *r) if (!ps_record->quiescing && ps_record->pid) { if (res == SERVER_READY - && ps_record->generation == ap_my_generation) + && ps_record->generation == mpm_generation) ready++; else if (res != SERVER_DEAD && res != SERVER_STARTING && @@ -422,7 +424,7 @@ static int status_handler(request_rec *r) DEFAULT_TIME_FORMAT, 0), "</dt>\n", NULL); ap_rprintf(r, "<dt>Parent Server Generation: %d</dt>\n", - (int)ap_my_generation); + (int)mpm_generation); ap_rputs("<dt>Server uptime: ", r); show_time(r, up_time); ap_rputs("</dt>\n", r); diff --git a/modules/ssl/ssl_private.h b/modules/ssl/ssl_private.h index 4400cd25dd..66b265c226 100644 --- a/modules/ssl/ssl_private.h +++ b/modules/ssl/ssl_private.h @@ -39,7 +39,6 @@ #include "util_script.h" #include "util_filter.h" #include "util_ebcdic.h" -#include "mpm.h" #include "apr.h" #include "apr_strings.h" #define APR_WANT_STRFUNC diff --git a/server/config.c b/server/config.c index 564cf6d5ef..fc2cb31dfa 100644 --- a/server/config.c +++ b/server/config.c @@ -49,12 +49,10 @@ #include "http_main.h" #include "http_vhost.h" #include "util_cfgtree.h" -#include "mpm.h" - AP_DECLARE_DATA const char *ap_server_argv0 = NULL; - AP_DECLARE_DATA const char *ap_server_root = NULL; +AP_DECLARE_DATA server_rec *ap_server_conf = NULL; AP_DECLARE_DATA apr_array_header_t *ap_server_pre_read_config = NULL; AP_DECLARE_DATA apr_array_header_t *ap_server_post_read_config = NULL; @@ -2195,7 +2193,3 @@ AP_DECLARE(void) ap_show_modules(void) printf(" %s\n", ap_loaded_modules[n]->name); } -AP_DECLARE(const char *) ap_show_mpm(void) -{ - return MPM_NAME; -} diff --git a/server/connection.c b/server/connection.c index 0adfb7071d..7de1431284 100644 --- a/server/connection.c +++ b/server/connection.c @@ -23,7 +23,6 @@ #include "http_request.h" #include "http_protocol.h" #include "ap_mpm.h" -#include "mpm_default.h" #include "http_config.h" #include "http_core.h" #include "http_vhost.h" diff --git a/server/core.c b/server/core.c index 5676b6b0f5..05319060cc 100644 --- a/server/core.c +++ b/server/core.c @@ -42,7 +42,6 @@ #include "util_filter.h" #include "util_ebcdic.h" #include "util_mutex.h" -#include "mpm.h" #include "mpm_common.h" #include "scoreboard.h" #include "mod_core.h" diff --git a/server/core_filters.c b/server/core_filters.c index 82a7f8def3..bdd55e6049 100644 --- a/server/core_filters.c +++ b/server/core_filters.c @@ -46,7 +46,6 @@ #include "apr_buckets.h" #include "util_filter.h" #include "util_ebcdic.h" -#include "mpm.h" #include "mpm_common.h" #include "scoreboard.h" #include "mod_core.h" diff --git a/server/listen.c b/server/listen.c index 52bc3104ec..8361fb3c35 100644 --- a/server/listen.c +++ b/server/listen.c @@ -26,7 +26,6 @@ #include "http_core.h" #include "ap_listen.h" #include "http_log.h" -#include "mpm.h" #include "mpm_common.h" AP_DECLARE_DATA ap_listen_rec *ap_listeners = NULL; @@ -169,11 +168,7 @@ static apr_status_t make_sock(apr_pool_t *p, ap_listen_rec *server) server->sd = s; server->active = 1; -#ifdef MPM_ACCEPT_FUNC - server->accept_func = MPM_ACCEPT_FUNC; -#else server->accept_func = NULL; -#endif return APR_SUCCESS; } diff --git a/server/main.c b/server/main.c index f9c8d89f22..eb241b6873 100644 --- a/server/main.c +++ b/server/main.c @@ -52,6 +52,9 @@ * Most significant main() global data can be found in http_config.c */ +/* XXX call after module loading based on some cmd-line option/define + */ + static void show_mpm_settings(void) { int mpm_query_info; @@ -108,8 +111,6 @@ static void show_compile_settings(void) */ printf("Architecture: %ld-bit\n", 8 * (long)sizeof(void *)); - show_mpm_settings(); - printf("Server compiled with....\n"); #ifdef BIG_SECURITY_HOLE printf(" -D BIG_SECURITY_HOLE\n"); @@ -706,6 +707,7 @@ int main(int argc, const char * const argv[]) apr_pool_clear(plog); + ap_server_conf = server_conf; if ( ap_run_open_logs(pconf, plog, ptemp, server_conf) != OK) { ap_log_error(APLOG_MARK, APLOG_STARTUP |APLOG_ERR, 0, NULL, "Unable to open logs"); diff --git a/server/mpm/config.m4 b/server/mpm/config.m4 index 0939022362..98e31020e1 100644 --- a/server/mpm/config.m4 +++ b/server/mpm/config.m4 @@ -69,10 +69,6 @@ fi MPM_DIR=server/mpm/$MPM_SUBDIR_NAME MPM_LIB=$MPM_DIR/lib${MPM_NAME}.la -if test ! -f "$abs_srcdir/$MPM_DIR/mpm.h"; then - AC_MSG_ERROR(the selected mpm -- $apache_cv_mpm -- is not supported) -fi - APACHE_SUBST(MPM_NAME) APACHE_SUBST(MPM_SUBDIR_NAME) MODLIST="$MODLIST mpm_${MPM_NAME}" diff --git a/server/mpm/experimental/event/event.c b/server/mpm/experimental/event/event.c index be49693711..cde6937c64 100644 --- a/server/mpm/experimental/event/event.c +++ b/server/mpm/experimental/event/event.c @@ -90,6 +90,7 @@ #include "fdqueue.h" #include "mpm_default.h" #include "http_vhost.h" +#include "unixd.h" #include <signal.h> #include <limits.h> /* for INT_MAX */ @@ -134,11 +135,13 @@ #define MAX_THREAD_LIMIT 100000 #endif +#define MPM_CHILD_PID(i) (ap_scoreboard_image->parent[i].pid) + /* * Actual definitions of config globals */ -int ap_threads_per_child = 0; /* Worker threads per child */ +static int threads_per_child = 0; /* Worker threads per child */ static int ap_daemons_to_start = 0; static int min_spare_threads = 0; static int max_spare_threads = 0; @@ -159,6 +162,7 @@ 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); @@ -206,13 +210,9 @@ typedef struct * use this value to optimize routines that have to scan the entire * scoreboard. */ -int ap_max_daemons_limit = -1; - -static ap_pod_t *pod; +static int max_daemons_limit = -1; -/* *Non*-shared http_main globals... */ - -server_rec *ap_server_conf; +static ap_event_pod_t *pod; /* The event MPM respects a couple of runtime flags that can aid * in debugging. Setting the -DNO_DETACH flag will prevent the root process @@ -257,7 +257,7 @@ static apr_socket_t **worker_sockets; static void close_worker_sockets(void) { int i; - for (i = 0; i < ap_threads_per_child; i++) { + for (i = 0; i < threads_per_child; i++) { if (worker_sockets[i]) { apr_socket_close(worker_sockets[i]); worker_sockets[i] = NULL; @@ -322,11 +322,11 @@ static void signal_threads(int mode) } } -AP_DECLARE(apr_status_t) ap_mpm_query(int query_code, int *result) +static apr_status_t event_query(int query_code, int *result) { switch (query_code) { case AP_MPMQ_MAX_DAEMON_USED: - *result = ap_max_daemons_limit; + *result = max_daemons_limit; return APR_SUCCESS; case AP_MPMQ_IS_THREADED: *result = AP_MPMQ_STATIC; @@ -344,7 +344,7 @@ AP_DECLARE(apr_status_t) ap_mpm_query(int query_code, int *result) *result = thread_limit; return APR_SUCCESS; case AP_MPMQ_MAX_THREADS: - *result = ap_threads_per_child; + *result = threads_per_child; return APR_SUCCESS; case AP_MPMQ_MIN_SPARE_DAEMONS: *result = 0; @@ -367,10 +367,24 @@ AP_DECLARE(apr_status_t) ap_mpm_query(int query_code, int *result) case AP_MPMQ_MPM_STATE: *result = mpm_state; return APR_SUCCESS; + case AP_MPMQ_GENERATION: + *result = my_generation; + return APR_SUCCESS; } return APR_ENOTIMPL; } +static pid_t event_get_child_pid(int childnum) +{ + return ap_scoreboard_image->parent[childnum].pid; +} + +static apr_status_t event_note_child_killed(int childnum) +{ + ap_scoreboard_image->parent[childnum].pid = 0; + return APR_SUCCESS; +} + /* 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) @@ -396,7 +410,6 @@ static int volatile shutdown_pending; static int volatile restart_pending; static int volatile is_graceful; static volatile int child_fatal; -ap_generation_t volatile ap_my_generation = 0; /* * ap_start_shutdown() and ap_start_restart(), below, are a first stab at @@ -773,7 +786,7 @@ static apr_status_t init_pollset(apr_pool_t *p) /* Create the main pollset */ rv = apr_pollset_create(&event_pollset, - ap_threads_per_child, + 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, @@ -795,6 +808,8 @@ static apr_status_t init_pollset(apr_pool_t *p) apr_socket_opt_set(pfd->desc.s, APR_SO_NONBLOCK, 1); apr_pollset_add(event_pollset, pfd); + + lr->accept_func = ap_unixd_accept; } return APR_SUCCESS; @@ -891,9 +906,9 @@ static APR_RING_HEAD(timer_ring_t, timer_event_t) timer_ring; static apr_thread_mutex_t *g_timer_ring_mtx; -AP_DECLARE(void) ap_mpm_register_timed_callback(apr_time_t t, - ap_mpm_callback_fn_t *cbfn, - void *baton) +static apr_status_t event_register_timed_callback(apr_time_t t, + ap_mpm_callback_fn_t *cbfn, + void *baton) { int inserted = 0; timer_event_t *ep; @@ -934,6 +949,8 @@ AP_DECLARE(void) ap_mpm_register_timed_callback(apr_time_t t, } apr_thread_mutex_unlock(g_timer_ring_mtx); + + return APR_SUCCESS; } #ifndef apr_time_from_msec @@ -1252,7 +1269,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 = ap_my_generation; + ap_scoreboard_image->servers[process_slot][thread_slot].generation = my_generation; ap_update_child_status_from_indexes(process_slot, thread_slot, SERVER_STARTING, NULL); @@ -1395,7 +1412,7 @@ static void *APR_THREAD_FUNC start_threads(apr_thread_t * thd, void *dummy) /* We must create the fd queues before we start up the listener * and worker threads. */ worker_queue = apr_pcalloc(pchild, sizeof(*worker_queue)); - rv = ap_queue_init(worker_queue, ap_threads_per_child, pchild); + rv = ap_queue_init(worker_queue, threads_per_child, pchild); if (rv != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf, "ap_queue_init() failed"); @@ -1403,20 +1420,20 @@ static void *APR_THREAD_FUNC start_threads(apr_thread_t * thd, void *dummy) } rv = ap_queue_info_create(&worker_queue_info, pchild, - ap_threads_per_child); + threads_per_child); if (rv != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf, "ap_queue_info_create() failed"); clean_child_exit(APEXIT_CHILDFATAL); } - worker_sockets = apr_pcalloc(pchild, ap_threads_per_child + worker_sockets = apr_pcalloc(pchild, threads_per_child * sizeof(apr_socket_t *)); loops = prev_threads_created = 0; while (1) { - /* ap_threads_per_child does not include the listener thread */ - for (i = 0; i < ap_threads_per_child; i++) { + /* threads_per_child does not include the listener thread */ + for (i = 0; i < threads_per_child; i++) { int status = ap_scoreboard_image->servers[child_num_arg][i].status; @@ -1458,7 +1475,7 @@ static void *APR_THREAD_FUNC start_threads(apr_thread_t * thd, void *dummy) } - if (start_thread_may_exit || threads_created == ap_threads_per_child) { + if (start_thread_may_exit || threads_created == threads_per_child) { break; } /* wait for previous generation to clean up an entry */ @@ -1470,7 +1487,7 @@ static void *APR_THREAD_FUNC start_threads(apr_thread_t * thd, void *dummy) "child %" APR_PID_T_FMT " isn't taking over " "slots very quickly (%d of %d)", ap_my_pid, threads_created, - ap_threads_per_child); + threads_per_child); } prev_threads_created = threads_created; } @@ -1532,7 +1549,7 @@ static void join_workers(apr_thread_t * listener, apr_thread_t ** threads) } } - for (i = 0; i < ap_threads_per_child; i++) { + for (i = 0; i < threads_per_child; i++) { if (threads[i]) { /* if we ever created this thread */ rv = apr_thread_join(&thread_rv, threads[i]); if (rv != APR_SUCCESS) { @@ -1615,7 +1632,7 @@ static void child_main(int child_num_arg) */ threads = (apr_thread_t **) calloc(1, sizeof(apr_thread_t *) * - ap_threads_per_child); + threads_per_child); if (threads == NULL) { ap_log_error(APLOG_MARK, APLOG_ALERT, errno, ap_server_conf, "malloc: out of memory"); @@ -1685,7 +1702,7 @@ static void child_main(int child_num_arg) apr_signal(SIGTERM, dummy_signal_handler); /* Watch for any messages from the parent over the POD */ while (1) { - rv = ap_mpm_pod_check(pod); + rv = ap_event_pod_check(pod); if (rv == AP_NORESTART) { /* see if termination was triggered while we slept */ switch (terminate_mode) { @@ -1727,8 +1744,8 @@ static int make_child(server_rec * s, int slot) { int pid; - if (slot + 1 > ap_max_daemons_limit) { - ap_max_daemons_limit = slot + 1; + if (slot + 1 > max_daemons_limit) { + max_daemons_limit = slot + 1; } if (one_process) { @@ -1847,13 +1864,13 @@ static void perform_idle_server_maintenance(void) for (i = 0; i < ap_daemons_limit; ++i) { /* Initialization to satisfy the compiler. It doesn't know - * that ap_threads_per_child is always > 0 */ + * that threads_per_child is always > 0 */ int status = SERVER_DEAD; int any_dying_threads = 0; int any_dead_threads = 0; int all_dead_threads = 1; - if (i >= ap_max_daemons_limit + if (i >= max_daemons_limit && totally_free_length == idle_spawn_rate) /* short cut if all active processes have been examined and * enough empty scoreboard slots have been found @@ -1861,7 +1878,7 @@ static void perform_idle_server_maintenance(void) break; ps = &ap_scoreboard_image->parent[i]; - for (j = 0; j < ap_threads_per_child; j++) { + for (j = 0; j < threads_per_child; j++) { ws = &ap_scoreboard_image->servers[i][j]; status = ws->status; @@ -1881,7 +1898,7 @@ static void perform_idle_server_maintenance(void) 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 == ap_my_generation) { + !ps->quiescing && ps->generation == my_generation) { ++idle_thread_count; } if (status >= SERVER_READY && status < SERVER_GRACEFUL) { @@ -1940,18 +1957,18 @@ static void perform_idle_server_maintenance(void) } } - ap_max_daemons_limit = last_non_dead + 1; + max_daemons_limit = last_non_dead + 1; if (idle_thread_count > max_spare_threads) { /* Kill off one child */ - ap_mpm_pod_signal(pod, TRUE); + ap_event_pod_signal(pod, TRUE); 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 * ap_threads_per_child) { + if (active_thread_count >= ap_daemons_limit * threads_per_child) { static int reported = 0; if (!reported) { /* only report this condition once */ @@ -2029,7 +2046,7 @@ static void server_main_loop(int remaining_children_to_start) /* non-fatal death... note that it's gone in the scoreboard. */ child_slot = ap_find_child_by_pid(&pid); if (child_slot >= 0) { - for (i = 0; i < ap_threads_per_child; i++) + for (i = 0; i < threads_per_child; i++) ap_update_child_status_from_indexes(child_slot, i, SERVER_DEAD, (request_rec *) NULL); @@ -2092,7 +2109,7 @@ static void server_main_loop(int remaining_children_to_start) } } -int ap_mpm_run(apr_pool_t * _pconf, apr_pool_t * plog, server_rec * s) +static int event_run(apr_pool_t * _pconf, apr_pool_t * plog, server_rec * s) { int remaining_children_to_start; @@ -2106,13 +2123,13 @@ int ap_mpm_run(apr_pool_t * _pconf, apr_pool_t * plog, server_rec * s) /* fix the generation number in the global score; we just got a new, * cleared scoreboard */ - ap_scoreboard_image->global->running_generation = ap_my_generation; + ap_scoreboard_image->global->running_generation = my_generation; } set_signals(); /* Don't thrash... */ - if (max_spare_threads < min_spare_threads + ap_threads_per_child) - max_spare_threads = min_spare_threads + ap_threads_per_child; + if (max_spare_threads < min_spare_threads + threads_per_child) + max_spare_threads = min_spare_threads + threads_per_child; /* 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 @@ -2153,7 +2170,7 @@ int ap_mpm_run(apr_pool_t * _pconf, apr_pool_t * plog, server_rec * s) /* Time to shut down: * Kill child processes, tell them to call child_exit, etc... */ - ap_mpm_pod_killpg(pod, ap_daemons_limit, FALSE); + ap_event_pod_killpg(pod, ap_daemons_limit, FALSE); ap_reclaim_child_processes(1); /* Start with SIGTERM */ if (!child_fatal) { @@ -2180,7 +2197,7 @@ int ap_mpm_run(apr_pool_t * _pconf, apr_pool_t * plog, server_rec * s) /* Close our listeners, and then ask our children to do same */ ap_close_listeners(); - ap_mpm_pod_killpg(pod, ap_daemons_limit, TRUE); + ap_event_pod_killpg(pod, ap_daemons_limit, TRUE); ap_relieve_child_processes(); if (!child_fatal) { @@ -2227,7 +2244,7 @@ int ap_mpm_run(apr_pool_t * _pconf, apr_pool_t * plog, server_rec * s) * way, try and make sure that all of our processes are * really dead. */ - ap_mpm_pod_killpg(pod, ap_daemons_limit, FALSE); + ap_event_pod_killpg(pod, ap_daemons_limit, FALSE); ap_reclaim_child_processes(1); return 1; @@ -2245,15 +2262,15 @@ int ap_mpm_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. */ - ++ap_my_generation; - ap_scoreboard_image->global->running_generation = ap_my_generation; + ++my_generation; + ap_scoreboard_image->global->running_generation = my_generation; if (is_graceful) { ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, AP_SIG_GRACEFUL_STRING " received. Doing graceful restart"); /* wake up the children...time to die. But we'll have more soon */ - ap_mpm_pod_killpg(pod, ap_daemons_limit, TRUE); + ap_event_pod_killpg(pod, ap_daemons_limit, TRUE); /* This is mostly for debugging... so that we know what is still @@ -2266,7 +2283,7 @@ int ap_mpm_run(apr_pool_t * _pconf, apr_pool_t * plog, server_rec * s) * and a SIGHUP, we may as well use the same signal, because some user * pthreads are stealing signals from us left and right. */ - ap_mpm_pod_killpg(pod, ap_daemons_limit, FALSE); + ap_event_pod_killpg(pod, ap_daemons_limit, FALSE); ap_reclaim_child_processes(1); /* Start with SIGTERM */ ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, @@ -2288,7 +2305,6 @@ static int event_open_logs(apr_pool_t * p, apr_pool_t * plog, apr_status_t rv; pconf = p; - ap_server_conf = s; /* the reverse of pre_config, we want this only the first time around */ if (restart_num++ == 0) { @@ -2304,7 +2320,7 @@ static int event_open_logs(apr_pool_t * p, apr_pool_t * plog, } if (!one_process) { - if ((rv = ap_mpm_pod_open(pconf, &pod))) { + if ((rv = ap_event_pod_open(pconf, &pod))) { ap_log_error(APLOG_MARK, APLOG_CRIT | level_flags, rv, (startup ? NULL : s), "could not open pipe-of-death"); @@ -2367,8 +2383,8 @@ static int event_pre_config(apr_pool_t * pconf, apr_pool_t * plog, server_limit = DEFAULT_SERVER_LIMIT; thread_limit = DEFAULT_THREAD_LIMIT; ap_daemons_limit = server_limit; - ap_threads_per_child = DEFAULT_THREADS_PER_CHILD; - max_clients = ap_daemons_limit * ap_threads_per_child; + threads_per_child = DEFAULT_THREADS_PER_CHILD; + max_clients = ap_daemons_limit * threads_per_child; ap_pid_fname = DEFAULT_PIDLOG; ap_lock_fname = DEFAULT_LOCKFILE; ap_max_requests_per_child = DEFAULT_MAX_REQUESTS_PER_CHILD; @@ -2481,11 +2497,11 @@ static int event_check_config(apr_pool_t *p, apr_pool_t *plog, thread_limit = first_thread_limit; } - if (ap_threads_per_child > thread_limit) { + if (threads_per_child > thread_limit) { if (startup) { ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, "WARNING: ThreadsPerChild of %d exceeds ThreadLimit " - "of", ap_threads_per_child); + "of", threads_per_child); ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, " %d threads, decreasing to %d.", thread_limit, thread_limit); @@ -2496,24 +2512,24 @@ static int event_check_config(apr_pool_t *p, apr_pool_t *plog, ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, "ThreadsPerChild of %d exceeds ThreadLimit " "of %d, decreasing to match", - ap_threads_per_child, thread_limit); + threads_per_child, thread_limit); } - ap_threads_per_child = thread_limit; + threads_per_child = thread_limit; } - else if (ap_threads_per_child < 1) { + else if (threads_per_child < 1) { if (startup) { ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, "WARNING: ThreadsPerChild of %d not allowed, " - "increasing to 1.", ap_threads_per_child); + "increasing to 1.", threads_per_child); } else { ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, "ThreadsPerChild of %d not allowed, increasing to 1", - ap_threads_per_child); + threads_per_child); } - ap_threads_per_child = 1; + threads_per_child = 1; } - if (max_clients < ap_threads_per_child) { + if (max_clients < threads_per_child) { if (startup) { ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, "WARNING: MaxClients of %d is less than " @@ -2521,22 +2537,22 @@ static int event_check_config(apr_pool_t *p, apr_pool_t *plog, ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, " %d, increasing to %d. MaxClients must be at " "least as large", - ap_threads_per_child, ap_threads_per_child); + threads_per_child, threads_per_child); ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, " as the number of threads in a single server."); } else { ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, "MaxClients of %d is less than ThreadsPerChild " "of %d, increasing to match", - max_clients, ap_threads_per_child); + max_clients, threads_per_child); } - max_clients = ap_threads_per_child; + max_clients = threads_per_child; } - ap_daemons_limit = max_clients / ap_threads_per_child; + ap_daemons_limit = max_clients / threads_per_child; - if (max_clients % ap_threads_per_child) { - int tmp_max_clients = ap_daemons_limit * ap_threads_per_child; + if (max_clients % threads_per_child) { + int tmp_max_clients = ap_daemons_limit * threads_per_child; if (startup) { ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, @@ -2544,7 +2560,7 @@ static int event_check_config(apr_pool_t *p, apr_pool_t *plog, "multiple of", max_clients); ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, " ThreadsPerChild of %d, decreasing to nearest " - "multiple %d,", ap_threads_per_child, + "multiple %d,", threads_per_child, tmp_max_clients); ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, " for a maximum of %d servers.", @@ -2553,7 +2569,7 @@ static int event_check_config(apr_pool_t *p, apr_pool_t *plog, ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, "MaxClients of %d is not an integer multiple of " "ThreadsPerChild of %d, decreasing to nearest " - "multiple %d", max_clients, ap_threads_per_child, + "multiple %d", max_clients, threads_per_child, tmp_max_clients); } max_clients = tmp_max_clients; @@ -2566,7 +2582,7 @@ static int event_check_config(apr_pool_t *p, apr_pool_t *plog, "servers and ", max_clients, ap_daemons_limit); ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, " would exceed ServerLimit of %d, decreasing to %d.", - server_limit, server_limit * ap_threads_per_child); + server_limit, server_limit * threads_per_child); ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, " To increase, please see the ServerLimit " "directive."); @@ -2575,7 +2591,7 @@ static int event_check_config(apr_pool_t *p, apr_pool_t *plog, "MaxClients of %d would require %d servers and " "exceed ServerLimit of %d, decreasing to %d", max_clients, ap_daemons_limit, server_limit, - server_limit * ap_threads_per_child); + server_limit * threads_per_child); } ap_daemons_limit = server_limit; } @@ -2611,7 +2627,7 @@ static int event_check_config(apr_pool_t *p, apr_pool_t *plog, min_spare_threads = 1; } - /* max_spare_threads < min_spare_threads + ap_threads_per_child + /* max_spare_threads < min_spare_threads + threads_per_child * checked in ap_mpm_run() */ @@ -2633,6 +2649,12 @@ static void event_hooks(apr_pool_t * p) */ ap_hook_pre_config(event_pre_config, NULL, NULL, APR_HOOK_REALLY_FIRST); 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_get_child_pid(event_get_child_pid, 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); } static const char *set_daemons_to_start(cmd_parms *cmd, void *dummy, @@ -2691,7 +2713,7 @@ static const char *set_threads_per_child(cmd_parms * cmd, void *dummy, return err; } - ap_threads_per_child = atoi(arg); + threads_per_child = atoi(arg); return NULL; } static const char *set_server_limit (cmd_parms *cmd, void *dummy, const char *arg) diff --git a/server/mpm/experimental/event/mpm.h b/server/mpm/experimental/event/mpm.h deleted file mode 100644 index d38c1f1e3a..0000000000 --- a/server/mpm/experimental/event/mpm.h +++ /dev/null @@ -1,64 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file event/mpm.h - * @brief Unix Exent driven MPM - * - * @defgroup APACHE_MPM_EVENT Unix Event MPM - * @ingroup APACHE_OS_UNIX APACHE_MPM - * @{ - */ - -#include "scoreboard.h" -#include "unixd.h" - -#ifndef APACHE_MPM_EVENT_H -#define APACHE_MPM_EVENT_H - -#define EVENT_MPM - -#define MPM_NAME "Event" - -#define AP_MPM_WANT_RECLAIM_CHILD_PROCESSES -#define AP_MPM_WANT_WAIT_OR_TIMEOUT -#define AP_MPM_WANT_PROCESS_CHILD_STATUS -#define AP_MPM_WANT_SET_PIDFILE -#define AP_MPM_WANT_SET_SCOREBOARD -#define AP_MPM_WANT_SET_LOCKFILE -#define AP_MPM_WANT_SET_MAX_REQUESTS -#define AP_MPM_WANT_SET_COREDUMPDIR -#define AP_MPM_WANT_SET_ACCEPT_LOCK_MECH -#define AP_MPM_WANT_SIGNAL_SERVER -#define AP_MPM_WANT_SET_MAX_MEM_FREE -#define AP_MPM_WANT_SET_STACKSIZE -#define AP_MPM_WANT_SET_GRACEFUL_SHUTDOWN -#define AP_MPM_WANT_FATAL_SIGNAL_HANDLER -#define AP_MPM_DISABLE_NAGLE_ACCEPTED_SOCK - -#define AP_MPM_HAS_USER_CALLBACKS - -#define MPM_CHILD_PID(i) (ap_scoreboard_image->parent[i].pid) -#define MPM_NOTE_CHILD_KILLED(i) (MPM_CHILD_PID(i) = 0) -#define MPM_ACCEPT_FUNC ap_unixd_accept - -extern int ap_threads_per_child; -extern int ap_max_daemons_limit; -extern server_rec *ap_server_conf; -extern char ap_coredump_dir[MAX_STRING_LEN]; - -#endif /* APACHE_MPM_EVENT_H */ -/** @} */ diff --git a/server/mpm/experimental/event/pod.c b/server/mpm/experimental/event/pod.c index 5a9999f738..262bd1197b 100644 --- a/server/mpm/experimental/event/pod.c +++ b/server/mpm/experimental/event/pod.c @@ -16,11 +16,13 @@ #include "pod.h" +#include "apr_portable.h" + #if APR_HAVE_UNISTD_H #include <unistd.h> #endif -AP_DECLARE(apr_status_t) ap_mpm_pod_open(apr_pool_t * p, ap_pod_t ** pod) +AP_DECLARE(apr_status_t) ap_event_pod_open(apr_pool_t * p, ap_event_pod_t ** pod) { apr_status_t rv; @@ -41,7 +43,7 @@ AP_DECLARE(apr_status_t) ap_mpm_pod_open(apr_pool_t * p, ap_pod_t ** pod) return APR_SUCCESS; } -AP_DECLARE(int) ap_mpm_pod_check(ap_pod_t * pod) +AP_DECLARE(int) ap_event_pod_check(ap_event_pod_t * pod) { char c; apr_os_file_t fd; @@ -63,7 +65,7 @@ AP_DECLARE(int) ap_mpm_pod_check(ap_pod_t * pod) return AP_NORESTART; } -AP_DECLARE(apr_status_t) ap_mpm_pod_close(ap_pod_t * pod) +AP_DECLARE(apr_status_t) ap_event_pod_close(ap_event_pod_t * pod) { apr_status_t rv; @@ -79,7 +81,7 @@ AP_DECLARE(apr_status_t) ap_mpm_pod_close(ap_pod_t * pod) return rv; } -static apr_status_t pod_signal_internal(ap_pod_t * pod, int graceful) +static apr_status_t pod_signal_internal(ap_event_pod_t * pod, int graceful) { apr_status_t rv; char char_of_death = graceful ? GRACEFUL_CHAR : RESTART_CHAR; @@ -93,12 +95,12 @@ static apr_status_t pod_signal_internal(ap_pod_t * pod, int graceful) return rv; } -AP_DECLARE(apr_status_t) ap_mpm_pod_signal(ap_pod_t * pod, int graceful) +AP_DECLARE(apr_status_t) ap_event_pod_signal(ap_event_pod_t * pod, int graceful) { return pod_signal_internal(pod, graceful); } -AP_DECLARE(void) ap_mpm_pod_killpg(ap_pod_t * pod, int num, int graceful) +AP_DECLARE(void) ap_event_pod_killpg(ap_event_pod_t * pod, int num, int graceful) { int i; apr_status_t rv = APR_SUCCESS; diff --git a/server/mpm/experimental/event/pod.h b/server/mpm/experimental/event/pod.h index 78e2b9d7bf..861e4d9957 100644 --- a/server/mpm/experimental/event/pod.h +++ b/server/mpm/experimental/event/pod.h @@ -31,7 +31,6 @@ #include "http_config.h" #include "http_log.h" #include "http_main.h" -#include "mpm.h" #include "mpm_common.h" #include "ap_mpm.h" #include "ap_listen.h" @@ -43,18 +42,18 @@ #define AP_RESTART 0 #define AP_GRACEFUL 1 -typedef struct ap_pod_t ap_pod_t; +typedef struct ap_event_pod_t ap_event_pod_t; -struct ap_pod_t +struct ap_event_pod_t { apr_file_t *pod_in; apr_file_t *pod_out; apr_pool_t *p; }; -AP_DECLARE(apr_status_t) ap_mpm_pod_open(apr_pool_t * p, ap_pod_t ** pod); -AP_DECLARE(int) ap_mpm_pod_check(ap_pod_t * pod); -AP_DECLARE(apr_status_t) ap_mpm_pod_close(ap_pod_t * pod); -AP_DECLARE(apr_status_t) ap_mpm_pod_signal(ap_pod_t * pod, int graceful); -AP_DECLARE(void) ap_mpm_pod_killpg(ap_pod_t * pod, int num, int graceful); +AP_DECLARE(apr_status_t) ap_event_pod_open(apr_pool_t * p, ap_event_pod_t ** pod); +AP_DECLARE(int) ap_event_pod_check(ap_event_pod_t * pod); +AP_DECLARE(apr_status_t) ap_event_pod_close(ap_event_pod_t * pod); +AP_DECLARE(apr_status_t) ap_event_pod_signal(ap_event_pod_t * pod, int graceful); +AP_DECLARE(void) ap_event_pod_killpg(ap_event_pod_t * pod, int num, int graceful); /** @} */ diff --git a/server/mpm/prefork/mpm.h b/server/mpm/prefork/mpm.h deleted file mode 100644 index 36c7b57607..0000000000 --- a/server/mpm/prefork/mpm.h +++ /dev/null @@ -1,62 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file prefork/mpm.h - * @brief Unix Prefork MPM (default for Uinx systems) - * - * @defgroup APACHE_MPM_PREFORK Unix Prefork - * @ingroup APACHE_MPM APACHE_OS_UNIX - * @{ - */ - -#include "httpd.h" -#include "mpm_default.h" -#include "scoreboard.h" -#include "unixd.h" - -#ifndef APACHE_MPM_PREFORK_H -#define APACHE_MPM_PREFORK_H - -#define PREFORK_MPM - -#define MPM_NAME "Prefork" - -#define AP_MPM_WANT_RECLAIM_CHILD_PROCESSES -#define AP_MPM_WANT_WAIT_OR_TIMEOUT -#define AP_MPM_WANT_PROCESS_CHILD_STATUS -#define AP_MPM_WANT_SET_PIDFILE -#define AP_MPM_WANT_SET_SCOREBOARD -#define AP_MPM_WANT_SET_LOCKFILE -#define AP_MPM_WANT_SET_MAX_REQUESTS -#define AP_MPM_WANT_SET_COREDUMPDIR -#define AP_MPM_WANT_SET_ACCEPT_LOCK_MECH -#define AP_MPM_WANT_SIGNAL_SERVER -#define AP_MPM_WANT_SET_MAX_MEM_FREE -#define AP_MPM_WANT_FATAL_SIGNAL_HANDLER -#define AP_MPM_WANT_SET_GRACEFUL_SHUTDOWN -#define AP_MPM_DISABLE_NAGLE_ACCEPTED_SOCK - -#define AP_MPM_USES_POD 1 -#define MPM_CHILD_PID(i) (ap_scoreboard_image->parent[i].pid) -#define MPM_NOTE_CHILD_KILLED(i) (MPM_CHILD_PID(i) = 0) -#define MPM_ACCEPT_FUNC ap_unixd_accept - -extern int ap_threads_per_child; -extern int ap_max_daemons_limit; -extern server_rec *ap_server_conf; -#endif /* APACHE_MPM_PREFORK_H */ -/** @} */ diff --git a/server/mpm/prefork/prefork.c b/server/mpm/prefork/prefork.c index d7157371d8..65417a4c42 100644 --- a/server/mpm/prefork/prefork.c +++ b/server/mpm/prefork/prefork.c @@ -88,7 +88,6 @@ /* config globals */ -int ap_threads_per_child=0; /* Worker threads per child */ static apr_proc_mutex_t *accept_mutex; static int ap_daemons_to_start=0; static int ap_daemons_min_free=0; @@ -99,13 +98,14 @@ static int first_server_limit = 0; static int mpm_state = AP_MPMQ_STARTING; static ap_pod_t *pod; +#define MPM_CHILD_PID(i) (ap_scoreboard_image->parent[i].pid) + /* * 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 ap_max_daemons_limit = -1; -server_rec *ap_server_conf; +static int max_daemons_limit = -1; /* 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 @@ -128,7 +128,7 @@ static pid_t parent_pid; #ifndef MULTITHREAD static int my_child_num; #endif -ap_generation_t volatile ap_my_generation=0; +static ap_generation_t volatile my_generation=0; #ifdef TPF int tpf_child = 0; @@ -203,7 +203,7 @@ static void accept_mutex_on(void) if (rv != APR_SUCCESS) { const char *msg = "couldn't grab the accept mutex"; - if (ap_my_generation != + if (my_generation != ap_scoreboard_image->global->running_generation) { ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, NULL, "%s", msg); clean_child_exit(0); @@ -221,7 +221,7 @@ static void accept_mutex_off(void) if (rv != APR_SUCCESS) { const char *msg = "couldn't release the accept mutex"; - if (ap_my_generation != + if (my_generation != ap_scoreboard_image->global->running_generation) { ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, NULL, "%s", msg); /* don't exit here... we have a connection to @@ -247,7 +247,7 @@ static void accept_mutex_off(void) #define SAFE_ACCEPT(stmt) do {stmt;} while(0) #endif -AP_DECLARE(apr_status_t) ap_mpm_query(int query_code, int *result) +static apr_status_t prefork_query(int query_code, int *result) { switch(query_code){ case AP_MPMQ_MAX_DAEMON_USED: @@ -289,10 +289,24 @@ AP_DECLARE(apr_status_t) ap_mpm_query(int query_code, int *result) case AP_MPMQ_MPM_STATE: *result = mpm_state; return APR_SUCCESS; + case AP_MPMQ_GENERATION: + *result = my_generation; + return APR_SUCCESS; } return APR_ENOTIMPL; } +static pid_t prefork_get_child_pid(int childnum) +{ + return ap_scoreboard_image->parent[childnum].pid; +} + +static apr_status_t prefork_note_child_killed(int childnum) +{ + ap_scoreboard_image->parent[childnum].pid = 0; + return APR_SUCCESS; +} + /***************************************************************** * Connection structures and accounting... */ @@ -510,6 +524,8 @@ static void child_main(int child_num_arg) /* ### check the status */ (void) apr_pollset_add(pollset, &pfd); + + lr->accept_func = ap_unixd_accept; } mpm_state = AP_MPMQ_RUNNING; @@ -650,7 +666,7 @@ static void child_main(int child_num_arg) if (ap_mpm_pod_check(pod) == APR_SUCCESS) { /* selected as idle? */ die_now = 1; } - else if (ap_my_generation != + else if (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? @@ -666,8 +682,8 @@ static int make_child(server_rec *s, int slot) { int pid; - if (slot + 1 > ap_max_daemons_limit) { - ap_max_daemons_limit = slot + 1; + if (slot + 1 > max_daemons_limit) { + max_daemons_limit = slot + 1; } if (one_process) { @@ -794,7 +810,7 @@ static void perform_idle_server_maintenance(apr_pool_t *p) for (i = 0; i < ap_daemons_limit; ++i) { int status; - if (i >= ap_max_daemons_limit && free_length == idle_spawn_rate) + if (i >= max_daemons_limit && free_length == idle_spawn_rate) break; ws = &ap_scoreboard_image->servers[i][0]; status = ws->status; @@ -827,7 +843,7 @@ static void perform_idle_server_maintenance(apr_pool_t *p) last_non_dead = i; } } - ap_max_daemons_limit = last_non_dead + 1; + max_daemons_limit = last_non_dead + 1; if (idle_count > ap_daemons_max_free) { /* kill off one child... we use the pod because that'll cause it to * shut down gracefully, in case it happened to pick up a request @@ -892,7 +908,7 @@ static void perform_idle_server_maintenance(apr_pool_t *p) * Executive routines. */ -int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s) +static int prefork_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s) { int index; int remaining_children_to_start; @@ -939,7 +955,7 @@ int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s) /* fix the generation number in the global score; we just got a new, * cleared scoreboard */ - ap_scoreboard_image->global->running_generation = ap_my_generation; + ap_scoreboard_image->global->running_generation = my_generation; } set_signals(); @@ -1113,7 +1129,7 @@ int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s) ap_close_listeners(); /* kill off the idle ones */ - ap_mpm_pod_killpg(pod, ap_max_daemons_limit); + ap_mpm_pod_killpg(pod, max_daemons_limit); /* Send SIGUSR1 to the active children */ active_children = 0; @@ -1188,15 +1204,15 @@ int ap_mpm_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. */ - ++ap_my_generation; - ap_scoreboard_image->global->running_generation = ap_my_generation; + ++my_generation; + ap_scoreboard_image->global->running_generation = my_generation; if (is_graceful) { ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, "Graceful restart requested, doing restart"); /* kill off the idle ones */ - ap_mpm_pod_killpg(pod, ap_max_daemons_limit); + ap_mpm_pod_killpg(pod, max_daemons_limit); /* This is mostly for debugging... so that we know what is still * gracefully dealing with existing request. This will break @@ -1409,7 +1425,7 @@ static int prefork_check_config(apr_pool_t *p, apr_pool_t *plog, ap_daemons_limit = 1; } - /* ap_daemons_to_start > ap_daemons_limit checked in ap_mpm_run() */ + /* ap_daemons_to_start > ap_daemons_limit checked in prefork_run() */ if (ap_daemons_to_start < 0) { if (startup) { ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, @@ -1440,7 +1456,7 @@ static int prefork_check_config(apr_pool_t *p, apr_pool_t *plog, ap_daemons_min_free = 1; } - /* ap_daemons_max_free < ap_daemons_min_free + 1 checked in ap_mpm_run() */ + /* ap_daemons_max_free < ap_daemons_min_free + 1 checked in prefork_run() */ return OK; } @@ -1463,6 +1479,10 @@ 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_hook_mpm_get_child_pid(prefork_get_child_pid, NULL, NULL, APR_HOOK_MIDDLE); + ap_hook_mpm_note_child_killed(prefork_note_child_killed, NULL, NULL, APR_HOOK_MIDDLE); } static const char *set_daemons_to_start(cmd_parms *cmd, void *dummy, const char *arg) diff --git a/server/mpm/simple/mpm.h b/server/mpm/simple/mpm.h deleted file mode 100644 index 610b617119..0000000000 --- a/server/mpm/simple/mpm.h +++ /dev/null @@ -1,32 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "httpd.h" - -#ifndef APACHE_MPM_SIMPLE_H -#define APACHE_MPM_SIMPLE_H - -#define MPM_NAME "Simple" - -/* pqXXXXXX: shouldn't need this really. */ -#define AP_MPM_WANT_SIGNAL_SERVER - -/* pqXXXXXX: signal server has a hidden dependency */ -#define AP_MPM_WANT_SET_PIDFILE - -extern server_rec *ap_server_conf; - -#endif /* APACHE_MPM_SIMPLE_H */ diff --git a/server/mpm/simple/simple_api.c b/server/mpm/simple/simple_api.c index db9b2f7f1b..d9befb3c96 100644 --- a/server/mpm/simple/simple_api.c +++ b/server/mpm/simple/simple_api.c @@ -14,7 +14,6 @@ * limitations under the License. */ -#include "mpm.h" #include "ap_mpm.h" #include "httpd.h" #include "http_config.h" @@ -26,13 +25,9 @@ #include "simple_run.h" #include "http_core.h" -/* Thie file contains the absolute minimal MPM API, to interface with httpd. */ +/* This file contains the absolute minimal MPM API, to interface with httpd. */ -ap_generation_t volatile ap_my_generation = 0; -server_rec *ap_server_conf = NULL; - - - int ap_mpm_run(apr_pool_t * pconf, apr_pool_t * plog, server_rec * s) +static int simple_run(apr_pool_t * pconf, apr_pool_t * plog, server_rec * s) { simple_core_t *sc = simple_core_get(); @@ -46,7 +41,7 @@ server_rec *ap_server_conf = NULL; return simple_main_loop(sc); } -apr_status_t ap_mpm_query(int query_code, int *result) +static apr_status_t simple_query(int query_code, int *result) { simple_core_t *sc = simple_core_get(); @@ -103,6 +98,9 @@ apr_status_t ap_mpm_query(int query_code, int *result) case AP_MPMQ_MPM_STATE: *result = sc->mpm_state; return APR_SUCCESS; + case AP_MPMQ_GENERATION: + *result = 0; + return APR_SUCCESS; default: break; } @@ -116,8 +114,6 @@ simple_open_logs(apr_pool_t * p, { int nsock; - ap_server_conf = s; - nsock = ap_setup_listeners(s); if (nsock < 1) { @@ -232,6 +228,9 @@ static void simple_hooks(apr_pool_t * p) ap_hook_check_config(simple_check_config, NULL, NULL, APR_HOOK_MIDDLE); + ap_hook_mpm(simple_run, NULL, NULL, APR_HOOK_MIDDLE); + + ap_hook_mpm_query(simple_query, NULL, NULL, APR_HOOK_MIDDLE); } static const char *set_proccount(cmd_parms * cmd, void *baton, diff --git a/server/mpm/winnt/mpm.h b/server/mpm/winnt/mpm.h index 5312c3610c..4228e4f4b6 100644 --- a/server/mpm/winnt/mpm.h +++ b/server/mpm/winnt/mpm.h @@ -34,15 +34,20 @@ #define MPM_NAME "WinNT" -#define AP_MPM_WANT_SET_PIDFILE -#define AP_MPM_WANT_SET_MAX_REQUESTS -#define AP_MPM_WANT_SET_SCOREBOARD -#define AP_MPM_WANT_SET_MAX_MEM_FREE -#define AP_MPM_WANT_SET_STACKSIZE +#define AP_MPM_NO_SET_ACCEPT_LOCK_MECH +#define AP_MPM_NO_RECLAIM_CHILD_PROCESSES +#define AP_MPM_NO_WAIT_OR_TIMEOUT +#define AP_MPM_NO_PROCESS_CHILD_STATUS +#define AP_MPM_NO_POD +#define AP_MPM_NO_SET_LOCKFILE +#define AP_MPM_NO_SET_COREDUMPDIR +#define AP_MPM_NO_SET_SCOREBOARD +#define AP_MPM_NO_SET_GRACEFUL_SHUTDOWN +#define AP_MPM_NO_SIGNAL_SERVER +#define AP_MPM_NO_FATAL_SIGNAL_HANDLER extern int ap_threads_per_child; extern int ap_thread_limit; -extern server_rec *ap_server_conf; #endif /* APACHE_MPM_H */ /** @} */ diff --git a/server/mpm/winnt/mpm_winnt.c b/server/mpm/winnt/mpm_winnt.c index 1422041fa4..60309fb98a 100644 --- a/server/mpm/winnt/mpm_winnt.c +++ b/server/mpm/winnt/mpm_winnt.c @@ -44,8 +44,8 @@ */ extern apr_shm_t *ap_scoreboard_shm; -/* ap_my_generation are used by the scoreboard code */ -ap_generation_t volatile ap_my_generation=0; +/* my_generation is returned to the scoreboard code */ +static ap_generation_t volatile my_generation=0; /* Definitions of WINNT MPM specific config globals */ static HANDLE shutdown_event; /* used to signal the parent to shutdown */ @@ -78,11 +78,6 @@ int winnt_mpm_state = AP_MPMQ_STARTING; */ apr_pool_t *pconf; -/* on several occasions we don't have the global server context - * although it's needed for logging, etc. - */ -server_rec *ap_server_conf; - /* definitions from child.c */ void child_main(apr_pool_t *pconf); @@ -843,8 +838,8 @@ static int master_main(server_rec *s, HANDLE shutdown_event, HANDLE restart_even event_handles[CHILD_HANDLE] = NULL; } if (restart_pending) { - ++ap_my_generation; - ap_scoreboard_image->global->running_generation = ap_my_generation; + ++my_generation; + ap_scoreboard_image->global->running_generation = my_generation; } die_now: if (shutdown_pending) @@ -898,7 +893,7 @@ apr_array_header_t *mpm_new_argv; * service after we preflight the config. */ -AP_DECLARE(apr_status_t) ap_mpm_query(int query_code, int *result) +static apr_status_t winnt_query(int query_code, int *result) { switch(query_code){ case AP_MPMQ_MAX_DAEMON_USED: @@ -940,6 +935,9 @@ AP_DECLARE(apr_status_t) ap_mpm_query(int query_code, int *result) case AP_MPMQ_MPM_STATE: *result = winnt_mpm_state; return APR_SUCCESS; + case AP_MPMQ_GENERATION: + *result = my_generation; + return APR_SUCCESS; } return APR_ENOTIMPL; } @@ -1334,7 +1332,7 @@ static int winnt_pre_config(apr_pool_t *pconf_, apr_pool_t *plog, apr_pool_t *pt service_name); exit(APEXIT_INIT); } - else if (!one_process && !ap_my_generation) { + else if (!one_process && !my_generation) { /* Open a null handle to soak stdout in this process. * We need to emulate apr_proc_detach, unix performs this * same check in the pre_config hook (although it is @@ -1635,7 +1633,7 @@ static void winnt_child_init(apr_pool_t *pchild, struct server_rec *s) /* Done reading from the parent, close that channel */ CloseHandle(pipe); - ap_my_generation = ap_scoreboard_image->global->running_generation; + my_generation = ap_scoreboard_image->global->running_generation; } else { /* Single process mode - this lock doesn't even need to exist */ @@ -1654,7 +1652,7 @@ static void winnt_child_init(apr_pool_t *pchild, struct server_rec *s) } -AP_DECLARE(int) ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s ) +static int winnt_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s ) { static int restart = 0; /* Default is "not a restart" */ @@ -1729,6 +1727,8 @@ static void winnt_hooks(apr_pool_t *p) ap_hook_post_config(winnt_post_config, NULL, NULL, 0); ap_hook_child_init(winnt_child_init, NULL, NULL, APR_HOOK_MIDDLE); ap_hook_open_logs(winnt_open_logs, NULL, aszSucc, APR_HOOK_REALLY_FIRST); + ap_hook_mpm(winnt_run, NULL, NULL, APR_HOOK_MIDDLE); + ap_hook_mpm_query(winnt_query, NULL, NULL, APR_HOOK_MIDDLE); } AP_MODULE_DECLARE_DATA module mpm_winnt_module = { diff --git a/server/mpm/worker/mpm.h b/server/mpm/worker/mpm.h deleted file mode 100644 index 59fe752b02..0000000000 --- a/server/mpm/worker/mpm.h +++ /dev/null @@ -1,62 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file worker/mpm.h - * @brief Unix Worker MPM - * - * @defgroup APACHE_MPM_WORKER Unix Worker MPM - * @ingroup APACHE_OS_UNIX APACHE_MPM - * @{ - */ - -#include "scoreboard.h" -#include "unixd.h" - -#ifndef APACHE_MPM_WORKER_H -#define APACHE_MPM_WORKER_H - -#define WORKER_MPM - -#define MPM_NAME "Worker" - -#define AP_MPM_WANT_RECLAIM_CHILD_PROCESSES -#define AP_MPM_WANT_WAIT_OR_TIMEOUT -#define AP_MPM_WANT_PROCESS_CHILD_STATUS -#define AP_MPM_WANT_SET_PIDFILE -#define AP_MPM_WANT_SET_SCOREBOARD -#define AP_MPM_WANT_SET_LOCKFILE -#define AP_MPM_WANT_SET_MAX_REQUESTS -#define AP_MPM_WANT_SET_COREDUMPDIR -#define AP_MPM_WANT_SET_ACCEPT_LOCK_MECH -#define AP_MPM_WANT_SIGNAL_SERVER -#define AP_MPM_WANT_SET_MAX_MEM_FREE -#define AP_MPM_WANT_SET_STACKSIZE -#define AP_MPM_WANT_SET_GRACEFUL_SHUTDOWN -#define AP_MPM_WANT_FATAL_SIGNAL_HANDLER -#define AP_MPM_DISABLE_NAGLE_ACCEPTED_SOCK - -#define MPM_CHILD_PID(i) (ap_scoreboard_image->parent[i].pid) -#define MPM_NOTE_CHILD_KILLED(i) (MPM_CHILD_PID(i) = 0) -#define MPM_ACCEPT_FUNC ap_unixd_accept - -extern int ap_threads_per_child; -extern int ap_max_daemons_limit; -extern server_rec *ap_server_conf; -extern char ap_coredump_dir[MAX_STRING_LEN]; - -#endif /* APACHE_MPM_WORKER_H */ -/** @} */ diff --git a/server/mpm/worker/pod.c b/server/mpm/worker/pod.c index 77ad1c90c2..d6ebb240e4 100644 --- a/server/mpm/worker/pod.c +++ b/server/mpm/worker/pod.c @@ -14,13 +14,14 @@ * limitations under the License. */ +#include "apr_portable.h" #include "pod.h" #if APR_HAVE_UNISTD_H #include <unistd.h> #endif -AP_DECLARE(apr_status_t) ap_mpm_pod_open(apr_pool_t *p, ap_pod_t **pod) +AP_DECLARE(apr_status_t) ap_worker_pod_open(apr_pool_t *p, ap_worker_pod_t **pod) { apr_status_t rv; @@ -41,7 +42,7 @@ AP_DECLARE(apr_status_t) ap_mpm_pod_open(apr_pool_t *p, ap_pod_t **pod) return APR_SUCCESS; } -AP_DECLARE(int) ap_mpm_pod_check(ap_pod_t *pod) +AP_DECLARE(int) ap_worker_pod_check(ap_worker_pod_t *pod) { char c; apr_os_file_t fd; @@ -63,7 +64,7 @@ AP_DECLARE(int) ap_mpm_pod_check(ap_pod_t *pod) return AP_NORESTART; } -AP_DECLARE(apr_status_t) ap_mpm_pod_close(ap_pod_t *pod) +AP_DECLARE(apr_status_t) ap_worker_pod_close(ap_worker_pod_t *pod) { apr_status_t rv; @@ -79,7 +80,7 @@ AP_DECLARE(apr_status_t) ap_mpm_pod_close(ap_pod_t *pod) return rv; } -static apr_status_t pod_signal_internal(ap_pod_t *pod, int graceful) +static apr_status_t pod_signal_internal(ap_worker_pod_t *pod, int graceful) { apr_status_t rv; char char_of_death = graceful ? GRACEFUL_CHAR : RESTART_CHAR; @@ -93,12 +94,12 @@ static apr_status_t pod_signal_internal(ap_pod_t *pod, int graceful) return rv; } -AP_DECLARE(apr_status_t) ap_mpm_pod_signal(ap_pod_t *pod, int graceful) +AP_DECLARE(apr_status_t) ap_worker_pod_signal(ap_worker_pod_t *pod, int graceful) { return pod_signal_internal(pod, graceful); } -AP_DECLARE(void) ap_mpm_pod_killpg(ap_pod_t *pod, int num, int graceful) +AP_DECLARE(void) ap_worker_pod_killpg(ap_worker_pod_t *pod, int num, int graceful) { int i; apr_status_t rv = APR_SUCCESS; diff --git a/server/mpm/worker/pod.h b/server/mpm/worker/pod.h index 55cad81950..ccb9cf9d70 100644 --- a/server/mpm/worker/pod.h +++ b/server/mpm/worker/pod.h @@ -31,7 +31,6 @@ #include "http_config.h" #include "http_log.h" #include "http_main.h" -#include "mpm.h" #include "mpm_common.h" #include "ap_mpm.h" #include "ap_listen.h" @@ -43,17 +42,17 @@ #define AP_RESTART 0 #define AP_GRACEFUL 1 -typedef struct ap_pod_t ap_pod_t; +typedef struct ap_worker_pod_t ap_worker_pod_t; -struct ap_pod_t { +struct ap_worker_pod_t { apr_file_t *pod_in; apr_file_t *pod_out; apr_pool_t *p; }; -AP_DECLARE(apr_status_t) ap_mpm_pod_open(apr_pool_t *p, ap_pod_t **pod); -AP_DECLARE(int) ap_mpm_pod_check(ap_pod_t *pod); -AP_DECLARE(apr_status_t) ap_mpm_pod_close(ap_pod_t *pod); -AP_DECLARE(apr_status_t) ap_mpm_pod_signal(ap_pod_t *pod, int graceful); -AP_DECLARE(void) ap_mpm_pod_killpg(ap_pod_t *pod, int num, int graceful); +AP_DECLARE(apr_status_t) ap_worker_pod_open(apr_pool_t *p, ap_worker_pod_t **pod); +AP_DECLARE(int) ap_worker_pod_check(ap_worker_pod_t *pod); +AP_DECLARE(apr_status_t) ap_worker_pod_close(ap_worker_pod_t *pod); +AP_DECLARE(apr_status_t) ap_worker_pod_signal(ap_worker_pod_t *pod, int graceful); +AP_DECLARE(void) ap_worker_pod_killpg(ap_worker_pod_t *pod, int num, int graceful); /** @} */ diff --git a/server/mpm/worker/worker.c b/server/mpm/worker/worker.c index a530dc5a6b..ddfaa65252 100644 --- a/server/mpm/worker/worker.c +++ b/server/mpm/worker/worker.c @@ -64,6 +64,7 @@ #include "scoreboard.h" #include "fdqueue.h" #include "mpm_default.h" +#include "unixd.h" #include <signal.h> #include <limits.h> /* for INT_MAX */ @@ -112,7 +113,7 @@ * Actual definitions of config globals */ -int ap_threads_per_child = 0; /* Worker threads per child */ +static int threads_per_child = 0; /* Worker threads per child */ static int ap_daemons_to_start = 0; static int min_spare_threads = 0; static int max_spare_threads = 0; @@ -133,6 +134,9 @@ 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; + +#define MPM_CHILD_PID(i) (ap_scoreboard_image->parent[i].pid) /* The structure used to pass unique initialization info to each thread */ typedef struct { @@ -159,13 +163,9 @@ typedef struct { * use this value to optimize routines that have to scan the entire * scoreboard. */ -int ap_max_daemons_limit = -1; - -static ap_pod_t *pod; - -/* *Non*-shared http_main globals... */ +static int max_daemons_limit = -1; -server_rec *ap_server_conf; +static ap_worker_pod_t *pod; /* The worker MPM respects a couple of runtime flags that can aid * in debugging. Setting the -DNO_DETACH flag will prevent the root process @@ -231,7 +231,7 @@ static apr_socket_t **worker_sockets; static void close_worker_sockets(void) { int i; - for (i = 0; i < ap_threads_per_child; i++) { + for (i = 0; i < threads_per_child; i++) { if (worker_sockets[i]) { apr_socket_close(worker_sockets[i]); worker_sockets[i] = NULL; @@ -296,11 +296,11 @@ static void signal_threads(int mode) } } -AP_DECLARE(apr_status_t) ap_mpm_query(int query_code, int *result) +static apr_status_t worker_query(int query_code, int *result) { switch(query_code){ case AP_MPMQ_MAX_DAEMON_USED: - *result = ap_max_daemons_limit; + *result = max_daemons_limit; return APR_SUCCESS; case AP_MPMQ_IS_THREADED: *result = AP_MPMQ_STATIC; @@ -315,7 +315,7 @@ AP_DECLARE(apr_status_t) ap_mpm_query(int query_code, int *result) *result = thread_limit; return APR_SUCCESS; case AP_MPMQ_MAX_THREADS: - *result = ap_threads_per_child; + *result = threads_per_child; return APR_SUCCESS; case AP_MPMQ_MIN_SPARE_DAEMONS: *result = 0; @@ -338,10 +338,24 @@ AP_DECLARE(apr_status_t) ap_mpm_query(int query_code, int *result) case AP_MPMQ_MPM_STATE: *result = mpm_state; return APR_SUCCESS; + case AP_MPMQ_GENERATION: + *result = my_generation; + return APR_SUCCESS; } return APR_ENOTIMPL; } +static pid_t worker_get_child_pid(int childnum) +{ + return ap_scoreboard_image->parent[childnum].pid; +} + +static apr_status_t worker_note_child_killed(int childnum) +{ + ap_scoreboard_image->parent[childnum].pid = 0; + return APR_SUCCESS; +} + /* 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) @@ -367,7 +381,6 @@ static int volatile shutdown_pending; static int volatile restart_pending; static int volatile is_graceful; static volatile int child_fatal; -ap_generation_t volatile ap_my_generation = 0; /* * ap_start_shutdown() and ap_start_restart(), below, are a first stab at @@ -608,6 +621,8 @@ static void * APR_THREAD_FUNC listener_thread(apr_thread_t *thd, void * dummy) /* ### check the status */ (void) apr_pollset_add(pollset, &pfd); + + lr->accept_func = ap_unixd_accept; } /* Unblock the signal used to wake this thread up, and set a handler for @@ -822,7 +837,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 = ap_my_generation; + ap_scoreboard_image->servers[process_slot][thread_slot].generation = my_generation; ap_update_child_status_from_indexes(process_slot, thread_slot, SERVER_STARTING, NULL); #ifdef HAVE_PTHREAD_KILL @@ -951,7 +966,7 @@ static void * APR_THREAD_FUNC start_threads(apr_thread_t *thd, void *dummy) /* We must create the fd queues before we start up the listener * and worker threads. */ worker_queue = apr_pcalloc(pchild, sizeof(*worker_queue)); - rv = ap_queue_init(worker_queue, ap_threads_per_child, pchild); + rv = ap_queue_init(worker_queue, threads_per_child, pchild); if (rv != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf, "ap_queue_init() failed"); @@ -959,20 +974,20 @@ static void * APR_THREAD_FUNC start_threads(apr_thread_t *thd, void *dummy) } rv = ap_queue_info_create(&worker_queue_info, pchild, - ap_threads_per_child); + threads_per_child); if (rv != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf, "ap_queue_info_create() failed"); clean_child_exit(APEXIT_CHILDFATAL); } - worker_sockets = apr_pcalloc(pchild, ap_threads_per_child + worker_sockets = apr_pcalloc(pchild, threads_per_child * sizeof(apr_socket_t *)); loops = prev_threads_created = 0; while (1) { - /* ap_threads_per_child does not include the listener thread */ - for (i = 0; i < ap_threads_per_child; i++) { + /* threads_per_child does not include the listener thread */ + for (i = 0; i < threads_per_child; i++) { int status = ap_scoreboard_image->servers[child_num_arg][i].status; if (status != SERVER_GRACEFUL && status != SERVER_DEAD) { @@ -1010,7 +1025,7 @@ static void * APR_THREAD_FUNC start_threads(apr_thread_t *thd, void *dummy) create_listener_thread(ts); listener_started = 1; } - if (start_thread_may_exit || threads_created == ap_threads_per_child) { + if (start_thread_may_exit || threads_created == threads_per_child) { break; } /* wait for previous generation to clean up an entry */ @@ -1021,7 +1036,7 @@ static void * APR_THREAD_FUNC start_threads(apr_thread_t *thd, void *dummy) ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, "child %" APR_PID_T_FMT " isn't taking over " "slots very quickly (%d of %d)", - ap_my_pid, threads_created, ap_threads_per_child); + ap_my_pid, threads_created, threads_per_child); } prev_threads_created = threads_created; } @@ -1083,7 +1098,7 @@ static void join_workers(apr_thread_t *listener, apr_thread_t **threads) } } - for (i = 0; i < ap_threads_per_child; i++) { + for (i = 0; i < threads_per_child; i++) { if (threads[i]) { /* if we ever created this thread */ #ifdef HAVE_PTHREAD_KILL apr_os_thread_t *worker_os_thread; @@ -1178,7 +1193,7 @@ static void child_main(int child_num_arg) * and we want a 0 entry to indicate a thread which was not created */ threads = (apr_thread_t **)calloc(1, - sizeof(apr_thread_t *) * ap_threads_per_child); + sizeof(apr_thread_t *) * threads_per_child); if (threads == NULL) { ap_log_error(APLOG_MARK, APLOG_ALERT, errno, ap_server_conf, "malloc: out of memory"); @@ -1246,7 +1261,7 @@ static void child_main(int child_num_arg) apr_signal(SIGTERM, dummy_signal_handler); /* Watch for any messages from the parent over the POD */ while (1) { - rv = ap_mpm_pod_check(pod); + rv = ap_worker_pod_check(pod); if (rv == AP_NORESTART) { /* see if termination was triggered while we slept */ switch(terminate_mode) { @@ -1287,8 +1302,8 @@ static int make_child(server_rec *s, int slot) { int pid; - if (slot + 1 > ap_max_daemons_limit) { - ap_max_daemons_limit = slot + 1; + if (slot + 1 > max_daemons_limit) { + max_daemons_limit = slot + 1; } if (one_process) { @@ -1406,19 +1421,19 @@ static void perform_idle_server_maintenance(void) for (i = 0; i < ap_daemons_limit; ++i) { /* Initialization to satisfy the compiler. It doesn't know - * that ap_threads_per_child is always > 0 */ + * that threads_per_child is always > 0 */ int status = SERVER_DEAD; int any_dying_threads = 0; int any_dead_threads = 0; int all_dead_threads = 1; - if (i >= ap_max_daemons_limit && totally_free_length == idle_spawn_rate) + if (i >= max_daemons_limit && totally_free_length == idle_spawn_rate) /* short cut if all active processes have been examined and * enough empty scoreboard slots have been found */ break; ps = &ap_scoreboard_image->parent[i]; - for (j = 0; j < ap_threads_per_child; j++) { + for (j = 0; j < threads_per_child; j++) { ws = &ap_scoreboard_image->servers[i][j]; status = ws->status; @@ -1440,7 +1455,7 @@ static void perform_idle_server_maintenance(void) loop if no pid? not much else matters */ if (status <= SERVER_READY && !ps->quiescing && - ps->generation == ap_my_generation) { + ps->generation == my_generation) { ++idle_thread_count; } if (status >= SERVER_READY && status < SERVER_GRACEFUL) { @@ -1498,18 +1513,18 @@ static void perform_idle_server_maintenance(void) } } - ap_max_daemons_limit = last_non_dead + 1; + max_daemons_limit = last_non_dead + 1; if (idle_thread_count > max_spare_threads) { /* Kill off one child */ - ap_mpm_pod_signal(pod, TRUE); + ap_worker_pod_signal(pod, TRUE); 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 * ap_threads_per_child) { + if (active_thread_count >= ap_daemons_limit * threads_per_child) { static int reported = 0; if (!reported) { /* only report this condition once */ @@ -1587,7 +1602,7 @@ static void server_main_loop(int remaining_children_to_start) /* non-fatal death... note that it's gone in the scoreboard. */ child_slot = ap_find_child_by_pid(&pid); if (child_slot >= 0) { - for (i = 0; i < ap_threads_per_child; i++) + for (i = 0; i < threads_per_child; i++) ap_update_child_status_from_indexes(child_slot, i, SERVER_DEAD, (request_rec *) NULL); @@ -1649,7 +1664,7 @@ static void server_main_loop(int remaining_children_to_start) } } -int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s) +static int worker_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s) { int remaining_children_to_start; apr_status_t rv; @@ -1694,13 +1709,13 @@ int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s) /* fix the generation number in the global score; we just got a new, * cleared scoreboard */ - ap_scoreboard_image->global->running_generation = ap_my_generation; + ap_scoreboard_image->global->running_generation = my_generation; } set_signals(); /* Don't thrash... */ - if (max_spare_threads < min_spare_threads + ap_threads_per_child) - max_spare_threads = min_spare_threads + ap_threads_per_child; + if (max_spare_threads < min_spare_threads + threads_per_child) + max_spare_threads = min_spare_threads + threads_per_child; /* 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 @@ -1746,7 +1761,7 @@ int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s) /* Time to shut down: * Kill child processes, tell them to call child_exit, etc... */ - ap_mpm_pod_killpg(pod, ap_daemons_limit, FALSE); + ap_worker_pod_killpg(pod, ap_daemons_limit, FALSE); ap_reclaim_child_processes(1); /* Start with SIGTERM */ if (!child_fatal) { @@ -1773,7 +1788,7 @@ int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s) /* Close our listeners, and then ask our children to do same */ ap_close_listeners(); - ap_mpm_pod_killpg(pod, ap_daemons_limit, TRUE); + ap_worker_pod_killpg(pod, ap_daemons_limit, TRUE); ap_relieve_child_processes(); if (!child_fatal) { @@ -1820,7 +1835,7 @@ int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s) * way, try and make sure that all of our processes are * really dead. */ - ap_mpm_pod_killpg(pod, ap_daemons_limit, FALSE); + ap_worker_pod_killpg(pod, ap_daemons_limit, FALSE); ap_reclaim_child_processes(1); return 1; @@ -1838,14 +1853,14 @@ int ap_mpm_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. */ - ++ap_my_generation; - ap_scoreboard_image->global->running_generation = ap_my_generation; + ++my_generation; + ap_scoreboard_image->global->running_generation = my_generation; if (is_graceful) { ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, AP_SIG_GRACEFUL_STRING " received. Doing graceful restart"); /* wake up the children...time to die. But we'll have more soon */ - ap_mpm_pod_killpg(pod, ap_daemons_limit, TRUE); + ap_worker_pod_killpg(pod, ap_daemons_limit, TRUE); /* This is mostly for debugging... so that we know what is still @@ -1858,7 +1873,7 @@ int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s) * and a SIGHUP, we may as well use the same signal, because some user * pthreads are stealing signals from us left and right. */ - ap_mpm_pod_killpg(pod, ap_daemons_limit, FALSE); + ap_worker_pod_killpg(pod, ap_daemons_limit, FALSE); ap_reclaim_child_processes(1); /* Start with SIGTERM */ ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, @@ -1879,7 +1894,6 @@ static int worker_open_logs(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, apr_status_t rv; pconf = p; - ap_server_conf = s; /* the reverse of pre_config, we want this only the first time around */ if (restart_num++ == 0) { @@ -1895,7 +1909,7 @@ static int worker_open_logs(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, } if (!one_process) { - if ((rv = ap_mpm_pod_open(pconf, &pod))) { + if ((rv = ap_worker_pod_open(pconf, &pod))) { ap_log_error(APLOG_MARK, APLOG_CRIT | level_flags, rv, (startup ? NULL : s), "could not open pipe-of-death"); @@ -1949,8 +1963,8 @@ static int worker_pre_config(apr_pool_t *pconf, apr_pool_t *plog, server_limit = DEFAULT_SERVER_LIMIT; thread_limit = DEFAULT_THREAD_LIMIT; ap_daemons_limit = server_limit; - ap_threads_per_child = DEFAULT_THREADS_PER_CHILD; - max_clients = ap_daemons_limit * ap_threads_per_child; + threads_per_child = DEFAULT_THREADS_PER_CHILD; + max_clients = ap_daemons_limit * threads_per_child; ap_pid_fname = DEFAULT_PIDLOG; ap_lock_fname = DEFAULT_LOCKFILE; ap_max_requests_per_child = DEFAULT_MAX_REQUESTS_PER_CHILD; @@ -2063,11 +2077,11 @@ static int worker_check_config(apr_pool_t *p, apr_pool_t *plog, thread_limit = first_thread_limit; } - if (ap_threads_per_child > thread_limit) { + if (threads_per_child > thread_limit) { if (startup) { ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, "WARNING: ThreadsPerChild of %d exceeds ThreadLimit " - "of", ap_threads_per_child); + "of", threads_per_child); ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, " %d threads, decreasing to %d.", thread_limit, thread_limit); @@ -2078,24 +2092,24 @@ static int worker_check_config(apr_pool_t *p, apr_pool_t *plog, ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, "ThreadsPerChild of %d exceeds ThreadLimit " "of %d, decreasing to match", - ap_threads_per_child, thread_limit); + threads_per_child, thread_limit); } - ap_threads_per_child = thread_limit; + threads_per_child = thread_limit; } - else if (ap_threads_per_child < 1) { + else if (threads_per_child < 1) { if (startup) { ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, "WARNING: ThreadsPerChild of %d not allowed, " - "increasing to 1.", ap_threads_per_child); + "increasing to 1.", threads_per_child); } else { ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, "ThreadsPerChild of %d not allowed, increasing to 1", - ap_threads_per_child); + threads_per_child); } - ap_threads_per_child = 1; + threads_per_child = 1; } - if (max_clients < ap_threads_per_child) { + if (max_clients < threads_per_child) { if (startup) { ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, "WARNING: MaxClients of %d is less than " @@ -2103,22 +2117,22 @@ static int worker_check_config(apr_pool_t *p, apr_pool_t *plog, ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, " %d, increasing to %d. MaxClients must be at " "least as large", - ap_threads_per_child, ap_threads_per_child); + threads_per_child, threads_per_child); ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, " as the number of threads in a single server."); } else { ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, "MaxClients of %d is less than ThreadsPerChild " "of %d, increasing to match", - max_clients, ap_threads_per_child); + max_clients, threads_per_child); } - max_clients = ap_threads_per_child; + max_clients = threads_per_child; } - ap_daemons_limit = max_clients / ap_threads_per_child; + ap_daemons_limit = max_clients / threads_per_child; - if (max_clients % ap_threads_per_child) { - int tmp_max_clients = ap_daemons_limit * ap_threads_per_child; + if (max_clients % threads_per_child) { + int tmp_max_clients = ap_daemons_limit * threads_per_child; if (startup) { ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, @@ -2126,7 +2140,7 @@ static int worker_check_config(apr_pool_t *p, apr_pool_t *plog, "multiple of", max_clients); ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, " ThreadsPerChild of %d, decreasing to nearest " - "multiple %d,", ap_threads_per_child, + "multiple %d,", threads_per_child, tmp_max_clients); ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, " for a maximum of %d servers.", @@ -2135,7 +2149,7 @@ static int worker_check_config(apr_pool_t *p, apr_pool_t *plog, ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, "MaxClients of %d is not an integer multiple of " "ThreadsPerChild of %d, decreasing to nearest " - "multiple %d", max_clients, ap_threads_per_child, + "multiple %d", max_clients, threads_per_child, tmp_max_clients); } max_clients = tmp_max_clients; @@ -2148,7 +2162,7 @@ static int worker_check_config(apr_pool_t *p, apr_pool_t *plog, "servers and ", max_clients, ap_daemons_limit); ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, " would exceed ServerLimit of %d, decreasing to %d.", - server_limit, server_limit * ap_threads_per_child); + server_limit, server_limit * threads_per_child); ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, " To increase, please see the ServerLimit " "directive."); @@ -2157,12 +2171,12 @@ static int worker_check_config(apr_pool_t *p, apr_pool_t *plog, "MaxClients of %d would require %d servers and " "exceed ServerLimit of %d, decreasing to %d", max_clients, ap_daemons_limit, server_limit, - server_limit * ap_threads_per_child); + server_limit * threads_per_child); } ap_daemons_limit = server_limit; } - /* ap_daemons_to_start > ap_daemons_limit checked in ap_mpm_run() */ + /* ap_daemons_to_start > ap_daemons_limit checked in worker_run() */ if (ap_daemons_to_start < 0) { if (startup) { ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, @@ -2193,8 +2207,8 @@ static int worker_check_config(apr_pool_t *p, apr_pool_t *plog, min_spare_threads = 1; } - /* max_spare_threads < min_spare_threads + ap_threads_per_child - * checked in ap_mpm_run() + /* max_spare_threads < min_spare_threads + threads_per_child + * checked in worker_run() */ return OK; @@ -2215,6 +2229,10 @@ 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_hook_mpm_get_child_pid(worker_get_child_pid, NULL, NULL, APR_HOOK_MIDDLE); + ap_hook_mpm_note_child_killed(worker_note_child_killed, NULL, NULL, APR_HOOK_MIDDLE); } static const char *set_daemons_to_start(cmd_parms *cmd, void *dummy, @@ -2273,7 +2291,7 @@ static const char *set_threads_per_child (cmd_parms *cmd, void *dummy, return err; } - ap_threads_per_child = atoi(arg); + threads_per_child = atoi(arg); return NULL; } diff --git a/server/mpm_common.c b/server/mpm_common.c index 72b0e66583..e6a70a86a1 100644 --- a/server/mpm_common.c +++ b/server/mpm_common.c @@ -39,14 +39,12 @@ #include "http_config.h" #include "http_log.h" #include "http_main.h" -#include "mpm.h" #include "mpm_common.h" #include "ap_mpm.h" #include "ap_listen.h" -#include "mpm_default.h" #include "util_mutex.h" -#ifdef AP_MPM_WANT_SET_SCOREBOARD +#ifndef AP_MPM_NO_SET_SCOREBOARD #include "scoreboard.h" #endif @@ -65,6 +63,11 @@ APR_HOOK_STRUCT( APR_HOOK_LINK(fatal_exception) APR_HOOK_LINK(monitor) APR_HOOK_LINK(drop_privileges) + APR_HOOK_LINK(mpm) + APR_HOOK_LINK(mpm_query) + APR_HOOK_LINK(mpm_get_child_pid) + APR_HOOK_LINK(mpm_note_child_killed) + APR_HOOK_LINK(mpm_register_timed_callback) ) AP_IMPLEMENT_HOOK_RUN_ALL(int, fatal_exception, (ap_exception_info_t *ei), (ei), OK, DECLINED) @@ -72,6 +75,11 @@ AP_IMPLEMENT_HOOK_RUN_ALL(int, fatal_exception, APR_HOOK_STRUCT( APR_HOOK_LINK(monitor) APR_HOOK_LINK(drop_privileges) + APR_HOOK_LINK(mpm) + APR_HOOK_LINK(mpm_query) + APR_HOOK_LINK(mpm_get_child_pid) + APR_HOOK_LINK(mpm_note_child_killed) + APR_HOOK_LINK(mpm_register_timed_callback) ) #endif AP_IMPLEMENT_HOOK_RUN_ALL(int, monitor, @@ -79,9 +87,30 @@ AP_IMPLEMENT_HOOK_RUN_ALL(int, monitor, AP_IMPLEMENT_HOOK_RUN_ALL(int, drop_privileges, (apr_pool_t * pchild, server_rec * s), (pchild, s), OK, DECLINED) +AP_IMPLEMENT_HOOK_RUN_FIRST(int, mpm, + (apr_pool_t *pconf, apr_pool_t *plog, server_rec *s), + (pconf, plog, s), DECLINED) +AP_IMPLEMENT_HOOK_RUN_FIRST(apr_status_t, mpm_query, + (int query_code, int *result), + (query_code, result), APR_ENOTIMPL) +AP_IMPLEMENT_HOOK_RUN_FIRST(pid_t, mpm_get_child_pid, + (int childnum), + (childnum), 0) +AP_IMPLEMENT_HOOK_RUN_FIRST(apr_status_t, mpm_note_child_killed, + (int childnum), + (childnum), APR_ENOTIMPL) +AP_IMPLEMENT_HOOK_RUN_FIRST(apr_status_t, mpm_register_timed_callback, + (apr_time_t t, ap_mpm_callback_fn_t *cbfn, void *baton), + (t, cbfn, baton), APR_ENOTIMPL) + +/* XXX + * need better concept for controlling generation of MPM helper functions + * Unix MPMs don't have/need mpm.h; currently we rely on non-Unix MPMs providing that file + * with AP_MPM_NO_xxx defined for functions that won't work or won't be needed + * mpm_common.h has the #if HACK #include "mpm.h" + */ - -#ifdef AP_MPM_WANT_RECLAIM_CHILD_PROCESSES +#ifndef AP_MPM_NO_RECLAIM_CHILD_PROCESSES typedef enum {DO_NOTHING, SEND_SIGTERM, SEND_SIGKILL, GIVEUP} action_t; @@ -142,7 +171,7 @@ static int reclaim_one_pid(pid_t pid, action_t action) proc.pid = pid; waitret = apr_proc_wait(&proc, &status, &why, APR_NOWAIT); if (waitret != APR_CHILD_NOTDONE) { -#ifdef AP_MPM_WANT_PROCESS_CHILD_STATUS +#ifndef AP_MPM_NO_PROCESS_CHILD_STATUS if (waitret == APR_CHILD_DONE) ap_process_child_status(&proc, why, status); #endif @@ -257,14 +286,14 @@ void ap_reclaim_child_processes(int terminate) /* now see who is done */ not_dead_yet = 0; for (i = 0; i < max_daemons; ++i) { - pid_t pid = MPM_CHILD_PID(i); + pid_t pid = ap_mpm_get_child_pid(i); if (pid == 0) { continue; /* not every scoreboard entry is in use */ } if (reclaim_one_pid(pid, action_table[cur_action].action)) { - MPM_NOTE_CHILD_KILLED(i); + ap_mpm_note_child_killed(i); } else { ++not_dead_yet; @@ -301,14 +330,14 @@ void ap_relieve_child_processes(void) /* now see who is done */ for (i = 0; i < max_daemons; ++i) { - pid_t pid = MPM_CHILD_PID(i); + pid_t pid = ap_mpm_get_child_pid(i); if (pid == 0) { continue; /* not every scoreboard entry is in use */ } if (reclaim_one_pid(pid, DO_NOTHING)) { - MPM_NOTE_CHILD_KILLED(i); + ap_mpm_note_child_killed(i); } } @@ -343,7 +372,7 @@ apr_status_t ap_mpm_safe_kill(pid_t pid, int sig) proc.pid = pid; rv = apr_proc_wait(&proc, &status, &why, APR_NOWAIT); if (rv == APR_CHILD_DONE) { -#ifdef AP_MPM_WANT_PROCESS_CHILD_STATUS +#ifndef AP_MPM_NO_PROCESS_CHILD_STATUS /* The child already died - log the termination status if * necessary: */ ap_process_child_status(&proc, why, status); @@ -382,9 +411,9 @@ apr_status_t ap_mpm_safe_kill(pid_t pid, int sig) return kill(pid, sig) ? errno : APR_SUCCESS; } -#endif /* AP_MPM_WANT_RECLAIM_CHILD_PROCESSES */ +#endif /* AP_MPM_NO_RECLAIM_CHILD_PROCESSES */ -#ifdef AP_MPM_WANT_WAIT_OR_TIMEOUT +#ifndef AP_MPM_NO_WAIT_OR_TIMEOUT /* number of calls to wait_or_timeout between writable probes */ #ifndef INTERVAL_OF_WRITABLE_PROBES @@ -413,13 +442,13 @@ void ap_wait_or_timeout(apr_exit_why_e *status, int *exitcode, apr_proc_t *ret, return; } - apr_sleep(SCOREBOARD_MAINTENANCE_INTERVAL); + apr_sleep(1000000); ret->pid = -1; return; } -#endif /* AP_MPM_WANT_WAIT_OR_TIMEOUT */ +#endif /* AP_MPM_NO_WAIT_OR_TIMEOUT */ -#ifdef AP_MPM_WANT_PROCESS_CHILD_STATUS +#ifndef AP_MPM_NO_PROCESS_CHILD_STATUS int ap_process_child_status(apr_proc_t *pid, apr_exit_why_e why, int status) { int signum = status; @@ -479,7 +508,7 @@ int ap_process_child_status(apr_proc_t *pid, apr_exit_why_e why, int status) } return 0; } -#endif /* AP_MPM_WANT_PROCESS_CHILD_STATUS */ +#endif /* AP_MPM_NO_PROCESS_CHILD_STATUS */ #if defined(TCP_NODELAY) && !defined(MPE) && !defined(TPF) void ap_sock_disable_nagle(apr_socket_t *s) @@ -571,7 +600,7 @@ int initgroups(const char *name, gid_t basegid) } #endif /* def NEED_INITGROUPS */ -#ifdef AP_MPM_USES_POD +#ifndef AP_MPM_NO_POD AP_DECLARE(apr_status_t) ap_mpm_pod_open(apr_pool_t *p, ap_pod_t **pod) { @@ -777,7 +806,7 @@ void ap_mpm_pod_killpg(ap_pod_t *pod, int num) #endif /* #ifdef AP_MPM_USES_POD */ /* standard mpm configuration handling */ -#ifdef AP_MPM_WANT_SET_PIDFILE +#ifndef AP_MPM_NO_SET_PIDFILE const char *ap_pid_fname = NULL; const char *ap_mpm_set_pidfile(cmd_parms *cmd, void *dummy, @@ -797,7 +826,7 @@ const char *ap_mpm_set_pidfile(cmd_parms *cmd, void *dummy, } #endif -#ifdef AP_MPM_WANT_SET_SCOREBOARD +#ifndef AP_MPM_NO_SET_SCOREBOARD const char * ap_mpm_set_scoreboard(cmd_parms *cmd, void *dummy, const char *arg) { @@ -811,7 +840,7 @@ const char * ap_mpm_set_scoreboard(cmd_parms *cmd, void *dummy, } #endif -#ifdef AP_MPM_WANT_SET_LOCKFILE +#ifndef AP_MPM_NO_SET_LOCKFILE const char *ap_lock_fname = NULL; const char *ap_mpm_set_lockfile(cmd_parms *cmd, void *dummy, @@ -827,7 +856,7 @@ const char *ap_mpm_set_lockfile(cmd_parms *cmd, void *dummy, } #endif -#ifdef AP_MPM_WANT_SET_MAX_REQUESTS +#ifndef AP_MPM_NO_SET_MAX_REQUESTS int ap_max_requests_per_child = 0; const char *ap_mpm_set_max_requests(cmd_parms *cmd, void *dummy, @@ -844,7 +873,7 @@ const char *ap_mpm_set_max_requests(cmd_parms *cmd, void *dummy, } #endif -#ifdef AP_MPM_WANT_SET_COREDUMPDIR +#ifndef AP_MPM_NO_SET_COREDUMPDIR char ap_coredump_dir[MAX_STRING_LEN]; int ap_coredumpdir_configured; @@ -878,7 +907,7 @@ const char *ap_mpm_set_coredumpdir(cmd_parms *cmd, void *dummy, } #endif -#ifdef AP_MPM_WANT_SET_GRACEFUL_SHUTDOWN +#ifndef AP_MPM_NO_SET_GRACEFUL_SHUTDOWN int ap_graceful_shutdown_timeout = 0; const char * ap_mpm_set_graceful_shutdown(cmd_parms *cmd, void *dummy, @@ -893,7 +922,7 @@ const char * ap_mpm_set_graceful_shutdown(cmd_parms *cmd, void *dummy, } #endif -#ifdef AP_MPM_WANT_SET_ACCEPT_LOCK_MECH +#ifndef AP_MPM_NO_SET_ACCEPT_LOCK_MECH apr_lockmech_e ap_accept_lock_mech = APR_LOCK_DEFAULT; AP_DECLARE(const char *) ap_mpm_set_accept_lock_mech(cmd_parms *cmd, @@ -936,7 +965,7 @@ AP_DECLARE(const char *) ap_mpm_set_accept_lock_mech(cmd_parms *cmd, #endif -#ifdef AP_MPM_WANT_SIGNAL_SERVER +#ifndef AP_MPM_NO_SIGNAL_SERVER static const char *dash_k_arg; @@ -1025,7 +1054,7 @@ int ap_signal_server(int *exit_status, apr_pool_t *pconf) } if (!strcmp(dash_k_arg, "graceful-stop")) { -#ifdef AP_MPM_WANT_SET_GRACEFUL_SHUTDOWN +#ifndef AP_MPM_NO_SET_GRACEFUL_SHUTDOWN if (!running) { printf("%s\n", status); } @@ -1098,9 +1127,9 @@ void ap_mpm_rewrite_args(process_rec *process) } } -#endif /* AP_MPM_WANT_SIGNAL_SERVER */ +#endif /* AP_MPM_NO_SIGNAL_SERVER */ -#ifdef AP_MPM_WANT_SET_MAX_MEM_FREE +#ifndef AP_MPM_NO_SET_MAX_MEM_FREE apr_uint32_t ap_max_mem_free = APR_ALLOCATOR_MAX_FREE_UNLIMITED; const char *ap_mpm_set_max_mem_free(cmd_parms *cmd, void *dummy, @@ -1122,9 +1151,9 @@ const char *ap_mpm_set_max_mem_free(cmd_parms *cmd, void *dummy, return NULL; } -#endif /* AP_MPM_WANT_SET_MAX_MEM_FREE */ +#endif /* AP_MPM_NO_SET_MAX_MEM_FREE */ -#ifdef AP_MPM_WANT_SET_STACKSIZE +#ifndef AP_MPM_NO_SET_STACKSIZE apr_size_t ap_thread_stacksize = 0; /* use system default */ const char *ap_mpm_set_thread_stacksize(cmd_parms *cmd, void *dummy, @@ -1146,9 +1175,9 @@ const char *ap_mpm_set_thread_stacksize(cmd_parms *cmd, void *dummy, return NULL; } -#endif /* AP_MPM_WANT_SET_STACKSIZE */ +#endif /* AP_MPM_NO_SET_STACKSIZE */ -#ifdef AP_MPM_WANT_FATAL_SIGNAL_HANDLER +#ifndef AP_MPM_NO_FATAL_SIGNAL_HANDLER static pid_t parent_pid, my_pid; static apr_pool_t *pconf; @@ -1304,15 +1333,35 @@ apr_status_t ap_fatal_signal_setup(server_rec *s, apr_pool_t *in_pconf) return APR_SUCCESS; } -#endif /* AP_MPM_WANT_FATAL_SIGNAL_HANDLER */ +#endif /* AP_MPM_NO_FATAL_SIGNAL_HANDLER */ + +AP_DECLARE(int) ap_mpm_run(apr_pool_t *pconf, apr_pool_t *plog, server_rec *server_conf) +{ + return ap_run_mpm(pconf, plog, server_conf); +} -#ifndef AP_MPM_HAS_USER_CALLBACKS +AP_DECLARE(apr_status_t) ap_mpm_query(int query_code, int *result) +{ + return ap_run_mpm_query(query_code, result); +} -AP_DECLARE(void) ap_mpm_register_timed_callback(apr_time_t t, - ap_mpm_callback_fn_t *cbfn, - void *baton) +AP_DECLARE(pid_t) ap_mpm_get_child_pid(int childnum) { - abort(); + return ap_run_mpm_get_child_pid(childnum); } -#endif /* AP_MPM_HAS_USER_CALLBACKS */ +AP_DECLARE(apr_status_t) ap_mpm_note_child_killed(int childnum) +{ + return ap_run_mpm_note_child_killed(childnum); +} + +AP_DECLARE(apr_status_t) ap_mpm_register_timed_callback(apr_time_t t, ap_mpm_callback_fn_t *cbfn, void *baton) +{ + return ap_run_mpm_register_timed_callback(t, cbfn, baton); +} + +AP_DECLARE(const char *)ap_show_mpm(void) +{ + /* XXX hook this */ + return "(unknown)"; +} diff --git a/server/scoreboard.c b/server/scoreboard.c index 43e0513f5f..257212e56d 100644 --- a/server/scoreboard.c +++ b/server/scoreboard.c @@ -34,7 +34,6 @@ #include "http_config.h" #include "ap_mpm.h" -#include "mpm.h" #include "scoreboard.h" AP_DECLARE_DATA scoreboard *ap_scoreboard_image = NULL; @@ -436,6 +435,7 @@ AP_DECLARE(int) ap_update_child_status_from_indexes(int child_num, int old_status; worker_score *ws; process_score *ps; + int mpm_generation; if (child_num < 0) { return -1; @@ -450,7 +450,8 @@ AP_DECLARE(int) ap_update_child_status_from_indexes(int child_num, if (status == SERVER_READY && old_status == SERVER_STARTING) { ws->thread_num = child_num * thread_limit + thread_num; - ps->generation = ap_my_generation; + ap_mpm_query(AP_MPMQ_GENERATION, &mpm_generation); + ps->generation = mpm_generation; } if (ap_extended_status) { |