36#define APR_WANT_STRFUNC
42#if APR_HAVE_SYS_SOCKET_H
43#include <sys/socket.h>
45#if APR_HAVE_SYS_WAIT_H
48#ifdef HAVE_SYS_PROCESSOR_H
49#include <sys/processor.h>
53#error The Worker MPM requires APR threads, but they are unavailable.
86#ifndef DEFAULT_SERVER_LIMIT
87#define DEFAULT_SERVER_LIMIT 16
93#ifndef MAX_SERVER_LIMIT
94#define MAX_SERVER_LIMIT 20000
104#ifndef DEFAULT_THREAD_LIMIT
105#define DEFAULT_THREAD_LIMIT 64
111#ifndef MAX_THREAD_LIMIT
112#define MAX_THREAD_LIMIT 20000
167#ifndef MAX_SPAWN_RATE
168#define MAX_SPAWN_RATE (32)
182#define MPM_CHILD_PID(i) (ap_scoreboard_image->parent[i].pid)
201#define ID_FROM_CHILD_THREAD(c, t) ((c * thread_limit) + t)
231#ifdef SINGLE_LISTEN_UNSERIALIZED_ACCEPT
232#define SAFE_ACCEPT(stmt) (ap_listeners->next ? (stmt) : APR_SUCCESS)
234#define SAFE_ACCEPT(stmt) (stmt)
243#define LISTENER_SIGNAL SIGHUP
256#define WORKER_SIGNAL AP_SIG_GRACEFUL
298#ifdef HAVE_PTHREAD_KILL
307#define ST_UNGRACEFUL 2
420 " (quiescing)" :
"");
488 conn_id, sbh, bucket_alloc);
515#if defined(SIGPROCMASK_SETS_THREAD_MASK)
541 "apr_proc_mutex_%s failed "
542 "before this child process served any requests.",
547 "apr_proc_mutex_%s failed. Attempting to "
548 "shutdown process gracefully.",
func);
587 "apr_queue_info_wait failed. Attempting to "
588 " shutdown process gracefully.");
625 "apr_pollset_poll: (listen)");
697 "ap_queue_push_socket failed");
714 "apr_proc_mutex_unlock failed. Attempting to "
715 "shutdown process gracefully.");
762#ifdef HAVE_PTHREAD_KILL
773 "ap_queue_info_set_idle failed. Attempting to "
774 "shutdown process gracefully.");
813 "ap_queue_pop_socket failed");
860 "ap_thread_create: unable to create listener thread");
891 "ap_queue_create() failed");
899 "ap_queue_info_create() failed");
920 "Couldn't create pollset in thread;"
921 " check system or user limits");
937 "Couldn't create add listener to pollset;"
938 " check system or user limits");
993 "ap_thread_create: unable to create worker thread");
1010 if (
loops % 120 == 0) {
1014 "slots very quickly (%d of %d)",
1060 "listener has not stopped accepting yet (%d iter)",
iter);
1065 "the listener thread didn't exit");
1071 "apr_thread_join: unable to join listener thread");
1079#ifdef HAVE_PTHREAD_KILL
1090 "apr_thread_join: unable to join worker "
1109 "apr_thread_join: unable to join the start "
1135#if AP_HAS_THREAD_LOCAL
1140 "Couldn't initialize child main thread");
1162 "Couldn't initialize cross-process lock in child");
1180 "Couldn't initialize signal thread");
1215 "inappropriate, using default",
1229 "ap_thread_create: unable to create worker thread");
1327 if ((pid =
fork()) == -1) {
1329 "fork: Unable to fork new process");
1346#if AP_HAS_THREAD_LOCAL
1352#ifdef HAVE_BINDPROCESSOR
1361 "processor unbind failed");
1474 ||
ps->quiescing)) {
1526 "A resource shortage or other unrecoverable failure "
1527 "was encountered before any child process initialized "
1528 "successfully... httpd is exiting!");
1551 "server reached MaxRequestWorkers "
1552 "setting, consider raising the "
1553 "MaxRequestWorkers setting");
1559 "server is within MinSpareThreads of "
1560 "MaxRequestWorkers, consider raising the "
1561 "MaxRequestWorkers setting");
1569 "scoreboard is full, not at MaxRequestWorkers");
1580 "server seems busy, (you may need "
1581 "to increase StartServers, ThreadsPerChild "
1582 "or Min/MaxSpareThreads), "
1583 "spawning %d children, there are around %d idle "
1621 if (pid.
pid != -1) {
1639 "Ignoring fatal error in child of previous "
1640 "generation (pid %ld).",
1686#if APR_HAS_OTHER_CHILD
1699 "long lost child came home! (pid %ld)",
1718 "children are killed successively!");
1811 "%s configured -- resuming normal operations",
1818 "Accept mutex: %s (default: %s)",
1870 ", shutting down gracefully");
1951 "SIGHUP received. Attempting to restart");
1980 (startup ?
NULL :
s),
1981 "no listening sockets available, shutting down");
1995 (startup ?
NULL :
s),
1996 "could not duplicate listeners");
2005 (startup ?
NULL :
s),
2006 "could not open pipe-of-death");
2015 (startup ?
NULL :
s),
2016 "could not create accept mutex");
2097 "apr_proc_detach failed");
2133 "WARNING: ServerLimit of %d exceeds compile-time "
2134 "limit of %d servers, decreasing to %d.",
2138 "ServerLimit of %d exceeds compile-time limit "
2139 "of %d, decreasing to match",
2147 "WARNING: ServerLimit of %d not allowed, "
2151 "ServerLimit of %d not allowed, increasing to 1",
2166 "changing ServerLimit to %d from original value of %d "
2167 "not allowed during restart",
2175 "WARNING: ThreadLimit of %d exceeds compile-time "
2176 "limit of %d threads, decreasing to %d.",
2180 "ThreadLimit of %d exceeds compile-time limit "
2181 "of %d, decreasing to match",
2189 "WARNING: ThreadLimit of %d not allowed, "
2193 "ThreadLimit of %d not allowed, increasing to 1",
2208 "changing ThreadLimit to %d from original value of %d "
2209 "not allowed during restart",
2217 "WARNING: ThreadsPerChild of %d exceeds ThreadLimit "
2218 "of %d threads, decreasing to %d. "
2219 "To increase, please see the ThreadLimit directive.",
2223 "ThreadsPerChild of %d exceeds ThreadLimit "
2224 "of %d, decreasing to match",
2232 "WARNING: ThreadsPerChild of %d not allowed, "
2236 "ThreadsPerChild of %d not allowed, increasing to 1",
2245 "WARNING: MaxRequestWorkers of %d is less than "
2246 "ThreadsPerChild of %d, increasing to %d. "
2247 "MaxRequestWorkers must be at least as large "
2248 "as the number of threads in a single server.",
2252 "MaxRequestWorkers of %d is less than ThreadsPerChild "
2253 "of %d, increasing to match",
2266 "WARNING: MaxRequestWorkers of %d is not an integer "
2267 "multiple of ThreadsPerChild of %d, decreasing to nearest "
2268 "multiple %d, for a maximum of %d servers.",
2273 "MaxRequestWorkers of %d is not an integer multiple of "
2274 "ThreadsPerChild of %d, decreasing to nearest "
2284 "WARNING: MaxRequestWorkers of %d would require %d "
2285 "servers and would exceed ServerLimit of %d, decreasing to %d. "
2286 "To increase, please see the ServerLimit directive.",
2291 "MaxRequestWorkers of %d would require %d servers and "
2292 "exceed ServerLimit of %d, decreasing to %d",
2303 "WARNING: StartServers of %d not allowed, "
2307 "StartServers of %d not allowed, increasing to 1",
2316 "WARNING: MinSpareThreads of %d not allowed, "
2317 "increasing to 1 to avoid almost certain server failure. "
2321 "MinSpareThreads of %d not allowed, increasing to 1",
2340 static const char *
const aszSucc[] = {
"core.c",
NULL};
2399 "MaxClients is deprecated, use MaxRequestWorkers "
2443 "Number of child processes launched at server startup"),
2445 "Minimum number of idle threads, to handle request spikes"),
2447 "Maximum number of idle threads"),
2449 "Maximum number of threads alive at the same time"),
2451 "Deprecated name of MaxRequestWorkers"),
2453 "Number of threads each child creates"),
2455 "Maximum number of child processes for this run of Apache"),
2457 "Maximum number of worker threads per child process for this run of Apache - Upper limit for ThreadsPerChild"),
Symbol export macros and hook functions.
Apache Listeners Library.
Apache Multi-Processing Module library.
APR Portability Routines.
APR Process Locking Routines.
APR Thread Mutex Routines.
APR Thread and Process Library.
APR Standard Headers Support.
void ap_process_connection(conn_rec *c, void *csd)
void ap_lingering_close(conn_rec *c)
conn_rec * ap_run_create_connection(apr_pool_t *p, server_rec *server, apr_socket_t *csd, long conn_id, void *sbh, apr_bucket_alloc_t *alloc)
#define AP_INIT_TAKE1(directive, func, mconfig, where, help)
void ap_run_child_init(apr_pool_t *pchild, server_rec *s)
#define AP_DECLARE_MODULE(foo)
void ap_hook_open_logs(ap_HOOK_open_logs_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
void ap_hook_check_config(ap_HOOK_check_config_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
void ap_hook_pre_config(ap_HOOK_pre_config_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
void * ap_retained_data_create(const char *key, apr_size_t size)
const char server_rec server_rec ** ps
void * ap_retained_data_get(const char *key)
const char * ap_get_server_built(void)
const char * ap_get_server_description(void)
#define APEXIT_CHILDFATAL
int ap_exists_config_define(const char *name)
void ap_close_listeners(void)
void ap_close_listeners_ex(ap_listen_rec *listeners)
void ap_listen_pre_config(void)
apr_status_t ap_duplicate_listeners(apr_pool_t *p, server_rec *s, ap_listen_rec ***buckets, int *num_buckets)
int ap_setup_listeners(server_rec *s)
void ap_remove_pid(apr_pool_t *p, const char *fname)
void ap_log_mpm_common(server_rec *s)
void ap_log_pid(apr_pool_t *p, const char *fname)
void ap_log_command_line(apr_pool_t *p, server_rec *s)
server_rec * ap_server_conf
void ap_run_child_status(server_rec *s, pid_t pid, ap_generation_t gen, int slot, mpm_child_status state)
void ap_hook_mpm(ap_HOOK_mpm_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
apr_status_t ap_proc_mutex_create(apr_proc_mutex_t **mutex, const char **name, const char *type, const char *instance_id, server_rec *server, apr_pool_t *pool, apr_int32_t options)
apr_status_t ap_mutex_register(apr_pool_t *pconf, const char *type, const char *default_dir, apr_lockmech_e default_mech, apr_int32_t options)
#define DEFAULT_MAX_FREE_DAEMON
#define DEFAULT_MIN_FREE_DAEMON
#define DEFAULT_START_DAEMON
#define DEFAULT_THREADS_PER_CHILD
#define AP_SIG_GRACEFUL_STRING
void ap_wait_or_timeout(apr_exit_why_e *status, int *exitcode, apr_proc_t *ret, apr_pool_t *p, server_rec *s)
const char * ap_pid_fname
apr_status_t ap_mpm_safe_kill(pid_t pid, int sig)
#define AP_GRACEFUL_SHUTDOWN_TIMEOUT_COMMAND
#define AP_ACCEPT_MUTEX_TYPE
int ap_max_requests_per_child
#define AP_SIG_GRACEFUL_STOP_STRING
int ap_unregister_extra_mpm_process(pid_t pid, ap_generation_t *old_gen)
void ap_run_child_stopping(apr_pool_t *pchild, int graceful)
void ap_hook_mpm_get_name(ap_HOOK_mpm_get_name_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
void ap_relieve_child_processes(ap_reclaim_callback_fn_t *mpm_callback)
int ap_graceful_shutdown_timeout
int ap_process_child_status(apr_proc_t *pid, apr_exit_why_e why, int status)
void ap_reclaim_child_processes(int terminate, ap_reclaim_callback_fn_t *mpm_callback)
apr_status_t ap_fatal_signal_child_setup(server_rec *s)
void ap_hook_mpm_query(ap_HOOK_mpm_query_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
void ap_mpm_podx_killpg(ap_pod_t *pod, int num, ap_podx_restart_t graceful)
apr_size_t ap_thread_stacksize
void ap_register_extra_mpm_process(pid_t pid, ap_generation_t gen)
apr_uint32_t ap_max_mem_free
apr_status_t ap_fatal_signal_setup(server_rec *s, apr_pool_t *in_pconf)
int ap_mpm_podx_check(ap_pod_t *pod)
apr_status_t ap_mpm_podx_signal(ap_pod_t *pod, ap_podx_restart_t graceful)
apr_status_t ap_mpm_podx_close(ap_pod_t *pod)
int ap_run_drop_privileges(apr_pool_t *pchild, server_rec *s)
apr_status_t ap_mpm_podx_open(apr_pool_t *p, ap_pod_t **pod)
#define APR_OC_REASON_DEATH
#define APR_STATUS_IS_EINTR(s)
#define APR_STATUS_IS_EOF(s)
apr_dbd_transaction_t int mode
const char *const const char *const * aszSucc
#define APR_HOOK_REALLY_FIRST
#define HTTP_INTERNAL_SERVER_ERROR
#define MPM20_MODULE_STUFF
#define AP_DEBUG_ASSERT(exp)
void * ap_calloc(size_t nelem, size_t size) __attribute__((malloc))
void * ap_malloc(size_t size) __attribute__((malloc))
const char * ap_check_cmd_context(cmd_parms *cmd, unsigned forbidden)
apr_array_header_t ** result
int strcasecmp(const char *a, const char *b)
apr_interval_time_t apr_pollcb_cb_t func
apr_abortfunc_t apr_allocator_t * allocator
const char apr_status_t(*) apr_pool_t *poo __attribute__)((nonnull(2, 4)))
#define apr_pool_create(newpool, parent)
#define apr_pcalloc(p, size)
void apr_skiplistnode ** iter
apr_int32_t apr_int32_t apr_int32_t err
int apr_exit_why_e * exitwhy
#define APR_PROC_CHECK_SIGNALED(x)
#define APR_PROC_DETACH_DAEMONIZE
#define APR_PROC_DETACH_FOREGROUND
#define apr_time_from_msec(msec)
#define apr_time_from_sec(sec)
#define APR_POLLSET_NOCOPY
#define APR_POLLSET_WAKEABLE
#define AP_MPMQ_IS_FORKED
#define AP_MPMQ_MPM_STATE
#define AP_MPMQ_MAX_DAEMON_USED
#define AP_MPMQ_MAX_SPARE_DAEMONS
#define AP_MPMQ_MIN_SPARE_THREADS
#define AP_MPMQ_HARD_LIMIT_THREADS
#define AP_MPMQ_IS_THREADED
#define AP_MPMQ_MAX_THREADS
#define AP_MPMQ_MAX_REQUESTS_DAEMON
#define AP_MPMQ_MAX_SPARE_THREADS
#define AP_MPMQ_GENERATION
#define AP_MPMQ_MAX_DAEMONS
#define AP_MPMQ_HARD_LIMIT_DAEMONS
#define AP_MPMQ_MIN_SPARE_DAEMONS
Apache connection library.
static unsigned long num_buckets
Multi-Processing Modules functions.
static int idle_spawn_rate
apr_status_t apr_proc_detach(int daemonize)
apr_status_t apr_thread_exit(apr_thread_t *thd, apr_status_t retval)
apr_os_thread_t apr_os_thread_current()
apr_status_t apr_thread_join(apr_status_t *retval, apr_thread_t *thd)
apr_status_t apr_threadattr_detach_set(apr_threadattr_t *attr, apr_int32_t on)
apr_status_t apr_threadattr_create(apr_threadattr_t **new, apr_pool_t *pool)
Apache scoreboard library.
void ap_create_sb_handle(ap_sb_handle_t **new_sbh, apr_pool_t *p, int child_num, int thread_num)
int ap_run_pre_mpm(apr_pool_t *p, ap_scoreboard_e sb_type)
scoreboard * ap_scoreboard_image
apr_status_t ap_reopen_scoreboard(apr_pool_t *p, apr_shm_t **shm, int detached)
int ap_update_child_status_from_indexes(int child_num, int thread_num, int status, request_rec *r)
int ap_find_child_by_pid(apr_proc_t *pid)
process_score * ap_get_scoreboard_process(int x)
Apache's listeners record.
Structure to store things which are per connection.
ap_generation_t running_generation
ap_generation_t generation
A structure to store information for each virtual server.
apr_threadattr_t * threadattr
ap_listen_rec * listeners
ap_unixd_mpm_retained_data * mpm
int hold_off_on_exponential_spawning
int near_maxclients_reported
ap_generation_t generation
apr_status_t apr_socket_close(apr_socket_t *thesocket)
Apache Mutex support library.
static void perform_idle_server_maintenance(int child_bucket)
#define DEFAULT_SERVER_LIMIT
static void *APR_THREAD_FUNC listener_thread(apr_thread_t *thd, void *dummy)
static int had_healthy_child
static void join_start_thread(apr_thread_t *start_thread_id)
static void startup_children(int number_to_start)
static apr_pool_t * pruntime
static apr_pollset_t * worker_pollset
static void process_socket(apr_thread_t *thd, apr_pool_t *p, apr_socket_t *sock, int my_child_num, int my_thread_num, apr_bucket_alloc_t *bucket_alloc)
static void *APR_THREAD_FUNC worker_thread(apr_thread_t *thd, void *dummy)
static int start_thread_may_exit
static worker_retained_data * retained
static apr_socket_t ** worker_sockets
static void unblock_signal(int sig)
static int worker_open_logs(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
static apr_pool_t * pchild
static void server_main_loop(int remaining_children_to_start)
static worker_child_bucket * my_bucket
static int max_spare_threads
static void just_die(int sig)
static void clean_child_exit(int code) __attribute__((noreturn))
static void accept_mutex_error(const char *func, apr_status_t rv, int process_slot)
static int min_spare_threads
static int worker_query(int query_code, int *result, apr_status_t *rv)
static void worker_note_child_started(int slot, pid_t pid)
static apr_pool_t * pconf
static void join_workers(apr_thread_t *listener, apr_thread_t **threads, int mode)
static void child_main(int child_num_arg, int child_bucket)
static void *APR_THREAD_FUNC start_threads(apr_thread_t *thd, void *dummy)
static void signal_threads(int mode)
static void worker_hooks(apr_pool_t *p)
static void worker_note_child_killed(int childnum, pid_t pid, ap_generation_t gen)
#define DEFAULT_THREAD_LIMIT
static int listener_may_exit
static void dummy_signal_handler(int sig)
static const char * set_max_workers(cmd_parms *cmd, void *dummy, const char *arg)
static const char * set_server_limit(cmd_parms *cmd, void *dummy, const char *arg)
static const char * set_min_spare_threads(cmd_parms *cmd, void *dummy, const char *arg)
static const char * set_thread_limit(cmd_parms *cmd, void *dummy, const char *arg)
static int worker_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
static int ap_daemons_limit
static fd_queue_t * worker_queue
static const char * set_max_spare_threads(cmd_parms *cmd, void *dummy, const char *arg)
static const char * worker_get_name(void)
static void worker_note_child_lost_slot(int slot, pid_t newpid)
static int num_listensocks
static int listener_is_wakeable
static fd_queue_info_t * worker_queue_info
static apr_os_thread_t * listener_os_thread
static const command_rec worker_cmds[]
static int make_child(server_rec *s, int slot, int bucket)
static const char * set_threads_per_child(cmd_parms *cmd, void *dummy, const char *arg)
static const char * set_daemons_to_start(cmd_parms *cmd, void *dummy, const char *arg)
#define ID_FROM_CHILD_THREAD(c, t)
static void setup_threads_runtime(void)
static int check_signal(int signum)
static void close_worker_sockets(void)
static int worker_check_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
static volatile int dying
static void create_listener_thread(thread_starter *ts)
static worker_child_bucket * all_buckets
static int requests_this_child
static int ap_daemons_to_start
static int workers_may_exit
static int resource_shortage
static int threads_per_child
static void wakeup_listener(void)
#define SAFE_ACCEPT(stmt)
static void check_infinite_requests(void)
static int terminate_mode
static int worker_pre_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp)