1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 * This MPM tries to fix the 'keep alive problem' in HTTP.
20 * After a client completes the first request, the client can keep the
21 * connection open to send more requests with the same socket. This can save
22 * significant overhead in creating TCP connections. However, the major
23 * disadvantage is that Apache traditionally keeps an entire child
24 * process/thread waiting for data from the client. To solve this problem,
25 * this MPM has a dedicated thread for handling both the Listening sockets,
26 * and all sockets that are in a Keep Alive status.
28 * The MPM assumes the underlying apr_pollset implementation is somewhat
29 * threadsafe. This currently is only compatible with KQueue and EPoll. This
30 * enables the MPM to avoid extra high level locking or having to wake up the
31 * listener thread when a keep-alive socket needs to be sent to it.
33 * This MPM does not perform well on older platforms that do not have very good
34 * threading, like Linux with a 2.4 kernel, but this does not matter, since we
35 * require EPoll or KQueue.
37 * For FreeBSD, use 5.3. It is possible to run this MPM on FreeBSD 5.2.1, if
38 * you use libkse (see `man libmap.conf`).
40 * For NetBSD, use at least 2.0.
42 * For Linux, you should use a 2.6 kernel, and make sure your glibc has epoll
43 * support compiled in.
48 #include "apr_portable.h"
49 #include "apr_strings.h"
50 #include "apr_file_io.h"
51 #include "apr_thread_proc.h"
52 #include "apr_signal.h"
53 #include "apr_thread_mutex.h"
56 #include "apr_queue.h"
57 #include "apr_atomic.h"
58 #define APR_WANT_STRFUNC
60 #include "apr_version.h"
67 #if APR_HAVE_SYS_SOCKET_H
68 #include <sys/socket.h>
70 #if APR_HAVE_SYS_WAIT_H
73 #ifdef HAVE_SYS_PROCESSOR_H
74 #include <sys/processor.h> /* for bindprocessor() */
78 #error The Event MPM requires APR threads, but they are unavailable.
81 #include "ap_config.h"
83 #include "http_main.h"
85 #include "http_config.h" /* for read_config */
86 #include "http_core.h" /* for get_remote_host */
87 #include "http_connection.h"
88 #include "http_protocol.h"
90 #include "mpm_common.h"
91 #include "ap_listen.h"
92 #include "scoreboard.h"
94 #include "mpm_default.h"
95 #include "http_vhost.h"
97 #include "apr_skiplist.h"
100 #include <limits.h> /* for INT_MAX */
103 /* Limit on the total --- clients will be locked out if more servers than
104 * this are needed. It is intended solely to keep the server from crashing
105 * when things get out of hand.
107 * We keep a hard maximum number of servers, for two reasons --- first off,
108 * in case something goes seriously wrong, we want to stop the fork bomb
109 * short of actually crashing the machine we're running on by filling some
110 * kernel table. Secondly, it keeps the size of the scoreboard file small
111 * enough that we can read the whole thing without worrying too much about
114 #ifndef DEFAULT_SERVER_LIMIT
115 #define DEFAULT_SERVER_LIMIT 16
118 /* Admin can't tune ServerLimit beyond MAX_SERVER_LIMIT. We want
119 * some sort of compile-time limit to help catch typos.
121 #ifndef MAX_SERVER_LIMIT
122 #define MAX_SERVER_LIMIT 20000
125 /* Limit on the threads per process. Clients will be locked out if more than
128 * We keep this for one reason it keeps the size of the scoreboard file small
129 * enough that we can read the whole thing without worrying too much about
132 #ifndef DEFAULT_THREAD_LIMIT
133 #define DEFAULT_THREAD_LIMIT 64
136 /* Admin can't tune ThreadLimit beyond MAX_THREAD_LIMIT. We want
137 * some sort of compile-time limit to help catch typos.
139 #ifndef MAX_THREAD_LIMIT
140 #define MAX_THREAD_LIMIT 100000
143 #define MPM_CHILD_PID(i) (ap_scoreboard_image->parent[i].pid)
145 #if !APR_VERSION_AT_LEAST(1,4,0)
146 #define apr_time_from_msec(x) (x * 1000)
149 #ifndef MAX_SECS_TO_LINGER
150 #define MAX_SECS_TO_LINGER 30
152 #define SECONDS_TO_LINGER 2
155 * Actual definitions of config globals
158 #ifndef DEFAULT_WORKER_FACTOR
159 #define DEFAULT_WORKER_FACTOR 2
161 #define WORKER_FACTOR_SCALE 16 /* scale factor to allow fractional values */
162 static unsigned int worker_factor = DEFAULT_WORKER_FACTOR * WORKER_FACTOR_SCALE;
164 static int threads_per_child = 0; /* Worker threads per child */
165 static int ap_daemons_to_start = 0;
166 static int min_spare_threads = 0;
167 static int max_spare_threads = 0;
168 static int ap_daemons_limit = 0;
169 static int max_workers = 0;
170 static int server_limit = 0;
171 static int thread_limit = 0;
172 static int had_healthy_child = 0;
173 static int dying = 0;
174 static int workers_may_exit = 0;
175 static int start_thread_may_exit = 0;
176 static int listener_may_exit = 0;
177 static int num_listensocks = 0;
178 static apr_int32_t conns_this_child; /* MaxConnectionsPerChild, only access
179 in listener thread */
180 static apr_uint32_t connection_count = 0; /* Number of open connections */
181 static apr_uint32_t lingering_count = 0; /* Number of connections in lingering close */
182 static apr_uint32_t suspended_count = 0; /* Number of suspended connections */
183 static apr_uint32_t clogged_count = 0; /* Number of threads processing ssl conns */
184 static int resource_shortage = 0;
185 static fd_queue_t *worker_queue;
186 static fd_queue_info_t *worker_queue_info;
187 static int mpm_state = AP_MPMQ_STARTING;
189 static apr_thread_mutex_t *timeout_mutex;
191 module AP_MODULE_DECLARE_DATA mpm_event_module;
193 /* forward declare */
194 struct event_srv_cfg_s;
195 typedef struct event_srv_cfg_s event_srv_cfg;
197 struct event_conn_state_t {
198 /** APR_RING of expiration timeouts */
199 APR_RING_ENTRY(event_conn_state_t) timeout_list;
200 /** the time when the entry was queued */
201 apr_time_t queue_timestamp;
202 /** connection record this struct refers to */
204 /** request record (if any) this struct refers to */
206 /** server config this struct refers to */
208 /** is the current conn_rec suspended? (disassociated with
209 * a particular MPM thread; for suspend_/resume_connection
213 /** memory pool to allocate from */
215 /** bucket allocator */
216 apr_bucket_alloc_t *bucket_alloc;
217 /** poll file descriptor information */
219 /** public parts of the connection state */
222 APR_RING_HEAD(timeout_head_t, event_conn_state_t);
224 struct timeout_queue {
225 struct timeout_head_t head;
227 apr_interval_time_t timeout;
228 struct timeout_queue *next;
231 * Several timeout queues that use different timeouts, so that we always can
232 * simply append to the end.
233 * write_completion_q uses vhost's TimeOut
234 * keepalive_q uses vhost's KeepAliveTimeOut
235 * linger_q uses MAX_SECS_TO_LINGER
236 * short_linger_q uses SECONDS_TO_LINGER
238 static struct timeout_queue *write_completion_q,
243 static apr_pollfd_t *listener_pollfd;
246 * Macros for accessing struct timeout_queue.
247 * For TO_QUEUE_APPEND and TO_QUEUE_REMOVE, timeout_mutex must be held.
249 #define TO_QUEUE_APPEND(q, el) \
251 APR_RING_INSERT_TAIL(&(q)->head, el, event_conn_state_t, \
257 #define TO_QUEUE_REMOVE(q, el) \
259 APR_RING_REMOVE(el, timeout_list); \
264 #define TO_QUEUE_INIT(q, p, t, v) \
266 struct timeout_queue *b = (v); \
267 (q) = apr_palloc((p), sizeof *(q)); \
268 APR_RING_INIT(&(q)->head, event_conn_state_t, timeout_list); \
269 (q)->total = (b) ? (b)->total : apr_pcalloc((p), sizeof *(q)->total); \
271 (q)->timeout = (t); \
275 #define TO_QUEUE_ELEM_INIT(el) APR_RING_ELEM_INIT(el, timeout_list)
278 * The pollset for sockets that are in any of the timeout queues. Currently
279 * we use the timeout_mutex to make sure that connections are added/removed
280 * atomically to/from both event_pollset and a timeout queue. Otherwise
281 * some confusion can happen under high load if timeout queues and pollset
283 * XXX: It should be possible to make the lock unnecessary in many or even all
286 static apr_pollset_t *event_pollset;
288 /* The structure used to pass unique initialization info to each thread */
296 /* Structure used to pass information to the thread responsible for
297 * creating the rest of the threads.
301 apr_thread_t **threads;
302 apr_thread_t *listener;
304 apr_threadattr_t *threadattr;
317 } listener_poll_type;
319 /* data retained by event across load/unload of the module
320 * allocated on first call to pre-config hook; located on
321 * subsequent calls to pre-config hook
323 typedef struct event_retained_data {
324 int first_server_limit;
325 int first_thread_limit;
327 int sick_child_detected;
328 ap_generation_t my_generation;
329 int volatile is_graceful; /* set from signal handler */
330 int maxclients_reported;
332 * The max child slot ever assigned, preserved across restarts. Necessary
333 * to deal with MaxRequestWorkers changes across AP_SIG_GRACEFUL restarts.
334 * We use this value to optimize routines that have to scan the entire
337 int max_daemons_limit;
339 * idle_spawn_rate is the number of children that will be spawned on the
340 * next maintenance cycle if there aren't enough idle servers. It is
341 * maintained per listeners bucket, doubled up to MAX_SPAWN_RATE, and
342 * reset only when a cycle goes by without the need to spawn.
344 int *idle_spawn_rate;
345 #ifndef MAX_SPAWN_RATE
346 #define MAX_SPAWN_RATE (32)
348 int hold_off_on_exponential_spawning;
350 * Current number of listeners buckets and maximum reached accross
351 * restarts (to size retained data according to dynamic num_buckets,
352 * eg. idle_spawn_rate).
354 int num_buckets, max_buckets;
355 } event_retained_data;
356 static event_retained_data *retained;
358 typedef struct event_child_bucket {
360 ap_listen_rec *listeners;
361 } event_child_bucket;
362 static event_child_bucket *all_buckets, /* All listeners buckets */
363 *my_bucket; /* Current child bucket */
365 struct event_srv_cfg_s {
366 struct timeout_queue *wc_q,
370 #define ID_FROM_CHILD_THREAD(c, t) ((c * thread_limit) + t)
372 /* The event MPM respects a couple of runtime flags that can aid
373 * in debugging. Setting the -DNO_DETACH flag will prevent the root process
374 * from detaching from its controlling terminal. Additionally, setting
375 * the -DONE_PROCESS flag (which implies -DNO_DETACH) will get you the
376 * child_main loop running in the process which originally started up.
377 * This gives you a pretty nice debugging environment. (You'll get a SIGHUP
378 * early in standalone_main; just continue through. This is the server
379 * trying to kill off any child processes which it might have lying
380 * around --- Apache doesn't keep track of their pids, it just sends
381 * SIGHUP to the process group, ignoring it in the root process.
382 * Continue through and you'll be fine.).
385 static int one_process = 0;
388 int raise_sigstop_flags;
391 static apr_pool_t *pconf; /* Pool for config stuff */
392 static apr_pool_t *pchild; /* Pool for httpd child stuff */
394 static pid_t ap_my_pid; /* Linux getpid() doesn't work except in main
395 thread. Use this instead */
396 static pid_t parent_pid;
397 static apr_os_thread_t *listener_os_thread;
399 /* The LISTENER_SIGNAL signal will be sent from the main thread to the
400 * listener thread to wake it up for graceful termination (what a child
401 * process from an old generation does when the admin does "apachectl
402 * graceful"). This signal will be blocked in all threads of a child
403 * process except for the listener thread.
405 #define LISTENER_SIGNAL SIGHUP
407 /* An array of socket descriptors in use by each thread used to
408 * perform a non-graceful (forced) shutdown of the server.
410 static apr_socket_t **worker_sockets;
412 static void disable_listensocks(int process_slot)
415 for (i = 0; i < num_listensocks; i++) {
416 apr_pollset_remove(event_pollset, &listener_pollfd[i]);
418 ap_scoreboard_image->parent[process_slot].not_accepting = 1;
421 static void enable_listensocks(int process_slot)
424 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(00457)
425 "Accepting new connections again: "
426 "%u active conns (%u lingering/%u clogged/%u suspended), "
428 apr_atomic_read32(&connection_count),
429 apr_atomic_read32(&lingering_count),
430 apr_atomic_read32(&clogged_count),
431 apr_atomic_read32(&suspended_count),
432 ap_queue_info_get_idlers(worker_queue_info));
433 for (i = 0; i < num_listensocks; i++)
434 apr_pollset_add(event_pollset, &listener_pollfd[i]);
436 * XXX: This is not yet optimal. If many workers suddenly become available,
437 * XXX: the parent may kill some processes off too soon.
439 ap_scoreboard_image->parent[process_slot].not_accepting = 0;
442 static void close_worker_sockets(void)
445 for (i = 0; i < threads_per_child; i++) {
446 if (worker_sockets[i]) {
447 apr_socket_close(worker_sockets[i]);
448 worker_sockets[i] = NULL;
453 static void wakeup_listener(void)
455 listener_may_exit = 1;
456 if (!listener_os_thread) {
457 /* XXX there is an obscure path that this doesn't handle perfectly:
458 * right after listener thread is created but before
459 * listener_os_thread is set, the first worker thread hits an
460 * error and starts graceful termination
465 /* unblock the listener if it's waiting for a worker */
466 ap_queue_info_term(worker_queue_info);
469 * we should just be able to "kill(ap_my_pid, LISTENER_SIGNAL)" on all
470 * platforms and wake up the listener thread since it is the only thread
471 * with SIGHUP unblocked, but that doesn't work on Linux
473 #ifdef HAVE_PTHREAD_KILL
474 pthread_kill(*listener_os_thread, LISTENER_SIGNAL);
476 kill(ap_my_pid, LISTENER_SIGNAL);
481 #define ST_GRACEFUL 1
482 #define ST_UNGRACEFUL 2
484 static int terminate_mode = ST_INIT;
486 static void signal_threads(int mode)
488 if (terminate_mode == mode) {
491 terminate_mode = mode;
492 mpm_state = AP_MPMQ_STOPPING;
494 /* in case we weren't called from the listener thread, wake up the
499 /* for ungraceful termination, let the workers exit now;
500 * for graceful termination, the listener thread will notify the
501 * workers to exit once it has stopped accepting new connections
503 if (mode == ST_UNGRACEFUL) {
504 workers_may_exit = 1;
505 ap_queue_interrupt_all(worker_queue);
506 close_worker_sockets(); /* forcefully kill all current connections */
510 static int event_query(int query_code, int *result, apr_status_t *rv)
513 switch (query_code) {
514 case AP_MPMQ_MAX_DAEMON_USED:
515 *result = retained->max_daemons_limit;
517 case AP_MPMQ_IS_THREADED:
518 *result = AP_MPMQ_STATIC;
520 case AP_MPMQ_IS_FORKED:
521 *result = AP_MPMQ_DYNAMIC;
523 case AP_MPMQ_IS_ASYNC:
526 case AP_MPMQ_HARD_LIMIT_DAEMONS:
527 *result = server_limit;
529 case AP_MPMQ_HARD_LIMIT_THREADS:
530 *result = thread_limit;
532 case AP_MPMQ_MAX_THREADS:
533 *result = threads_per_child;
535 case AP_MPMQ_MIN_SPARE_DAEMONS:
538 case AP_MPMQ_MIN_SPARE_THREADS:
539 *result = min_spare_threads;
541 case AP_MPMQ_MAX_SPARE_DAEMONS:
544 case AP_MPMQ_MAX_SPARE_THREADS:
545 *result = max_spare_threads;
547 case AP_MPMQ_MAX_REQUESTS_DAEMON:
548 *result = ap_max_requests_per_child;
550 case AP_MPMQ_MAX_DAEMONS:
551 *result = ap_daemons_limit;
553 case AP_MPMQ_MPM_STATE:
556 case AP_MPMQ_GENERATION:
557 *result = retained->my_generation;
566 static void event_note_child_killed(int childnum, pid_t pid, ap_generation_t gen)
568 if (childnum != -1) { /* child had a scoreboard slot? */
569 ap_run_child_status(ap_server_conf,
570 ap_scoreboard_image->parent[childnum].pid,
571 ap_scoreboard_image->parent[childnum].generation,
572 childnum, MPM_CHILD_EXITED);
573 ap_scoreboard_image->parent[childnum].pid = 0;
576 ap_run_child_status(ap_server_conf, pid, gen, -1, MPM_CHILD_EXITED);
580 static void event_note_child_started(int slot, pid_t pid)
582 ap_scoreboard_image->parent[slot].pid = pid;
583 ap_run_child_status(ap_server_conf,
584 ap_scoreboard_image->parent[slot].pid,
585 retained->my_generation, slot, MPM_CHILD_STARTED);
588 static void event_note_child_lost_slot(int slot, pid_t newpid)
590 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(00458)
591 "pid %" APR_PID_T_FMT " taking over scoreboard slot from "
592 "%" APR_PID_T_FMT "%s",
594 ap_scoreboard_image->parent[slot].pid,
595 ap_scoreboard_image->parent[slot].quiescing ?
596 " (quiescing)" : "");
597 ap_run_child_status(ap_server_conf,
598 ap_scoreboard_image->parent[slot].pid,
599 ap_scoreboard_image->parent[slot].generation,
600 slot, MPM_CHILD_LOST_SLOT);
601 /* Don't forget about this exiting child process, or we
602 * won't be able to kill it if it doesn't exit by the
603 * time the server is shut down.
605 ap_register_extra_mpm_process(ap_scoreboard_image->parent[slot].pid,
606 ap_scoreboard_image->parent[slot].generation);
609 static const char *event_get_name(void)
614 /* a clean exit from a child with proper cleanup */
615 static void clean_child_exit(int code) __attribute__ ((noreturn));
616 static void clean_child_exit(int code)
618 mpm_state = AP_MPMQ_STOPPING;
620 apr_pool_destroy(pchild);
624 event_note_child_killed(/* slot */ 0, 0, 0);
630 static void just_die(int sig)
635 /*****************************************************************
636 * Connection structures and accounting...
639 static int child_fatal;
641 /* volatile because they're updated from a signal handler */
642 static int volatile shutdown_pending;
643 static int volatile restart_pending;
645 static apr_status_t decrement_connection_count(void *cs_)
647 event_conn_state_t *cs = cs_;
648 switch (cs->pub.state) {
649 case CONN_STATE_LINGER_NORMAL:
650 case CONN_STATE_LINGER_SHORT:
651 apr_atomic_dec32(&lingering_count);
653 case CONN_STATE_SUSPENDED:
654 apr_atomic_dec32(&suspended_count);
659 apr_atomic_dec32(&connection_count);
664 * ap_start_shutdown() and ap_start_restart(), below, are a first stab at
665 * functions to initiate shutdown or restart without relying on signals.
666 * Previously this was initiated in sig_term() and restart() signal handlers,
667 * but we want to be able to start a shutdown/restart from other sources --
668 * e.g. on Win32, from the service manager. Now the service manager can
669 * call ap_start_shutdown() or ap_start_restart() as appropriate. Note that
670 * these functions can also be called by the child processes, since global
671 * variables are no longer used to pass on the required action to the parent.
673 * These should only be called from the parent process itself, since the
674 * parent process will use the shutdown_pending and restart_pending variables
675 * to determine whether to shutdown or restart. The child process should
676 * call signal_parent() directly to tell the parent to die -- this will
677 * cause neither of those variable to be set, which the parent will
678 * assume means something serious is wrong (which it will be, for the
679 * child to force an exit) and so do an exit anyway.
682 static void ap_start_shutdown(int graceful)
684 mpm_state = AP_MPMQ_STOPPING;
685 if (shutdown_pending == 1) {
686 /* Um, is this _probably_ not an error, if the user has
687 * tried to do a shutdown twice quickly, so we won't
688 * worry about reporting it.
692 shutdown_pending = 1;
693 retained->is_graceful = graceful;
696 /* do a graceful restart if graceful == 1 */
697 static void ap_start_restart(int graceful)
699 mpm_state = AP_MPMQ_STOPPING;
700 if (restart_pending == 1) {
701 /* Probably not an error - don't bother reporting it */
705 retained->is_graceful = graceful;
708 static void sig_term(int sig)
710 ap_start_shutdown(sig == AP_SIG_GRACEFUL_STOP);
713 static void restart(int sig)
715 ap_start_restart(sig == AP_SIG_GRACEFUL);
718 static void set_signals(void)
720 #ifndef NO_USE_SIGACTION
725 ap_fatal_signal_setup(ap_server_conf, pconf);
728 #ifndef NO_USE_SIGACTION
729 sigemptyset(&sa.sa_mask);
732 sa.sa_handler = sig_term;
733 if (sigaction(SIGTERM, &sa, NULL) < 0)
734 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00459)
735 "sigaction(SIGTERM)");
736 #ifdef AP_SIG_GRACEFUL_STOP
737 if (sigaction(AP_SIG_GRACEFUL_STOP, &sa, NULL) < 0)
738 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00460)
739 "sigaction(" AP_SIG_GRACEFUL_STOP_STRING ")");
742 if (sigaction(SIGINT, &sa, NULL) < 0)
743 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00461)
744 "sigaction(SIGINT)");
747 sa.sa_handler = SIG_DFL;
748 if (sigaction(SIGXCPU, &sa, NULL) < 0)
749 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00462)
750 "sigaction(SIGXCPU)");
753 /* For systems following the LFS standard, ignoring SIGXFSZ allows
754 * a write() beyond the 2GB limit to fail gracefully with E2BIG
755 * rather than terminate the process. */
756 sa.sa_handler = SIG_IGN;
757 if (sigaction(SIGXFSZ, &sa, NULL) < 0)
758 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00463)
759 "sigaction(SIGXFSZ)");
762 sa.sa_handler = SIG_IGN;
763 if (sigaction(SIGPIPE, &sa, NULL) < 0)
764 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00464)
765 "sigaction(SIGPIPE)");
768 /* we want to ignore HUPs and AP_SIG_GRACEFUL while we're busy
770 sigaddset(&sa.sa_mask, SIGHUP);
771 sigaddset(&sa.sa_mask, AP_SIG_GRACEFUL);
772 sa.sa_handler = restart;
773 if (sigaction(SIGHUP, &sa, NULL) < 0)
774 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00465)
775 "sigaction(SIGHUP)");
776 if (sigaction(AP_SIG_GRACEFUL, &sa, NULL) < 0)
777 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00466)
778 "sigaction(" AP_SIG_GRACEFUL_STRING ")");
782 apr_signal(SIGXCPU, SIG_DFL);
785 apr_signal(SIGXFSZ, SIG_IGN);
789 apr_signal(SIGTERM, sig_term);
791 apr_signal(SIGHUP, restart);
793 #ifdef AP_SIG_GRACEFUL
794 apr_signal(AP_SIG_GRACEFUL, restart);
795 #endif /* AP_SIG_GRACEFUL */
796 #ifdef AP_SIG_GRACEFUL_STOP
797 apr_signal(AP_SIG_GRACEFUL_STOP, sig_term);
798 #endif /* AP_SIG_GRACEFUL_STOP */
800 apr_signal(SIGPIPE, SIG_IGN);
806 static void notify_suspend(event_conn_state_t *cs)
808 ap_run_suspend_connection(cs->c, cs->r);
813 static void notify_resume(event_conn_state_t *cs, ap_sb_handle_t *sbh)
817 ap_run_resume_connection(cs->c, cs->r);
820 static int start_lingering_close_common(event_conn_state_t *cs, int in_worker)
823 struct timeout_queue *q;
824 apr_socket_t *csd = cs->pfd.desc.s;
827 rv = apr_socket_timeout_set(csd, 0);
828 AP_DEBUG_ASSERT(rv == APR_SUCCESS);
831 apr_socket_timeout_set(csd, 0);
833 cs->queue_timestamp = apr_time_now();
835 * If some module requested a shortened waiting period, only wait for
836 * 2s (SECONDS_TO_LINGER). This is useful for mitigating certain
839 if (apr_table_get(cs->c->notes, "short-lingering-close")) {
841 cs->pub.state = CONN_STATE_LINGER_SHORT;
845 cs->pub.state = CONN_STATE_LINGER_NORMAL;
847 apr_atomic_inc32(&lingering_count);
854 apr_thread_mutex_lock(timeout_mutex);
855 TO_QUEUE_APPEND(q, cs);
856 cs->pfd.reqevents = (
857 cs->pub.sense == CONN_SENSE_WANT_WRITE ? APR_POLLOUT :
858 APR_POLLIN) | APR_POLLHUP | APR_POLLERR;
859 cs->pub.sense = CONN_SENSE_DEFAULT;
860 rv = apr_pollset_add(event_pollset, &cs->pfd);
861 apr_thread_mutex_unlock(timeout_mutex);
862 if (rv != APR_SUCCESS && !APR_STATUS_IS_EEXIST(rv)) {
863 ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf, APLOGNO(03092)
864 "start_lingering_close: apr_pollset_add failure");
865 apr_thread_mutex_lock(timeout_mutex);
866 TO_QUEUE_REMOVE(q, cs);
867 apr_thread_mutex_unlock(timeout_mutex);
868 apr_socket_close(cs->pfd.desc.s);
869 ap_push_pool(worker_queue_info, cs->p);
876 * Close our side of the connection, flushing data to the client first.
877 * Pre-condition: cs is not in any timeout queue and not in the pollset,
878 * timeout_mutex is not locked
879 * return: 0 if connection is fully closed,
880 * 1 if connection is lingering
881 * May only be called by worker thread.
883 static int start_lingering_close_blocking(event_conn_state_t *cs)
885 if (ap_start_lingering_close(cs->c)) {
887 ap_push_pool(worker_queue_info, cs->p);
890 return start_lingering_close_common(cs, 1);
894 * Close our side of the connection, NOT flushing data to the client.
895 * This should only be called if there has been an error or if we know
896 * that our send buffers are empty.
897 * Pre-condition: cs is not in any timeout queue and not in the pollset,
898 * timeout_mutex is not locked
899 * return: 0 if connection is fully closed,
900 * 1 if connection is lingering
901 * may be called by listener thread
903 static int start_lingering_close_nonblocking(event_conn_state_t *cs)
906 apr_socket_t *csd = cs->pfd.desc.s;
908 if (ap_prep_lingering_close(c)
910 || ap_shutdown_conn(c, 0) != APR_SUCCESS || c->aborted
911 || apr_socket_shutdown(csd, APR_SHUTDOWN_WRITE) != APR_SUCCESS) {
912 apr_socket_close(csd);
913 ap_push_pool(worker_queue_info, cs->p);
916 return start_lingering_close_common(cs, 0);
920 * forcibly close a lingering connection after the lingering period has
922 * Pre-condition: cs is not in any timeout queue and not in the pollset
923 * return: irrelevant (need same prototype as start_lingering_close)
925 static int stop_lingering_close(event_conn_state_t *cs)
928 apr_socket_t *csd = ap_get_conn_socket(cs->c);
929 ap_log_error(APLOG_MARK, APLOG_TRACE4, 0, ap_server_conf,
930 "socket reached timeout in lingering-close state");
931 rv = apr_socket_close(csd);
932 if (rv != APR_SUCCESS) {
933 ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf, APLOGNO(00468) "error closing socket");
936 ap_push_pool(worker_queue_info, cs->p);
941 * This runs before any non-MPM cleanup code on the connection;
942 * if the connection is currently suspended as far as modules
943 * know, provide notification of resumption.
945 static apr_status_t ptrans_pre_cleanup(void *dummy)
947 event_conn_state_t *cs = dummy;
950 notify_resume(cs, NULL);
956 * event_pre_read_request() and event_request_cleanup() track the
957 * current r for a given connection.
959 static apr_status_t event_request_cleanup(void *dummy)
962 event_conn_state_t *cs = ap_get_module_config(c->conn_config,
969 static void event_pre_read_request(request_rec *r, conn_rec *c)
971 event_conn_state_t *cs = ap_get_module_config(c->conn_config,
975 cs->sc = ap_get_module_config(ap_server_conf->module_config,
977 apr_pool_cleanup_register(r->pool, c, event_request_cleanup,
978 apr_pool_cleanup_null);
982 * event_post_read_request() tracks the current server config for a
985 static int event_post_read_request(request_rec *r)
987 conn_rec *c = r->connection;
988 event_conn_state_t *cs = ap_get_module_config(c->conn_config,
991 /* To preserve legacy behaviour (consistent with other MPMs), use
992 * the keepalive timeout from the base server (first on this IP:port)
993 * when none is explicitly configured on this server.
995 if (r->server->keep_alive_timeout_set) {
996 cs->sc = ap_get_module_config(r->server->module_config,
1000 cs->sc = ap_get_module_config(c->base_server->module_config,
1007 * process one connection in the worker
1009 static void process_socket(apr_thread_t *thd, apr_pool_t * p, apr_socket_t * sock,
1010 event_conn_state_t * cs, int my_child_num,
1014 long conn_id = ID_FROM_CHILD_THREAD(my_child_num, my_thread_num);
1016 ap_sb_handle_t *sbh;
1018 /* XXX: This will cause unbounded mem usage for long lasting connections */
1019 ap_create_sb_handle(&sbh, p, my_child_num, my_thread_num);
1021 if (cs == NULL) { /* This is a new connection */
1022 listener_poll_type *pt = apr_pcalloc(p, sizeof(*pt));
1023 cs = apr_pcalloc(p, sizeof(event_conn_state_t));
1024 cs->bucket_alloc = apr_bucket_alloc_create(p);
1025 c = ap_run_create_connection(p, ap_server_conf, sock,
1026 conn_id, sbh, cs->bucket_alloc);
1028 ap_push_pool(worker_queue_info, p);
1031 apr_atomic_inc32(&connection_count);
1032 apr_pool_cleanup_register(c->pool, cs, decrement_connection_count,
1033 apr_pool_cleanup_null);
1034 ap_set_module_config(c->conn_config, &mpm_event_module, cs);
1035 c->current_thread = thd;
1039 cs->sc = ap_get_module_config(ap_server_conf->module_config,
1041 cs->pfd.desc_type = APR_POLL_SOCKET;
1042 cs->pfd.reqevents = APR_POLLIN;
1043 cs->pfd.desc.s = sock;
1046 cs->pfd.client_data = pt;
1047 apr_pool_pre_cleanup_register(p, cs, ptrans_pre_cleanup);
1048 TO_QUEUE_ELEM_INIT(cs);
1050 ap_update_vhost_given_ip(c);
1052 rc = ap_run_pre_connection(c, sock);
1053 if (rc != OK && rc != DONE) {
1054 ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(00469)
1055 "process_socket: connection aborted");
1060 * XXX If the platform does not have a usable way of bundling
1061 * accept() with a socket readability check, like Win32,
1062 * and there are measurable delays before the
1063 * socket is readable due to the first data packet arriving,
1064 * it might be better to create the cs on the listener thread
1065 * with the state set to CONN_STATE_CHECK_REQUEST_LINE_READABLE
1067 * FreeBSD users will want to enable the HTTP accept filter
1068 * module in their kernel for the highest performance
1069 * When the accept filter is active, sockets are kept in the
1070 * kernel until a HTTP request is received.
1072 cs->pub.state = CONN_STATE_READ_REQUEST_LINE;
1074 cs->pub.sense = CONN_SENSE_DEFAULT;
1078 notify_resume(cs, sbh);
1079 c->current_thread = thd;
1080 /* Subsequent request on a conn, and thread number is part of ID */
1084 if (c->clogging_input_filters && !c->aborted) {
1085 /* Since we have an input filter which 'clogs' the input stream,
1086 * like mod_ssl used to, lets just do the normal read from input
1087 * filters, like the Worker MPM does. Filters that need to write
1088 * where they would otherwise read, or read where they would
1089 * otherwise write, should set the sense appropriately.
1091 apr_atomic_inc32(&clogged_count);
1092 ap_run_process_connection(c);
1093 if (cs->pub.state != CONN_STATE_SUSPENDED) {
1094 cs->pub.state = CONN_STATE_LINGER;
1096 apr_atomic_dec32(&clogged_count);
1100 if (cs->pub.state == CONN_STATE_READ_REQUEST_LINE) {
1102 ap_run_process_connection(c);
1104 /* state will be updated upon return
1105 * fall thru to either wait for readability/timeout or
1106 * do lingering close
1110 cs->pub.state = CONN_STATE_LINGER;
1114 if (cs->pub.state == CONN_STATE_WRITE_COMPLETION) {
1115 ap_filter_t *output_filter = c->output_filters;
1117 ap_update_child_status_from_conn(sbh, SERVER_BUSY_WRITE, c);
1118 while (output_filter->next != NULL) {
1119 output_filter = output_filter->next;
1121 rv = output_filter->frec->filter_func.out_func(output_filter, NULL);
1122 if (rv != APR_SUCCESS) {
1123 ap_log_cerror(APLOG_MARK, APLOG_DEBUG, rv, c, APLOGNO(00470)
1124 "network write failure in core output filter");
1125 cs->pub.state = CONN_STATE_LINGER;
1127 else if (c->data_in_output_filters) {
1128 /* Still in WRITE_COMPLETION_STATE:
1129 * Set a write timeout for this connection, and let the
1130 * event thread poll for writeability.
1132 cs->queue_timestamp = apr_time_now();
1134 apr_thread_mutex_lock(timeout_mutex);
1135 TO_QUEUE_APPEND(cs->sc->wc_q, cs);
1136 cs->pfd.reqevents = (
1137 cs->pub.sense == CONN_SENSE_WANT_READ ? APR_POLLIN :
1138 APR_POLLOUT) | APR_POLLHUP | APR_POLLERR;
1139 cs->pub.sense = CONN_SENSE_DEFAULT;
1140 rc = apr_pollset_add(event_pollset, &cs->pfd);
1141 apr_thread_mutex_unlock(timeout_mutex);
1144 else if (c->keepalive != AP_CONN_KEEPALIVE || c->aborted ||
1145 listener_may_exit) {
1146 cs->pub.state = CONN_STATE_LINGER;
1148 else if (c->data_in_input_filters) {
1149 cs->pub.state = CONN_STATE_READ_REQUEST_LINE;
1153 cs->pub.state = CONN_STATE_CHECK_REQUEST_LINE_READABLE;
1157 if (cs->pub.state == CONN_STATE_LINGER) {
1158 start_lingering_close_blocking(cs);
1160 else if (cs->pub.state == CONN_STATE_CHECK_REQUEST_LINE_READABLE) {
1161 /* It greatly simplifies the logic to use a single timeout value per q
1162 * because the new element can just be added to the end of the list and
1163 * it will stay sorted in expiration time sequence. If brand new
1164 * sockets are sent to the event thread for a readability check, this
1165 * will be a slight behavior change - they use the non-keepalive
1166 * timeout today. With a normal client, the socket will be readable in
1167 * a few milliseconds anyway.
1169 cs->queue_timestamp = apr_time_now();
1171 apr_thread_mutex_lock(timeout_mutex);
1172 TO_QUEUE_APPEND(cs->sc->ka_q, cs);
1174 /* Add work to pollset. */
1175 cs->pfd.reqevents = APR_POLLIN;
1176 rc = apr_pollset_add(event_pollset, &cs->pfd);
1177 apr_thread_mutex_unlock(timeout_mutex);
1179 if (rc != APR_SUCCESS) {
1180 ap_log_error(APLOG_MARK, APLOG_ERR, rc, ap_server_conf, APLOGNO(03093)
1181 "process_socket: apr_pollset_add failure");
1182 AP_DEBUG_ASSERT(rc == APR_SUCCESS);
1185 else if (cs->pub.state == CONN_STATE_SUSPENDED) {
1186 apr_atomic_inc32(&suspended_count);
1191 /* conns_this_child has gone to zero or below. See if the admin coded
1192 "MaxConnectionsPerChild 0", and keep going in that case. Doing it this way
1193 simplifies the hot path in worker_thread */
1194 static void check_infinite_requests(void)
1196 if (ap_max_requests_per_child) {
1197 ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, ap_server_conf,
1198 "Stopping process due to MaxConnectionsPerChild");
1199 signal_threads(ST_GRACEFUL);
1203 conns_this_child = APR_INT32_MAX;
1207 static void close_listeners(int process_slot, int *closed)
1211 disable_listensocks(process_slot);
1212 ap_close_listeners_ex(my_bucket->listeners);
1215 ap_scoreboard_image->parent[process_slot].quiescing = 1;
1216 for (i = 0; i < threads_per_child; ++i) {
1217 ap_update_child_status_from_indexes(process_slot, i,
1218 SERVER_GRACEFUL, NULL);
1220 /* wake up the main thread */
1221 kill(ap_my_pid, SIGTERM);
1225 static void unblock_signal(int sig)
1229 sigemptyset(&sig_mask);
1230 sigaddset(&sig_mask, sig);
1231 #if defined(SIGPROCMASK_SETS_THREAD_MASK)
1232 sigprocmask(SIG_UNBLOCK, &sig_mask, NULL);
1234 pthread_sigmask(SIG_UNBLOCK, &sig_mask, NULL);
1238 static void dummy_signal_handler(int sig)
1240 /* XXX If specifying SIG_IGN is guaranteed to unblock a syscall,
1241 * then we don't need this goofy function.
1246 static apr_status_t init_pollset(apr_pool_t *p)
1249 listener_poll_type *pt;
1252 listener_pollfd = apr_palloc(p, sizeof(apr_pollfd_t) * num_listensocks);
1253 for (lr = my_bucket->listeners; lr != NULL; lr = lr->next, i++) {
1255 AP_DEBUG_ASSERT(i < num_listensocks);
1256 pfd = &listener_pollfd[i];
1257 pt = apr_pcalloc(p, sizeof(*pt));
1258 pfd->desc_type = APR_POLL_SOCKET;
1259 pfd->desc.s = lr->sd;
1260 pfd->reqevents = APR_POLLIN;
1262 pt->type = PT_ACCEPT;
1265 pfd->client_data = pt;
1267 apr_socket_opt_set(pfd->desc.s, APR_SO_NONBLOCK, 1);
1268 apr_pollset_add(event_pollset, pfd);
1270 lr->accept_func = ap_unixd_accept;
1276 static apr_status_t push_timer2worker(timer_event_t* te)
1278 return ap_queue_push_timer(worker_queue, te);
1282 * Pre-condition: pfd->cs is neither in pollset nor timeout queue
1283 * this function may only be called by the listener
1285 static apr_status_t push2worker(const apr_pollfd_t * pfd,
1286 apr_pollset_t * pollset)
1288 listener_poll_type *pt = (listener_poll_type *) pfd->client_data;
1289 event_conn_state_t *cs = (event_conn_state_t *) pt->baton;
1292 rc = ap_queue_push(worker_queue, cs->pfd.desc.s, cs, cs->p);
1293 if (rc != APR_SUCCESS) {
1294 /* trash the connection; we couldn't queue the connected
1295 * socket to a worker
1297 apr_bucket_alloc_destroy(cs->bucket_alloc);
1298 apr_socket_close(cs->pfd.desc.s);
1299 ap_log_error(APLOG_MARK, APLOG_CRIT, rc,
1300 ap_server_conf, APLOGNO(00471) "push2worker: ap_queue_push failed");
1301 ap_push_pool(worker_queue_info, cs->p);
1308 * If *have_idle_worker_p == 0, reserve a worker thread, and set
1309 * *have_idle_worker_p = 1.
1310 * If *have_idle_worker_p is already 1, will do nothing.
1311 * If blocking == 1, block if all workers are currently busy.
1312 * If no worker was available immediately, will set *all_busy to 1.
1313 * XXX: If there are no workers, we should not block immediately but
1314 * XXX: close all keep-alive connections first.
1316 static void get_worker(int *have_idle_worker_p, int blocking, int *all_busy)
1320 if (*have_idle_worker_p) {
1321 /* already reserved a worker thread - must have hit a
1322 * transient error on a previous pass
1328 rc = ap_queue_info_wait_for_idler(worker_queue_info, all_busy);
1330 rc = ap_queue_info_try_get_idler(worker_queue_info);
1332 if (rc == APR_SUCCESS || APR_STATUS_IS_EOF(rc)) {
1333 *have_idle_worker_p = 1;
1335 else if (!blocking && rc == APR_EAGAIN) {
1339 ap_log_error(APLOG_MARK, APLOG_ERR, rc, ap_server_conf, APLOGNO(00472)
1340 "ap_queue_info_wait_for_idler failed. "
1341 "Attempting to shutdown process gracefully");
1342 signal_threads(ST_GRACEFUL);
1346 /* Structures to reuse */
1347 static APR_RING_HEAD(timer_free_ring_t, timer_event_t) timer_free_ring;
1349 static apr_skiplist *timer_skiplist;
1351 /* The following compare function is used by apr_skiplist_insert() to keep the
1352 * elements (timers) sorted and provide O(log n) complexity (this is also true
1353 * for apr_skiplist_{find,remove}(), but those are not used in MPM event where
1354 * inserted timers are not searched nor removed, but with apr_skiplist_pop()
1355 * which does use any compare function). It is meant to return 0 when a == b,
1356 * <0 when a < b, and >0 when a > b. However apr_skiplist_insert() will not
1357 * add duplicates (i.e. a == b), and apr_skiplist_add() is only available in
1358 * APR 1.6, yet multiple timers could possibly be created in the same micro-
1359 * second (duplicates with regard to apr_time_t); therefore we implement the
1360 * compare function to return +1 instead of 0 when compared timers are equal,
1361 * thus duplicates are still added after each other (in order of insertion).
1363 static int timer_comp(void *a, void *b)
1365 apr_time_t t1 = (apr_time_t) ((timer_event_t *)a)->when;
1366 apr_time_t t2 = (apr_time_t) ((timer_event_t *)b)->when;
1367 AP_DEBUG_ASSERT(t1);
1368 AP_DEBUG_ASSERT(t2);
1369 return ((t1 < t2) ? -1 : 1);
1372 static apr_thread_mutex_t *g_timer_skiplist_mtx;
1374 static apr_status_t event_register_timed_callback(apr_time_t t,
1375 ap_mpm_callback_fn_t *cbfn,
1379 /* oh yeah, and make locking smarter/fine grained. */
1380 apr_thread_mutex_lock(g_timer_skiplist_mtx);
1382 if (!APR_RING_EMPTY(&timer_free_ring, timer_event_t, link)) {
1383 te = APR_RING_FIRST(&timer_free_ring);
1384 APR_RING_REMOVE(te, link);
1387 te = apr_skiplist_alloc(timer_skiplist, sizeof(timer_event_t));
1388 APR_RING_ELEM_INIT(te, link);
1393 /* XXXXX: optimize */
1394 te->when = t + apr_time_now();
1396 /* Okay, add sorted by when.. */
1397 apr_skiplist_insert(timer_skiplist, te);
1399 apr_thread_mutex_unlock(g_timer_skiplist_mtx);
1406 * Close socket and clean up if remote closed its end while we were in
1408 * Only to be called in the listener thread;
1409 * Pre-condition: cs is in one of the linger queues and in the pollset
1411 static void process_lingering_close(event_conn_state_t *cs, const apr_pollfd_t *pfd)
1413 apr_socket_t *csd = ap_get_conn_socket(cs->c);
1414 char dummybuf[2048];
1417 struct timeout_queue *q;
1418 q = (cs->pub.state == CONN_STATE_LINGER_SHORT) ? short_linger_q : linger_q;
1420 /* socket is already in non-blocking state */
1422 nbytes = sizeof(dummybuf);
1423 rv = apr_socket_recv(csd, dummybuf, &nbytes);
1424 } while (rv == APR_SUCCESS);
1426 if (APR_STATUS_IS_EAGAIN(rv)) {
1430 apr_thread_mutex_lock(timeout_mutex);
1431 rv = apr_pollset_remove(event_pollset, pfd);
1432 AP_DEBUG_ASSERT(rv == APR_SUCCESS);
1434 rv = apr_socket_close(csd);
1435 AP_DEBUG_ASSERT(rv == APR_SUCCESS);
1437 TO_QUEUE_REMOVE(q, cs);
1438 apr_thread_mutex_unlock(timeout_mutex);
1439 TO_QUEUE_ELEM_INIT(cs);
1441 ap_push_pool(worker_queue_info, cs->p);
1444 /* call 'func' for all elements of 'q' with timeout less than 'timeout_time'.
1445 * Pre-condition: timeout_mutex must already be locked
1446 * Post-condition: timeout_mutex will be locked again
1448 static void process_timeout_queue(struct timeout_queue *q,
1449 apr_time_t timeout_time,
1450 int (*func)(event_conn_state_t *))
1452 int total = 0, count;
1453 event_conn_state_t *first, *cs, *last;
1454 struct timeout_head_t trash;
1455 struct timeout_queue *qp;
1462 APR_RING_INIT(&trash, event_conn_state_t, timeout_list);
1463 for (qp = q; qp; qp = qp->next) {
1465 cs = first = last = APR_RING_FIRST(&qp->head);
1466 while (cs != APR_RING_SENTINEL(&qp->head, event_conn_state_t,
1468 /* Trash the entry if:
1469 * - no timeout_time was given (asked for all), or
1470 * - it expired (according to the queue timeout), or
1471 * - the system clock skewed in the past: no entry should be
1472 * registered above the given timeout_time (~now) + the queue
1473 * timeout, we won't keep any here (eg. for centuries).
1474 * Stop otherwise, no following entry will match thanks to the
1475 * single timeout per queue (entries are added to the end!).
1476 * This allows maintenance in O(1).
1479 || cs->queue_timestamp + qp->timeout < timeout_time
1480 || cs->queue_timestamp > timeout_time + qp->timeout)) {
1482 rv = apr_pollset_remove(event_pollset, &cs->pfd);
1483 if (rv != APR_SUCCESS && !APR_STATUS_IS_NOTFOUND(rv)) {
1484 ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, cs->c, APLOGNO(00473)
1485 "apr_pollset_remove failed");
1487 cs = APR_RING_NEXT(cs, timeout_list);
1493 APR_RING_UNSPLICE(first, last, timeout_list);
1494 APR_RING_SPLICE_TAIL(&trash, first, last, event_conn_state_t,
1502 AP_DEBUG_ASSERT(*q->total >= total);
1504 apr_thread_mutex_unlock(timeout_mutex);
1505 first = APR_RING_FIRST(&trash);
1507 cs = APR_RING_NEXT(first, timeout_list);
1508 TO_QUEUE_ELEM_INIT(first);
1512 apr_thread_mutex_lock(timeout_mutex);
1515 static void * APR_THREAD_FUNC listener_thread(apr_thread_t * thd, void *dummy)
1520 proc_info *ti = dummy;
1521 int process_slot = ti->pid;
1522 apr_pool_t *tpool = apr_thread_pool_get(thd);
1524 apr_pool_t *ptrans; /* Pool for per-transaction stuff */
1526 int have_idle_worker = 0;
1527 const apr_pollfd_t *out_pfd;
1528 apr_int32_t num = 0;
1529 apr_interval_time_t timeout_interval;
1530 apr_time_t timeout_time = 0, now, last_log;
1531 listener_poll_type *pt;
1532 int closed = 0, listeners_disabled = 0;
1534 last_log = apr_time_now();
1537 /* the following times out events that are really close in the future
1538 * to prevent extra poll calls
1540 * current value is .1 second
1542 #define TIMEOUT_FUDGE_FACTOR 100000
1543 #define EVENT_FUDGE_FACTOR 10000
1545 rc = init_pollset(tpool);
1546 if (rc != APR_SUCCESS) {
1547 ap_log_error(APLOG_MARK, APLOG_ERR, rc, ap_server_conf,
1548 "failed to initialize pollset, "
1549 "attempting to shutdown process gracefully");
1550 signal_threads(ST_GRACEFUL);
1554 /* Unblock the signal used to wake this thread up, and set a handler for
1557 unblock_signal(LISTENER_SIGNAL);
1558 apr_signal(LISTENER_SIGNAL, dummy_signal_handler);
1561 int workers_were_busy = 0;
1562 if (listener_may_exit) {
1563 close_listeners(process_slot, &closed);
1564 if (terminate_mode == ST_UNGRACEFUL
1565 || apr_atomic_read32(&connection_count) == 0)
1569 if (conns_this_child <= 0)
1570 check_infinite_requests();
1572 now = apr_time_now();
1573 if (APLOGtrace6(ap_server_conf)) {
1574 /* trace log status every second */
1575 if (now - last_log > apr_time_from_msec(1000)) {
1577 apr_thread_mutex_lock(timeout_mutex);
1578 ap_log_error(APLOG_MARK, APLOG_TRACE6, 0, ap_server_conf,
1579 "connections: %u (clogged: %u write-completion: %d "
1580 "keep-alive: %d lingering: %d suspended: %u)",
1581 apr_atomic_read32(&connection_count),
1582 apr_atomic_read32(&clogged_count),
1583 *write_completion_q->total,
1584 *keepalive_q->total,
1585 apr_atomic_read32(&lingering_count),
1586 apr_atomic_read32(&suspended_count));
1587 apr_thread_mutex_unlock(timeout_mutex);
1591 apr_thread_mutex_lock(g_timer_skiplist_mtx);
1592 te = apr_skiplist_peek(timer_skiplist);
1594 if (te->when > now) {
1595 timeout_interval = te->when - now;
1598 timeout_interval = 1;
1602 timeout_interval = apr_time_from_msec(100);
1604 apr_thread_mutex_unlock(g_timer_skiplist_mtx);
1606 rc = apr_pollset_poll(event_pollset, timeout_interval, &num, &out_pfd);
1607 if (rc != APR_SUCCESS) {
1608 if (APR_STATUS_IS_EINTR(rc)) {
1611 if (!APR_STATUS_IS_TIMEUP(rc)) {
1612 ap_log_error(APLOG_MARK, APLOG_CRIT, rc, ap_server_conf,
1613 "apr_pollset_poll failed. Attempting to "
1614 "shutdown process gracefully");
1615 signal_threads(ST_GRACEFUL);
1619 if (listener_may_exit) {
1620 close_listeners(process_slot, &closed);
1621 if (terminate_mode == ST_UNGRACEFUL
1622 || apr_atomic_read32(&connection_count) == 0)
1626 now = apr_time_now();
1627 apr_thread_mutex_lock(g_timer_skiplist_mtx);
1628 ep = apr_skiplist_peek(timer_skiplist);
1630 if (ep->when < now + EVENT_FUDGE_FACTOR) {
1631 apr_skiplist_pop(timer_skiplist, NULL);
1632 push_timer2worker(ep);
1637 ep = apr_skiplist_peek(timer_skiplist);
1639 apr_thread_mutex_unlock(g_timer_skiplist_mtx);
1642 pt = (listener_poll_type *) out_pfd->client_data;
1643 if (pt->type == PT_CSD) {
1644 /* one of the sockets is readable */
1645 event_conn_state_t *cs = (event_conn_state_t *) pt->baton;
1646 struct timeout_queue *remove_from_q = cs->sc->wc_q;
1649 switch (cs->pub.state) {
1650 case CONN_STATE_CHECK_REQUEST_LINE_READABLE:
1651 cs->pub.state = CONN_STATE_READ_REQUEST_LINE;
1652 remove_from_q = cs->sc->ka_q;
1653 /* don't wait for a worker for a keepalive request */
1656 case CONN_STATE_WRITE_COMPLETION:
1657 get_worker(&have_idle_worker, blocking,
1658 &workers_were_busy);
1659 apr_thread_mutex_lock(timeout_mutex);
1660 TO_QUEUE_REMOVE(remove_from_q, cs);
1661 rc = apr_pollset_remove(event_pollset, &cs->pfd);
1662 apr_thread_mutex_unlock(timeout_mutex);
1665 * Some of the pollset backends, like KQueue or Epoll
1666 * automagically remove the FD if the socket is closed,
1667 * therefore, we can accept _SUCCESS or _NOTFOUND,
1668 * and we still want to keep going
1670 if (rc != APR_SUCCESS && !APR_STATUS_IS_NOTFOUND(rc)) {
1671 ap_log_error(APLOG_MARK, APLOG_ERR, rc, ap_server_conf,
1672 APLOGNO(03094) "pollset remove failed");
1673 start_lingering_close_nonblocking(cs);
1677 TO_QUEUE_ELEM_INIT(cs);
1678 /* If we didn't get a worker immediately for a keep-alive
1679 * request, we close the connection, so that the client can
1680 * re-connect to a different process.
1682 if (!have_idle_worker) {
1683 start_lingering_close_nonblocking(cs);
1686 rc = push2worker(out_pfd, event_pollset);
1687 if (rc != APR_SUCCESS) {
1688 ap_log_error(APLOG_MARK, APLOG_CRIT, rc,
1689 ap_server_conf, APLOGNO(03095)
1690 "push2worker failed");
1693 have_idle_worker = 0;
1696 case CONN_STATE_LINGER_NORMAL:
1697 case CONN_STATE_LINGER_SHORT:
1698 process_lingering_close(cs, out_pfd);
1701 ap_log_error(APLOG_MARK, APLOG_CRIT, rc,
1702 ap_server_conf, APLOGNO(03096)
1703 "event_loop: unexpected state %d",
1708 else if (pt->type == PT_ACCEPT) {
1709 /* A Listener Socket is ready for an accept() */
1710 if (workers_were_busy) {
1711 if (!listeners_disabled)
1712 disable_listensocks(process_slot);
1713 listeners_disabled = 1;
1714 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
1715 "All workers busy, not accepting new conns "
1718 else if ( (int)apr_atomic_read32(&connection_count)
1719 - (int)apr_atomic_read32(&lingering_count)
1721 + ap_queue_info_get_idlers(worker_queue_info) *
1722 worker_factor / WORKER_FACTOR_SCALE)
1724 if (!listeners_disabled)
1725 disable_listensocks(process_slot);
1726 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
1727 "Too many open connections (%u), "
1728 "not accepting new conns in this process",
1729 apr_atomic_read32(&connection_count));
1730 ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, ap_server_conf,
1732 ap_queue_info_get_idlers(worker_queue_info));
1733 listeners_disabled = 1;
1735 else if (listeners_disabled) {
1736 listeners_disabled = 0;
1737 enable_listensocks(process_slot);
1739 if (!listeners_disabled) {
1740 lr = (ap_listen_rec *) pt->baton;
1741 ap_pop_pool(&ptrans, worker_queue_info);
1743 if (ptrans == NULL) {
1744 /* create a new transaction pool for each accepted socket */
1745 apr_allocator_t *allocator;
1747 apr_allocator_create(&allocator);
1748 apr_allocator_max_free_set(allocator,
1750 apr_pool_create_ex(&ptrans, pconf, NULL, allocator);
1751 apr_allocator_owner_set(allocator, ptrans);
1752 if (ptrans == NULL) {
1753 ap_log_error(APLOG_MARK, APLOG_CRIT, rc,
1754 ap_server_conf, APLOGNO(03097)
1755 "Failed to create transaction pool");
1756 signal_threads(ST_GRACEFUL);
1760 apr_pool_tag(ptrans, "transaction");
1762 get_worker(&have_idle_worker, 1, &workers_were_busy);
1763 rc = lr->accept_func(&csd, lr, ptrans);
1765 /* later we trash rv and rely on csd to indicate
1768 AP_DEBUG_ASSERT(rc == APR_SUCCESS || !csd);
1770 if (rc == APR_EGENERAL) {
1771 /* E[NM]FILE, ENOMEM, etc */
1772 resource_shortage = 1;
1773 signal_threads(ST_GRACEFUL);
1778 rc = ap_queue_push(worker_queue, csd, NULL, ptrans);
1779 if (rc != APR_SUCCESS) {
1780 /* trash the connection; we couldn't queue the connected
1781 * socket to a worker
1783 apr_socket_close(csd);
1784 ap_log_error(APLOG_MARK, APLOG_CRIT, rc,
1785 ap_server_conf, APLOGNO(03098)
1786 "ap_queue_push failed");
1787 ap_push_pool(worker_queue_info, ptrans);
1790 have_idle_worker = 0;
1794 ap_push_pool(worker_queue_info, ptrans);
1797 } /* if:else on pt->type */
1800 } /* while for processing poll */
1802 /* XXX possible optimization: stash the current time for use as
1803 * r->request_time for new requests
1805 now = apr_time_now();
1806 /* We only do this once per 0.1s (TIMEOUT_FUDGE_FACTOR), or on a clock
1807 * skew (if the system time is set back in the meantime, timeout_time
1808 * will exceed now + TIMEOUT_FUDGE_FACTOR, can't happen otherwise).
1810 if (now > timeout_time || now + TIMEOUT_FUDGE_FACTOR < timeout_time ) {
1811 struct process_score *ps;
1812 timeout_time = now + TIMEOUT_FUDGE_FACTOR;
1814 /* handle timed out sockets */
1815 apr_thread_mutex_lock(timeout_mutex);
1817 /* Step 1: keepalive timeouts */
1818 /* If all workers are busy, we kill older keep-alive connections so that they
1819 * may connect to another process.
1821 if (workers_were_busy && *keepalive_q->total) {
1822 ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, ap_server_conf,
1823 "All workers are busy, will close %d keep-alive "
1825 *keepalive_q->total);
1826 process_timeout_queue(keepalive_q, 0,
1827 start_lingering_close_nonblocking);
1830 process_timeout_queue(keepalive_q, timeout_time,
1831 start_lingering_close_nonblocking);
1833 /* Step 2: write completion timeouts */
1834 process_timeout_queue(write_completion_q, timeout_time,
1835 start_lingering_close_nonblocking);
1836 /* Step 3: (normal) lingering close completion timeouts */
1837 process_timeout_queue(linger_q, timeout_time, stop_lingering_close);
1838 /* Step 4: (short) lingering close completion timeouts */
1839 process_timeout_queue(short_linger_q, timeout_time, stop_lingering_close);
1841 ps = ap_get_scoreboard_process(process_slot);
1842 ps->write_completion = *write_completion_q->total;
1843 ps->keep_alive = *keepalive_q->total;
1844 apr_thread_mutex_unlock(timeout_mutex);
1846 ps->connections = apr_atomic_read32(&connection_count);
1847 ps->suspended = apr_atomic_read32(&suspended_count);
1848 ps->lingering_close = apr_atomic_read32(&lingering_count);
1850 if (listeners_disabled && !workers_were_busy
1851 && (int)apr_atomic_read32(&connection_count)
1852 - (int)apr_atomic_read32(&lingering_count)
1853 < ((int)ap_queue_info_get_idlers(worker_queue_info) - 1)
1854 * worker_factor / WORKER_FACTOR_SCALE + threads_per_child)
1856 listeners_disabled = 0;
1857 enable_listensocks(process_slot);
1860 * XXX: do we need to set some timeout that re-enables the listensocks
1861 * XXX: in case no other event occurs?
1863 } /* listener main loop */
1865 close_listeners(process_slot, &closed);
1866 ap_queue_term(worker_queue);
1868 apr_thread_exit(thd, APR_SUCCESS);
1872 /* XXX For ungraceful termination/restart, we definitely don't want to
1873 * wait for active connections to finish but we may want to wait
1874 * for idle workers to get out of the queue code and release mutexes,
1875 * since those mutexes are cleaned up pretty soon and some systems
1876 * may not react favorably (i.e., segfault) if operations are attempted
1877 * on cleaned-up mutexes.
1879 static void *APR_THREAD_FUNC worker_thread(apr_thread_t * thd, void *dummy)
1881 proc_info *ti = dummy;
1882 int process_slot = ti->pid;
1883 int thread_slot = ti->tid;
1884 apr_socket_t *csd = NULL;
1885 event_conn_state_t *cs;
1886 apr_pool_t *ptrans; /* Pool for per-transaction stuff */
1889 timer_event_t *te = NULL;
1893 ap_scoreboard_image->servers[process_slot][thread_slot].pid = ap_my_pid;
1894 ap_scoreboard_image->servers[process_slot][thread_slot].tid = apr_os_thread_current();
1895 ap_scoreboard_image->servers[process_slot][thread_slot].generation = retained->my_generation;
1896 ap_update_child_status_from_indexes(process_slot, thread_slot,
1897 SERVER_STARTING, NULL);
1899 while (!workers_may_exit) {
1901 rv = ap_queue_info_set_idle(worker_queue_info, NULL);
1902 if (rv != APR_SUCCESS) {
1903 ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
1904 "ap_queue_info_set_idle failed. Attempting to "
1905 "shutdown process gracefully.");
1906 signal_threads(ST_GRACEFUL);
1912 ap_update_child_status_from_indexes(process_slot, thread_slot,
1913 dying ? SERVER_GRACEFUL : SERVER_READY, NULL);
1915 if (workers_may_exit) {
1920 rv = ap_queue_pop_something(worker_queue, &csd, &cs, &ptrans, &te);
1922 if (rv != APR_SUCCESS) {
1923 /* We get APR_EOF during a graceful shutdown once all the
1924 * connections accepted by this server process have been handled.
1926 if (APR_STATUS_IS_EOF(rv)) {
1929 /* We get APR_EINTR whenever ap_queue_pop() has been interrupted
1930 * from an explicit call to ap_queue_interrupt_all(). This allows
1931 * us to unblock threads stuck in ap_queue_pop() when a shutdown
1934 * If workers_may_exit is set and this is ungraceful termination/
1935 * restart, we are bound to get an error on some systems (e.g.,
1936 * AIX, which sanity-checks mutex operations) since the queue
1937 * may have already been cleaned up. Don't log the "error" if
1938 * workers_may_exit is set.
1940 else if (APR_STATUS_IS_EINTR(rv)) {
1943 /* We got some other error. */
1944 else if (!workers_may_exit) {
1945 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
1946 APLOGNO(03099) "ap_queue_pop failed");
1951 te->cbfunc(te->baton);
1954 apr_thread_mutex_lock(g_timer_skiplist_mtx);
1955 APR_RING_INSERT_TAIL(&timer_free_ring, te, timer_event_t, link);
1956 apr_thread_mutex_unlock(g_timer_skiplist_mtx);
1961 worker_sockets[thread_slot] = csd;
1962 process_socket(thd, ptrans, csd, cs, process_slot, thread_slot);
1963 worker_sockets[thread_slot] = NULL;
1967 ap_update_child_status_from_indexes(process_slot, thread_slot,
1968 dying ? SERVER_DEAD :
1970 (request_rec *) NULL);
1972 apr_thread_exit(thd, APR_SUCCESS);
1976 static int check_signal(int signum)
1988 static void create_listener_thread(thread_starter * ts)
1990 int my_child_num = ts->child_num_arg;
1991 apr_threadattr_t *thread_attr = ts->threadattr;
1995 my_info = (proc_info *) ap_malloc(sizeof(proc_info));
1996 my_info->pid = my_child_num;
1997 my_info->tid = -1; /* listener thread doesn't have a thread slot */
1999 rv = apr_thread_create(&ts->listener, thread_attr, listener_thread,
2001 if (rv != APR_SUCCESS) {
2002 ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf, APLOGNO(00474)
2003 "apr_thread_create: unable to create listener thread");
2004 /* let the parent decide how bad this really is */
2005 clean_child_exit(APEXIT_CHILDSICK);
2007 apr_os_thread_get(&listener_os_thread, ts->listener);
2010 /* XXX under some circumstances not understood, children can get stuck
2011 * in start_threads forever trying to take over slots which will
2012 * never be cleaned up; for now there is an APLOG_DEBUG message issued
2013 * every so often when this condition occurs
2015 static void *APR_THREAD_FUNC start_threads(apr_thread_t * thd, void *dummy)
2017 thread_starter *ts = dummy;
2018 apr_thread_t **threads = ts->threads;
2019 apr_threadattr_t *thread_attr = ts->threadattr;
2020 int child_num_arg = ts->child_num_arg;
2021 int my_child_num = child_num_arg;
2025 int threads_created = 0;
2026 int listener_started = 0;
2028 int prev_threads_created;
2029 int max_recycled_pools = -1;
2030 int good_methods[] = {APR_POLLSET_KQUEUE, APR_POLLSET_PORT, APR_POLLSET_EPOLL};
2032 /* We must create the fd queues before we start up the listener
2033 * and worker threads. */
2034 worker_queue = apr_pcalloc(pchild, sizeof(*worker_queue));
2035 rv = ap_queue_init(worker_queue, threads_per_child, pchild);
2036 if (rv != APR_SUCCESS) {
2037 ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf, APLOGNO(03100)
2038 "ap_queue_init() failed");
2039 clean_child_exit(APEXIT_CHILDFATAL);
2042 if (ap_max_mem_free != APR_ALLOCATOR_MAX_FREE_UNLIMITED) {
2043 /* If we want to conserve memory, let's not keep an unlimited number of
2044 * pools & allocators.
2045 * XXX: This should probably be a separate config directive
2047 max_recycled_pools = threads_per_child * 3 / 4 ;
2049 rv = ap_queue_info_create(&worker_queue_info, pchild,
2050 threads_per_child, max_recycled_pools);
2051 if (rv != APR_SUCCESS) {
2052 ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf, APLOGNO(03101)
2053 "ap_queue_info_create() failed");
2054 clean_child_exit(APEXIT_CHILDFATAL);
2057 /* Create the timeout mutex and main pollset before the listener
2060 rv = apr_thread_mutex_create(&timeout_mutex, APR_THREAD_MUTEX_DEFAULT,
2062 if (rv != APR_SUCCESS) {
2063 ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf, APLOGNO(03102)
2064 "creation of the timeout mutex failed.");
2065 clean_child_exit(APEXIT_CHILDFATAL);
2068 /* Create the main pollset */
2069 for (i = 0; i < sizeof(good_methods) / sizeof(void*); i++) {
2070 rv = apr_pollset_create_ex(&event_pollset,
2071 threads_per_child*2, /* XXX don't we need more, to handle
2072 * connections in K-A or lingering
2075 pchild, APR_POLLSET_THREADSAFE | APR_POLLSET_NOCOPY | APR_POLLSET_NODEFAULT,
2077 if (rv == APR_SUCCESS) {
2081 if (rv != APR_SUCCESS) {
2082 rv = apr_pollset_create(&event_pollset,
2083 threads_per_child*2, /* XXX don't we need more, to handle
2084 * connections in K-A or lingering
2087 pchild, APR_POLLSET_THREADSAFE | APR_POLLSET_NOCOPY);
2089 if (rv != APR_SUCCESS) {
2090 ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf, APLOGNO(03103)
2091 "apr_pollset_create with Thread Safety failed.");
2092 clean_child_exit(APEXIT_CHILDFATAL);
2095 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02471)
2096 "start_threads: Using %s", apr_pollset_method_name(event_pollset));
2097 worker_sockets = apr_pcalloc(pchild, threads_per_child
2098 * sizeof(apr_socket_t *));
2100 loops = prev_threads_created = 0;
2102 /* threads_per_child does not include the listener thread */
2103 for (i = 0; i < threads_per_child; i++) {
2105 ap_scoreboard_image->servers[child_num_arg][i].status;
2107 if (status != SERVER_GRACEFUL && status != SERVER_DEAD) {
2111 my_info = (proc_info *) ap_malloc(sizeof(proc_info));
2112 my_info->pid = my_child_num;
2116 /* We are creating threads right now */
2117 ap_update_child_status_from_indexes(my_child_num, i,
2118 SERVER_STARTING, NULL);
2119 /* We let each thread update its own scoreboard entry. This is
2120 * done because it lets us deal with tid better.
2122 rv = apr_thread_create(&threads[i], thread_attr,
2123 worker_thread, my_info, pchild);
2124 if (rv != APR_SUCCESS) {
2125 ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
2127 "apr_thread_create: unable to create worker thread");
2128 /* let the parent decide how bad this really is */
2129 clean_child_exit(APEXIT_CHILDSICK);
2134 /* Start the listener only when there are workers available */
2135 if (!listener_started && threads_created) {
2136 create_listener_thread(ts);
2137 listener_started = 1;
2141 if (start_thread_may_exit || threads_created == threads_per_child) {
2144 /* wait for previous generation to clean up an entry */
2145 apr_sleep(apr_time_from_sec(1));
2147 if (loops % 120 == 0) { /* every couple of minutes */
2148 if (prev_threads_created == threads_created) {
2149 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
2150 "child %" APR_PID_T_FMT " isn't taking over "
2151 "slots very quickly (%d of %d)",
2152 ap_my_pid, threads_created,
2155 prev_threads_created = threads_created;
2159 /* What state should this child_main process be listed as in the
2161 * ap_update_child_status_from_indexes(my_child_num, i, SERVER_STARTING,
2162 * (request_rec *) NULL);
2164 * This state should be listed separately in the scoreboard, in some kind
2165 * of process_status, not mixed in with the worker threads' status.
2166 * "life_status" is almost right, but it's in the worker's structure, and
2167 * the name could be clearer. gla
2169 apr_thread_exit(thd, APR_SUCCESS);
2173 static void join_workers(apr_thread_t * listener, apr_thread_t ** threads)
2176 apr_status_t rv, thread_rv;
2181 /* deal with a rare timing window which affects waking up the
2182 * listener thread... if the signal sent to the listener thread
2183 * is delivered between the time it verifies that the
2184 * listener_may_exit flag is clear and the time it enters a
2185 * blocking syscall, the signal didn't do any good... work around
2186 * that by sleeping briefly and sending it again
2190 while (iter < 10 && !dying) {
2191 /* listener has not stopped accepting yet */
2192 apr_sleep(apr_time_make(0, 500000));
2197 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(00475)
2198 "the listener thread didn't stop accepting");
2201 rv = apr_thread_join(&thread_rv, listener);
2202 if (rv != APR_SUCCESS) {
2203 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf, APLOGNO(00476)
2204 "apr_thread_join: unable to join listener thread");
2209 for (i = 0; i < threads_per_child; i++) {
2210 if (threads[i]) { /* if we ever created this thread */
2211 rv = apr_thread_join(&thread_rv, threads[i]);
2212 if (rv != APR_SUCCESS) {
2213 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf, APLOGNO(00477)
2214 "apr_thread_join: unable to join worker "
2221 static void join_start_thread(apr_thread_t * start_thread_id)
2223 apr_status_t rv, thread_rv;
2225 start_thread_may_exit = 1; /* tell it to give up in case it is still
2226 * trying to take over slots from a
2227 * previous generation
2229 rv = apr_thread_join(&thread_rv, start_thread_id);
2230 if (rv != APR_SUCCESS) {
2231 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf, APLOGNO(00478)
2232 "apr_thread_join: unable to join the start " "thread");
2236 static void child_main(int child_num_arg, int child_bucket)
2238 apr_thread_t **threads;
2241 apr_threadattr_t *thread_attr;
2242 apr_thread_t *start_thread_id;
2245 mpm_state = AP_MPMQ_STARTING; /* for benefit of any hooks that run as this
2248 ap_my_pid = getpid();
2249 ap_fatal_signal_child_setup(ap_server_conf);
2250 apr_pool_create(&pchild, pconf);
2252 /* close unused listeners and pods */
2253 for (i = 0; i < retained->num_buckets; i++) {
2254 if (i != child_bucket) {
2255 ap_close_listeners_ex(all_buckets[i].listeners);
2256 ap_mpm_podx_close(all_buckets[i].pod);
2260 /*stuff to do before we switch id's, so we have permissions. */
2261 ap_reopen_scoreboard(pchild, NULL, 0);
2263 if (ap_run_drop_privileges(pchild, ap_server_conf)) {
2264 clean_child_exit(APEXIT_CHILDFATAL);
2267 apr_thread_mutex_create(&g_timer_skiplist_mtx, APR_THREAD_MUTEX_DEFAULT, pchild);
2268 APR_RING_INIT(&timer_free_ring, timer_event_t, link);
2269 apr_skiplist_init(&timer_skiplist, pchild);
2270 apr_skiplist_set_compare(timer_skiplist, timer_comp, timer_comp);
2271 ap_run_child_init(pchild, ap_server_conf);
2273 /* done with init critical section */
2275 /* Just use the standard apr_setup_signal_thread to block all signals
2276 * from being received. The child processes no longer use signals for
2277 * any communication with the parent process.
2279 rv = apr_setup_signal_thread();
2280 if (rv != APR_SUCCESS) {
2281 ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf, APLOGNO(00479)
2282 "Couldn't initialize signal thread");
2283 clean_child_exit(APEXIT_CHILDFATAL);
2286 if (ap_max_requests_per_child) {
2287 conns_this_child = ap_max_requests_per_child;
2290 /* coding a value of zero means infinity */
2291 conns_this_child = APR_INT32_MAX;
2294 /* Setup worker threads */
2296 /* clear the storage; we may not create all our threads immediately,
2297 * and we want a 0 entry to indicate a thread which was not created
2299 threads = ap_calloc(threads_per_child, sizeof(apr_thread_t *));
2300 ts = apr_palloc(pchild, sizeof(*ts));
2302 apr_threadattr_create(&thread_attr, pchild);
2303 /* 0 means PTHREAD_CREATE_JOINABLE */
2304 apr_threadattr_detach_set(thread_attr, 0);
2306 if (ap_thread_stacksize != 0) {
2307 rv = apr_threadattr_stacksize_set(thread_attr, ap_thread_stacksize);
2308 if (rv != APR_SUCCESS && rv != APR_ENOTIMPL) {
2309 ap_log_error(APLOG_MARK, APLOG_WARNING, rv, ap_server_conf, APLOGNO(02436)
2310 "WARNING: ThreadStackSize of %" APR_SIZE_T_FMT " is "
2311 "inappropriate, using default",
2312 ap_thread_stacksize);
2316 ts->threads = threads;
2317 ts->listener = NULL;
2318 ts->child_num_arg = child_num_arg;
2319 ts->threadattr = thread_attr;
2321 rv = apr_thread_create(&start_thread_id, thread_attr, start_threads,
2323 if (rv != APR_SUCCESS) {
2324 ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf, APLOGNO(00480)
2325 "apr_thread_create: unable to create worker thread");
2326 /* let the parent decide how bad this really is */
2327 clean_child_exit(APEXIT_CHILDSICK);
2330 mpm_state = AP_MPMQ_RUNNING;
2332 /* If we are only running in one_process mode, we will want to
2333 * still handle signals. */
2335 /* Block until we get a terminating signal. */
2336 apr_signal_thread(check_signal);
2337 /* make sure the start thread has finished; signal_threads()
2338 * and join_workers() depend on that
2340 /* XXX join_start_thread() won't be awakened if one of our
2341 * threads encounters a critical error and attempts to
2342 * shutdown this child
2344 join_start_thread(start_thread_id);
2346 /* helps us terminate a little more quickly than the dispatch of the
2347 * signal thread; beats the Pipe of Death and the browsers
2349 signal_threads(ST_UNGRACEFUL);
2351 /* A terminating signal was received. Now join each of the
2352 * workers to clean them up.
2353 * If the worker already exited, then the join frees
2354 * their resources and returns.
2355 * If the worker hasn't exited, then this blocks until
2356 * they have (then cleans up).
2358 join_workers(ts->listener, threads);
2360 else { /* !one_process */
2361 /* remove SIGTERM from the set of blocked signals... if one of
2362 * the other threads in the process needs to take us down
2363 * (e.g., for MaxConnectionsPerChild) it will send us SIGTERM
2365 unblock_signal(SIGTERM);
2366 apr_signal(SIGTERM, dummy_signal_handler);
2367 /* Watch for any messages from the parent over the POD */
2369 rv = ap_mpm_podx_check(my_bucket->pod);
2370 if (rv == AP_MPM_PODX_NORESTART) {
2371 /* see if termination was triggered while we slept */
2372 switch (terminate_mode) {
2374 rv = AP_MPM_PODX_GRACEFUL;
2377 rv = AP_MPM_PODX_RESTART;
2381 if (rv == AP_MPM_PODX_GRACEFUL || rv == AP_MPM_PODX_RESTART) {
2382 /* make sure the start thread has finished;
2383 * signal_threads() and join_workers depend on that
2385 join_start_thread(start_thread_id);
2386 signal_threads(rv ==
2387 AP_MPM_PODX_GRACEFUL ? ST_GRACEFUL : ST_UNGRACEFUL);
2392 /* A terminating signal was received. Now join each of the
2393 * workers to clean them up.
2394 * If the worker already exited, then the join frees
2395 * their resources and returns.
2396 * If the worker hasn't exited, then this blocks until
2397 * they have (then cleans up).
2399 join_workers(ts->listener, threads);
2404 clean_child_exit(resource_shortage ? APEXIT_CHILDSICK : 0);
2407 static int make_child(server_rec * s, int slot, int bucket)
2411 if (slot + 1 > retained->max_daemons_limit) {
2412 retained->max_daemons_limit = slot + 1;
2416 my_bucket = &all_buckets[0];
2419 event_note_child_started(slot, getpid());
2420 child_main(slot, 0);
2426 if ((pid = fork()) == -1) {
2427 ap_log_error(APLOG_MARK, APLOG_ERR, errno, s, APLOGNO(00481)
2428 "fork: Unable to fork new process");
2430 /* fork didn't succeed. There's no need to touch the scoreboard;
2431 * if we were trying to replace a failed child process, then
2432 * server_main_loop() marked its workers SERVER_DEAD, and if
2433 * we were trying to replace a child process that exited normally,
2434 * its worker_thread()s left SERVER_DEAD or SERVER_GRACEFUL behind.
2437 /* In case system resources are maxxed out, we don't want
2438 Apache running away with the CPU trying to fork over and
2439 over and over again. */
2440 apr_sleep(apr_time_from_sec(10));
2446 my_bucket = &all_buckets[bucket];
2448 #ifdef HAVE_BINDPROCESSOR
2449 /* By default, AIX binds to a single processor. This bit unbinds
2450 * children which will then bind to another CPU.
2452 int status = bindprocessor(BINDPROCESS, (int) getpid(),
2453 PROCESSOR_CLASS_ANY);
2455 ap_log_error(APLOG_MARK, APLOG_DEBUG, errno,
2456 ap_server_conf, APLOGNO(00482)
2457 "processor unbind failed");
2459 RAISE_SIGSTOP(MAKE_CHILD);
2461 apr_signal(SIGTERM, just_die);
2462 child_main(slot, bucket);
2468 if (ap_scoreboard_image->parent[slot].pid != 0) {
2469 /* This new child process is squatting on the scoreboard
2470 * entry owned by an exiting child process, which cannot
2471 * exit until all active requests complete.
2473 event_note_child_lost_slot(slot, pid);
2475 ap_scoreboard_image->parent[slot].quiescing = 0;
2476 ap_scoreboard_image->parent[slot].not_accepting = 0;
2477 ap_scoreboard_image->parent[slot].bucket = bucket;
2478 event_note_child_started(slot, pid);
2482 /* start up a bunch of children */
2483 static void startup_children(int number_to_start)
2487 for (i = 0; number_to_start && i < ap_daemons_limit; ++i) {
2488 if (ap_scoreboard_image->parent[i].pid != 0) {
2491 if (make_child(ap_server_conf, i, i % retained->num_buckets) < 0) {
2498 static void perform_idle_server_maintenance(int child_bucket, int num_buckets)
2501 int idle_thread_count;
2505 int totally_free_length = 0;
2506 int free_slots[MAX_SPAWN_RATE];
2509 int active_thread_count = 0;
2511 /* initialize the free_list */
2514 idle_thread_count = 0;
2518 for (i = 0; i < ap_daemons_limit; ++i) {
2519 /* Initialization to satisfy the compiler. It doesn't know
2520 * that threads_per_child is always > 0 */
2521 int status = SERVER_DEAD;
2522 int any_dying_threads = 0;
2523 int any_dead_threads = 0;
2524 int all_dead_threads = 1;
2525 int child_threads_active = 0;
2527 if (i >= retained->max_daemons_limit
2528 && totally_free_length == retained->idle_spawn_rate[child_bucket])
2529 /* short cut if all active processes have been examined and
2530 * enough empty scoreboard slots have been found
2534 ps = &ap_scoreboard_image->parent[i];
2535 for (j = 0; j < threads_per_child; j++) {
2536 ws = &ap_scoreboard_image->servers[i][j];
2537 status = ws->status;
2539 /* XXX any_dying_threads is probably no longer needed GLA */
2540 any_dying_threads = any_dying_threads ||
2541 (status == SERVER_GRACEFUL);
2542 any_dead_threads = any_dead_threads || (status == SERVER_DEAD);
2543 all_dead_threads = all_dead_threads &&
2544 (status == SERVER_DEAD || status == SERVER_GRACEFUL);
2546 /* We consider a starting server as idle because we started it
2547 * at least a cycle ago, and if it still hasn't finished starting
2548 * then we're just going to swamp things worse by forking more.
2549 * So we hopefully won't need to fork more if we count it.
2550 * This depends on the ordering of SERVER_READY and SERVER_STARTING.
2552 if (ps->pid != 0) { /* XXX just set all_dead_threads in outer
2553 for loop if no pid? not much else matters */
2554 if (status <= SERVER_READY && !ps->quiescing && !ps->not_accepting
2555 && ps->generation == retained->my_generation
2556 && ps->bucket == child_bucket)
2558 ++idle_thread_count;
2560 if (status >= SERVER_READY && status < SERVER_GRACEFUL) {
2561 ++child_threads_active;
2565 active_thread_count += child_threads_active;
2566 if (any_dead_threads
2567 && totally_free_length < retained->idle_spawn_rate[child_bucket]
2568 && free_length < MAX_SPAWN_RATE / num_buckets
2569 && (!ps->pid /* no process in the slot */
2570 || ps->quiescing)) { /* or at least one is going away */
2571 if (all_dead_threads) {
2572 /* great! we prefer these, because the new process can
2573 * start more threads sooner. So prioritize this slot
2574 * by putting it ahead of any slots with active threads.
2576 * first, make room by moving a slot that's potentially still
2577 * in use to the end of the array
2579 free_slots[free_length] = free_slots[totally_free_length];
2580 free_slots[totally_free_length++] = i;
2583 /* slot is still in use - back of the bus
2585 free_slots[free_length] = i;
2589 else if (child_threads_active == threads_per_child) {
2590 had_healthy_child = 1;
2592 /* XXX if (!ps->quiescing) is probably more reliable GLA */
2593 if (!any_dying_threads) {
2599 if (retained->sick_child_detected) {
2600 if (had_healthy_child) {
2601 /* Assume this is a transient error, even though it may not be. Leave
2602 * the server up in case it is able to serve some requests or the
2603 * problem will be resolved.
2605 retained->sick_child_detected = 0;
2608 /* looks like a basket case, as no child ever fully initialized; give up.
2610 shutdown_pending = 1;
2612 ap_log_error(APLOG_MARK, APLOG_ALERT, 0,
2613 ap_server_conf, APLOGNO(02324)
2614 "A resource shortage or other unrecoverable failure "
2615 "was encountered before any child process initialized "
2616 "successfully... httpd is exiting!");
2617 /* the child already logged the failure details */
2622 retained->max_daemons_limit = last_non_dead + 1;
2624 if (idle_thread_count > max_spare_threads / num_buckets) {
2625 /* Kill off one child */
2626 ap_mpm_podx_signal(all_buckets[child_bucket].pod,
2627 AP_MPM_PODX_GRACEFUL);
2628 retained->idle_spawn_rate[child_bucket] = 1;
2630 else if (idle_thread_count < min_spare_threads / num_buckets) {
2631 /* terminate the free list */
2632 if (free_length == 0) { /* scoreboard is full, can't fork */
2634 if (active_thread_count >= ap_daemons_limit * threads_per_child) {
2635 if (!retained->maxclients_reported) {
2636 /* only report this condition once */
2637 ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, APLOGNO(00484)
2638 "server reached MaxRequestWorkers setting, "
2639 "consider raising the MaxRequestWorkers "
2641 retained->maxclients_reported = 1;
2645 ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, APLOGNO(00485)
2646 "scoreboard is full, not at MaxRequestWorkers");
2648 retained->idle_spawn_rate[child_bucket] = 1;
2651 if (free_length > retained->idle_spawn_rate[child_bucket]) {
2652 free_length = retained->idle_spawn_rate[child_bucket];
2654 if (retained->idle_spawn_rate[child_bucket] >= 8) {
2655 ap_log_error(APLOG_MARK, APLOG_INFO, 0, ap_server_conf, APLOGNO(00486)
2656 "server seems busy, (you may need "
2657 "to increase StartServers, ThreadsPerChild "
2658 "or Min/MaxSpareThreads), "
2659 "spawning %d children, there are around %d idle "
2660 "threads, and %d total children", free_length,
2661 idle_thread_count, total_non_dead);
2663 for (i = 0; i < free_length; ++i) {
2664 make_child(ap_server_conf, free_slots[i], child_bucket);
2666 /* the next time around we want to spawn twice as many if this
2667 * wasn't good enough, but not if we've just done a graceful
2669 if (retained->hold_off_on_exponential_spawning) {
2670 --retained->hold_off_on_exponential_spawning;
2672 else if (retained->idle_spawn_rate[child_bucket]
2673 < MAX_SPAWN_RATE / num_buckets) {
2674 retained->idle_spawn_rate[child_bucket] *= 2;
2679 retained->idle_spawn_rate[child_bucket] = 1;
2683 static void server_main_loop(int remaining_children_to_start, int num_buckets)
2685 ap_generation_t old_gen;
2687 apr_exit_why_e exitwhy;
2688 int status, processed_status;
2692 while (!restart_pending && !shutdown_pending) {
2693 ap_wait_or_timeout(&exitwhy, &status, &pid, pconf, ap_server_conf);
2695 if (pid.pid != -1) {
2696 processed_status = ap_process_child_status(&pid, exitwhy, status);
2697 child_slot = ap_find_child_by_pid(&pid);
2698 if (processed_status == APEXIT_CHILDFATAL) {
2699 /* fix race condition found in PR 39311
2700 * A child created at the same time as a graceful happens
2701 * can find the lock missing and create a fatal error.
2702 * It is not fatal for the last generation to be in this state.
2705 || ap_get_scoreboard_process(child_slot)->generation
2706 == retained->my_generation) {
2707 shutdown_pending = 1;
2712 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ap_server_conf, APLOGNO(00487)
2713 "Ignoring fatal error in child of previous "
2714 "generation (pid %ld).",
2716 retained->sick_child_detected = 1;
2719 else if (processed_status == APEXIT_CHILDSICK) {
2720 /* tell perform_idle_server_maintenance to check into this
2721 * on the next timer pop
2723 retained->sick_child_detected = 1;
2725 /* non-fatal death... note that it's gone in the scoreboard. */
2726 if (child_slot >= 0) {
2729 for (i = 0; i < threads_per_child; i++)
2730 ap_update_child_status_from_indexes(child_slot, i,
2732 (request_rec *) NULL);
2734 event_note_child_killed(child_slot, 0, 0);
2735 ps = &ap_scoreboard_image->parent[child_slot];
2737 if (processed_status == APEXIT_CHILDSICK) {
2738 /* resource shortage, minimize the fork rate */
2739 retained->idle_spawn_rate[ps->bucket] = 1;
2741 else if (remaining_children_to_start
2742 && child_slot < ap_daemons_limit) {
2743 /* we're still doing a 1-for-1 replacement of dead
2744 * children with new children
2746 make_child(ap_server_conf, child_slot, ps->bucket);
2747 --remaining_children_to_start;
2750 else if (ap_unregister_extra_mpm_process(pid.pid, &old_gen) == 1) {
2752 event_note_child_killed(-1, /* already out of the scoreboard */
2754 if (processed_status == APEXIT_CHILDSICK
2755 && old_gen == retained->my_generation) {
2756 /* resource shortage, minimize the fork rate */
2757 for (i = 0; i < num_buckets; i++) {
2758 retained->idle_spawn_rate[i] = 1;
2761 #if APR_HAS_OTHER_CHILD
2763 else if (apr_proc_other_child_alert(&pid, APR_OC_REASON_DEATH,
2768 else if (retained->is_graceful) {
2769 /* Great, we've probably just lost a slot in the
2770 * scoreboard. Somehow we don't know about this child.
2772 ap_log_error(APLOG_MARK, APLOG_WARNING, 0,
2773 ap_server_conf, APLOGNO(00488)
2774 "long lost child came home! (pid %ld)",
2777 /* Don't perform idle maintenance when a child dies,
2778 * only do it when there's a timeout. Remember only a
2779 * finite number of children can die, and it's pretty
2780 * pathological for a lot to die suddenly.
2784 else if (remaining_children_to_start) {
2785 /* we hit a 1 second timeout in which none of the previous
2786 * generation of children needed to be reaped... so assume
2787 * they're all done, and pick up the slack if any is left.
2789 startup_children(remaining_children_to_start);
2790 remaining_children_to_start = 0;
2791 /* In any event we really shouldn't do the code below because
2792 * few of the servers we just started are in the IDLE state
2793 * yet, so we'd mistakenly create an extra server.
2798 for (i = 0; i < num_buckets; i++) {
2799 perform_idle_server_maintenance(i, num_buckets);
2804 static int event_run(apr_pool_t * _pconf, apr_pool_t * plog, server_rec * s)
2806 int num_buckets = retained->num_buckets;
2807 int remaining_children_to_start;
2810 ap_log_pid(pconf, ap_pid_fname);
2812 if (!retained->is_graceful) {
2813 if (ap_run_pre_mpm(s->process->pool, SB_SHARED) != OK) {
2814 mpm_state = AP_MPMQ_STOPPING;
2817 /* fix the generation number in the global score; we just got a new,
2818 * cleared scoreboard
2820 ap_scoreboard_image->global->running_generation = retained->my_generation;
2823 restart_pending = shutdown_pending = 0;
2826 /* Don't thrash since num_buckets depends on the
2827 * system and the number of online CPU cores...
2829 if (ap_daemons_limit < num_buckets)
2830 ap_daemons_limit = num_buckets;
2831 if (ap_daemons_to_start < num_buckets)
2832 ap_daemons_to_start = num_buckets;
2833 if (min_spare_threads < threads_per_child * num_buckets)
2834 min_spare_threads = threads_per_child * num_buckets;
2835 if (max_spare_threads < min_spare_threads + threads_per_child * num_buckets)
2836 max_spare_threads = min_spare_threads + threads_per_child * num_buckets;
2838 /* If we're doing a graceful_restart then we're going to see a lot
2839 * of children exiting immediately when we get into the main loop
2840 * below (because we just sent them AP_SIG_GRACEFUL). This happens pretty
2841 * rapidly... and for each one that exits we may start a new one, until
2842 * there are at least min_spare_threads idle threads, counting across
2843 * all children. But we may be permitted to start more children than
2844 * that, so we'll just keep track of how many we're
2845 * supposed to start up without the 1 second penalty between each fork.
2847 remaining_children_to_start = ap_daemons_to_start;
2848 if (remaining_children_to_start > ap_daemons_limit) {
2849 remaining_children_to_start = ap_daemons_limit;
2851 if (!retained->is_graceful) {
2852 startup_children(remaining_children_to_start);
2853 remaining_children_to_start = 0;
2856 /* give the system some time to recover before kicking into
2857 * exponential mode */
2858 retained->hold_off_on_exponential_spawning = 10;
2861 ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, APLOGNO(00489)
2862 "%s configured -- resuming normal operations",
2863 ap_get_server_description());
2864 ap_log_error(APLOG_MARK, APLOG_INFO, 0, ap_server_conf, APLOGNO(00490)
2865 "Server built: %s", ap_get_server_built());
2866 ap_log_command_line(plog, s);
2867 ap_log_mpm_common(s);
2869 mpm_state = AP_MPMQ_RUNNING;
2871 server_main_loop(remaining_children_to_start, num_buckets);
2872 mpm_state = AP_MPMQ_STOPPING;
2874 if (shutdown_pending && !retained->is_graceful) {
2875 /* Time to shut down:
2876 * Kill child processes, tell them to call child_exit, etc...
2878 for (i = 0; i < num_buckets; i++) {
2879 ap_mpm_podx_killpg(all_buckets[i].pod, ap_daemons_limit,
2880 AP_MPM_PODX_RESTART);
2882 ap_reclaim_child_processes(1, /* Start with SIGTERM */
2883 event_note_child_killed);
2886 /* cleanup pid file on normal shutdown */
2887 ap_remove_pid(pconf, ap_pid_fname);
2888 ap_log_error(APLOG_MARK, APLOG_NOTICE, 0,
2889 ap_server_conf, APLOGNO(00491) "caught SIGTERM, shutting down");
2892 } else if (shutdown_pending) {
2893 /* Time to gracefully shut down:
2894 * Kill child processes, tell them to call child_exit, etc...
2896 int active_children;
2898 apr_time_t cutoff = 0;
2900 /* Close our listeners, and then ask our children to do same */
2901 ap_close_listeners();
2902 for (i = 0; i < num_buckets; i++) {
2903 ap_mpm_podx_killpg(all_buckets[i].pod, ap_daemons_limit,
2904 AP_MPM_PODX_GRACEFUL);
2906 ap_relieve_child_processes(event_note_child_killed);
2909 /* cleanup pid file on normal shutdown */
2910 ap_remove_pid(pconf, ap_pid_fname);
2911 ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, APLOGNO(00492)
2912 "caught " AP_SIG_GRACEFUL_STOP_STRING
2913 ", shutting down gracefully");
2916 if (ap_graceful_shutdown_timeout) {
2917 cutoff = apr_time_now() +
2918 apr_time_from_sec(ap_graceful_shutdown_timeout);
2921 /* Don't really exit until each child has finished */
2922 shutdown_pending = 0;
2924 /* Pause for a second */
2925 apr_sleep(apr_time_from_sec(1));
2927 /* Relieve any children which have now exited */
2928 ap_relieve_child_processes(event_note_child_killed);
2930 active_children = 0;
2931 for (index = 0; index < ap_daemons_limit; ++index) {
2932 if (ap_mpm_safe_kill(MPM_CHILD_PID(index), 0) == APR_SUCCESS) {
2933 active_children = 1;
2934 /* Having just one child is enough to stay around */
2938 } while (!shutdown_pending && active_children &&
2939 (!ap_graceful_shutdown_timeout || apr_time_now() < cutoff));
2941 /* We might be here because we received SIGTERM, either
2942 * way, try and make sure that all of our processes are
2945 for (i = 0; i < num_buckets; i++) {
2946 ap_mpm_podx_killpg(all_buckets[i].pod, ap_daemons_limit,
2947 AP_MPM_PODX_RESTART);
2949 ap_reclaim_child_processes(1, event_note_child_killed);
2954 /* we've been told to restart */
2955 apr_signal(SIGHUP, SIG_IGN);
2958 /* not worth thinking about */
2962 /* advance to the next generation */
2963 /* XXX: we really need to make sure this new generation number isn't in
2964 * use by any of the children.
2966 ++retained->my_generation;
2967 ap_scoreboard_image->global->running_generation = retained->my_generation;
2969 if (retained->is_graceful) {
2970 ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, APLOGNO(00493)
2971 AP_SIG_GRACEFUL_STRING
2972 " received. Doing graceful restart");
2973 /* wake up the children...time to die. But we'll have more soon */
2974 for (i = 0; i < num_buckets; i++) {
2975 ap_mpm_podx_killpg(all_buckets[i].pod, ap_daemons_limit,
2976 AP_MPM_PODX_GRACEFUL);
2979 /* This is mostly for debugging... so that we know what is still
2980 * gracefully dealing with existing request.
2985 /* Kill 'em all. Since the child acts the same on the parents SIGTERM
2986 * and a SIGHUP, we may as well use the same signal, because some user
2987 * pthreads are stealing signals from us left and right.
2989 for (i = 0; i < num_buckets; i++) {
2990 ap_mpm_podx_killpg(all_buckets[i].pod, ap_daemons_limit,
2991 AP_MPM_PODX_RESTART);
2994 ap_reclaim_child_processes(1, /* Start with SIGTERM */
2995 event_note_child_killed);
2996 ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, APLOGNO(00494)
2997 "SIGHUP received. Attempting to restart");
3003 /* This really should be a post_config hook, but the error log is already
3004 * redirected by that point, so we need to do this in the open_logs phase.
3006 static int event_open_logs(apr_pool_t * p, apr_pool_t * plog,
3007 apr_pool_t * ptemp, server_rec * s)
3010 int level_flags = 0;
3011 int num_buckets = 0;
3012 ap_listen_rec **listen_buckets;
3018 /* the reverse of pre_config, we want this only the first time around */
3019 if (retained->module_loads == 1) {
3021 level_flags |= APLOG_STARTUP;
3024 if ((num_listensocks = ap_setup_listeners(ap_server_conf)) < 1) {
3025 ap_log_error(APLOG_MARK, APLOG_ALERT | level_flags, 0,
3026 (startup ? NULL : s),
3027 "no listening sockets available, shutting down");
3034 else if (retained->is_graceful) {
3035 /* Preserve the number of buckets on graceful restarts. */
3036 num_buckets = retained->num_buckets;
3038 if ((rv = ap_duplicate_listeners(pconf, ap_server_conf,
3039 &listen_buckets, &num_buckets))) {
3040 ap_log_error(APLOG_MARK, APLOG_CRIT | level_flags, rv,
3041 (startup ? NULL : s),
3042 "could not duplicate listeners");
3046 all_buckets = apr_pcalloc(pconf, num_buckets * sizeof(*all_buckets));
3047 for (i = 0; i < num_buckets; i++) {
3048 if (!one_process && /* no POD in one_process mode */
3049 (rv = ap_mpm_podx_open(pconf, &all_buckets[i].pod))) {
3050 ap_log_error(APLOG_MARK, APLOG_CRIT | level_flags, rv,
3051 (startup ? NULL : s),
3052 "could not open pipe-of-death");
3055 all_buckets[i].listeners = listen_buckets[i];
3058 if (retained->max_buckets < num_buckets) {
3059 int new_max, *new_ptr;
3060 new_max = retained->max_buckets * 2;
3061 if (new_max < num_buckets) {
3062 new_max = num_buckets;
3064 new_ptr = (int *)apr_palloc(ap_pglobal, new_max * sizeof(int));
3065 memcpy(new_ptr, retained->idle_spawn_rate,
3066 retained->num_buckets * sizeof(int));
3067 retained->idle_spawn_rate = new_ptr;
3068 retained->max_buckets = new_max;
3070 if (retained->num_buckets < num_buckets) {
3072 /* If new buckets are added, set their idle spawn rate to
3073 * the highest so far, so that they get filled as quickly
3074 * as the existing ones.
3076 for (i = 0; i < retained->num_buckets; i++) {
3077 if (rate_max < retained->idle_spawn_rate[i]) {
3078 rate_max = retained->idle_spawn_rate[i];
3081 for (/* up to date i */; i < num_buckets; i++) {
3082 retained->idle_spawn_rate[i] = rate_max;
3085 retained->num_buckets = num_buckets;
3088 srand((unsigned int)apr_time_now());
3092 static int event_pre_config(apr_pool_t * pconf, apr_pool_t * plog,
3095 int no_detach, debug, foreground;
3097 const char *userdata_key = "mpm_event_module";
3099 mpm_state = AP_MPMQ_STARTING;
3101 debug = ap_exists_config_define("DEBUG");
3104 foreground = one_process = 1;
3108 one_process = ap_exists_config_define("ONE_PROCESS");
3109 no_detach = ap_exists_config_define("NO_DETACH");
3110 foreground = ap_exists_config_define("FOREGROUND");
3113 /* sigh, want this only the second time around */
3114 retained = ap_retained_data_get(userdata_key);
3116 retained = ap_retained_data_create(userdata_key, sizeof(*retained));
3117 retained->max_daemons_limit = -1;
3119 ++retained->module_loads;
3120 if (retained->module_loads == 2) {
3121 /* test for correct operation of fdqueue */
3122 static apr_uint32_t foo1, foo2;
3124 apr_atomic_set32(&foo1, 100);
3125 foo2 = apr_atomic_add32(&foo1, -10);
3126 if (foo2 != 100 || foo1 != 90) {
3127 ap_log_error(APLOG_MARK, APLOG_CRIT, 0, NULL, APLOGNO(02405)
3128 "atomics not working as expected - add32 of negative number");
3129 return HTTP_INTERNAL_SERVER_ERROR;
3132 rv = apr_pollset_create(&event_pollset, 1, plog,
3133 APR_POLLSET_THREADSAFE | APR_POLLSET_NOCOPY);
3134 if (rv != APR_SUCCESS) {
3135 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL, APLOGNO(00495)
3136 "Couldn't create a Thread Safe Pollset. "
3137 "Is it supported on your platform?"
3138 "Also check system or user limits!");
3139 return HTTP_INTERNAL_SERVER_ERROR;
3141 apr_pollset_destroy(event_pollset);
3143 if (!one_process && !foreground) {
3144 /* before we detach, setup crash handlers to log to errorlog */
3145 ap_fatal_signal_setup(ap_server_conf, pconf);
3146 rv = apr_proc_detach(no_detach ? APR_PROC_DETACH_FOREGROUND
3147 : APR_PROC_DETACH_DAEMONIZE);
3148 if (rv != APR_SUCCESS) {
3149 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL, APLOGNO(00496)
3150 "apr_proc_detach failed");
3151 return HTTP_INTERNAL_SERVER_ERROR;
3156 parent_pid = ap_my_pid = getpid();
3158 ap_listen_pre_config();
3159 ap_daemons_to_start = DEFAULT_START_DAEMON;
3160 min_spare_threads = DEFAULT_MIN_FREE_DAEMON * DEFAULT_THREADS_PER_CHILD;
3161 max_spare_threads = DEFAULT_MAX_FREE_DAEMON * DEFAULT_THREADS_PER_CHILD;
3162 server_limit = DEFAULT_SERVER_LIMIT;
3163 thread_limit = DEFAULT_THREAD_LIMIT;
3164 ap_daemons_limit = server_limit;
3165 threads_per_child = DEFAULT_THREADS_PER_CHILD;
3166 max_workers = ap_daemons_limit * threads_per_child;
3167 had_healthy_child = 0;
3168 ap_extended_status = 0;
3173 static int event_post_config(apr_pool_t *pconf, apr_pool_t *plog,
3174 apr_pool_t *ptemp, server_rec *s)
3177 struct timeout_queue *tail, *q;
3181 /* Not needed in pre_config stage */
3182 if (ap_state_query(AP_SQ_MAIN_STATE) == AP_SQ_MS_CREATE_PRE_CONFIG) {
3186 wc.tail = ka.tail = NULL;
3187 wc.hash = apr_hash_make(ptemp);
3188 ka.hash = apr_hash_make(ptemp);
3190 TO_QUEUE_INIT(linger_q, pconf,
3191 apr_time_from_sec(MAX_SECS_TO_LINGER), NULL);
3192 TO_QUEUE_INIT(short_linger_q, pconf,
3193 apr_time_from_sec(SECONDS_TO_LINGER), NULL);
3195 for (; s; s = s->next) {
3196 event_srv_cfg *sc = apr_pcalloc(pconf, sizeof *sc);
3198 ap_set_module_config(s->module_config, &mpm_event_module, sc);
3200 /* The main server uses the global queues */
3201 TO_QUEUE_INIT(wc.q, pconf, s->timeout, NULL);
3202 apr_hash_set(wc.hash, &s->timeout, sizeof s->timeout, wc.q);
3203 wc.tail = write_completion_q = wc.q;
3205 TO_QUEUE_INIT(ka.q, pconf, s->keep_alive_timeout, NULL);
3206 apr_hash_set(ka.hash, &s->keep_alive_timeout,
3207 sizeof s->keep_alive_timeout, ka.q);
3208 ka.tail = keepalive_q = ka.q;
3211 /* The vhosts use any existing queue with the same timeout,
3212 * or their own queue(s) if there isn't */
3213 wc.q = apr_hash_get(wc.hash, &s->timeout, sizeof s->timeout);
3215 TO_QUEUE_INIT(wc.q, pconf, s->timeout, wc.tail);
3216 apr_hash_set(wc.hash, &s->timeout, sizeof s->timeout, wc.q);
3217 wc.tail = wc.tail->next = wc.q;
3220 ka.q = apr_hash_get(ka.hash, &s->keep_alive_timeout,
3221 sizeof s->keep_alive_timeout);
3223 TO_QUEUE_INIT(ka.q, pconf, s->keep_alive_timeout, ka.tail);
3224 apr_hash_set(ka.hash, &s->keep_alive_timeout,
3225 sizeof s->keep_alive_timeout, ka.q);
3226 ka.tail = ka.tail->next = ka.q;
3236 static int event_check_config(apr_pool_t *p, apr_pool_t *plog,
3237 apr_pool_t *ptemp, server_rec *s)
3241 /* the reverse of pre_config, we want this only the first time around */
3242 if (retained->module_loads == 1) {
3246 if (server_limit > MAX_SERVER_LIMIT) {
3248 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00497)
3249 "WARNING: ServerLimit of %d exceeds compile-time "
3250 "limit of", server_limit);
3251 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(03105)
3252 " %d servers, decreasing to %d.",
3253 MAX_SERVER_LIMIT, MAX_SERVER_LIMIT);
3255 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00498)
3256 "ServerLimit of %d exceeds compile-time limit "
3257 "of %d, decreasing to match",
3258 server_limit, MAX_SERVER_LIMIT);
3260 server_limit = MAX_SERVER_LIMIT;
3262 else if (server_limit < 1) {
3264 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00499)
3265 "WARNING: ServerLimit of %d not allowed, "
3266 "increasing to 1.", server_limit);
3268 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00500)
3269 "ServerLimit of %d not allowed, increasing to 1",
3275 /* you cannot change ServerLimit across a restart; ignore
3278 if (!retained->first_server_limit) {
3279 retained->first_server_limit = server_limit;
3281 else if (server_limit != retained->first_server_limit) {
3282 /* don't need a startup console version here */
3283 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00501)
3284 "changing ServerLimit to %d from original value of %d "
3285 "not allowed during restart",
3286 server_limit, retained->first_server_limit);
3287 server_limit = retained->first_server_limit;
3290 if (thread_limit > MAX_THREAD_LIMIT) {
3292 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00502)
3293 "WARNING: ThreadLimit of %d exceeds compile-time "
3294 "limit of", thread_limit);
3295 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(03106)
3296 " %d threads, decreasing to %d.",
3297 MAX_THREAD_LIMIT, MAX_THREAD_LIMIT);
3299 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00503)
3300 "ThreadLimit of %d exceeds compile-time limit "
3301 "of %d, decreasing to match",
3302 thread_limit, MAX_THREAD_LIMIT);
3304 thread_limit = MAX_THREAD_LIMIT;
3306 else if (thread_limit < 1) {
3308 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00504)
3309 "WARNING: ThreadLimit of %d not allowed, "
3310 "increasing to 1.", thread_limit);
3312 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00505)
3313 "ThreadLimit of %d not allowed, increasing to 1",
3319 /* you cannot change ThreadLimit across a restart; ignore
3322 if (!retained->first_thread_limit) {
3323 retained->first_thread_limit = thread_limit;
3325 else if (thread_limit != retained->first_thread_limit) {
3326 /* don't need a startup console version here */
3327 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00506)
3328 "changing ThreadLimit to %d from original value of %d "
3329 "not allowed during restart",
3330 thread_limit, retained->first_thread_limit);
3331 thread_limit = retained->first_thread_limit;
3334 if (threads_per_child > thread_limit) {
3336 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00507)
3337 "WARNING: ThreadsPerChild of %d exceeds ThreadLimit "
3338 "of", threads_per_child);
3339 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(03107)
3340 " %d threads, decreasing to %d.",
3341 thread_limit, thread_limit);
3342 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(03108)
3343 " To increase, please see the ThreadLimit "
3346 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00508)
3347 "ThreadsPerChild of %d exceeds ThreadLimit "
3348 "of %d, decreasing to match",
3349 threads_per_child, thread_limit);
3351 threads_per_child = thread_limit;
3353 else if (threads_per_child < 1) {
3355 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00509)
3356 "WARNING: ThreadsPerChild of %d not allowed, "
3357 "increasing to 1.", threads_per_child);
3359 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00510)
3360 "ThreadsPerChild of %d not allowed, increasing to 1",
3363 threads_per_child = 1;
3366 if (max_workers < threads_per_child) {
3368 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00511)
3369 "WARNING: MaxRequestWorkers of %d is less than "
3370 "ThreadsPerChild of", max_workers);
3371 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(03109)
3372 " %d, increasing to %d. MaxRequestWorkers must be at "
3374 threads_per_child, threads_per_child);
3375 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(03110)
3376 " as the number of threads in a single server.");
3378 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00512)
3379 "MaxRequestWorkers of %d is less than ThreadsPerChild "
3380 "of %d, increasing to match",
3381 max_workers, threads_per_child);
3383 max_workers = threads_per_child;
3386 ap_daemons_limit = max_workers / threads_per_child;
3388 if (max_workers % threads_per_child) {
3389 int tmp_max_workers = ap_daemons_limit * threads_per_child;
3392 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00513)
3393 "WARNING: MaxRequestWorkers of %d is not an integer "
3394 "multiple of", max_workers);
3395 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(03111)
3396 " ThreadsPerChild of %d, decreasing to nearest "
3397 "multiple %d,", threads_per_child,
3399 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(03112)
3400 " for a maximum of %d servers.",
3403 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00514)
3404 "MaxRequestWorkers of %d is not an integer multiple "
3405 "of ThreadsPerChild of %d, decreasing to nearest "
3406 "multiple %d", max_workers, threads_per_child,
3409 max_workers = tmp_max_workers;
3412 if (ap_daemons_limit > server_limit) {
3414 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00515)
3415 "WARNING: MaxRequestWorkers of %d would require %d "
3416 "servers and ", max_workers, ap_daemons_limit);
3417 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(03113)
3418 " would exceed ServerLimit of %d, decreasing to %d.",
3419 server_limit, server_limit * threads_per_child);
3420 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(03114)
3421 " To increase, please see the ServerLimit "
3424 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00516)
3425 "MaxRequestWorkers of %d would require %d servers and "
3426 "exceed ServerLimit of %d, decreasing to %d",
3427 max_workers, ap_daemons_limit, server_limit,
3428 server_limit * threads_per_child);
3430 ap_daemons_limit = server_limit;
3433 /* ap_daemons_to_start > ap_daemons_limit checked in ap_mpm_run() */
3434 if (ap_daemons_to_start < 1) {
3436 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00517)
3437 "WARNING: StartServers of %d not allowed, "
3438 "increasing to 1.", ap_daemons_to_start);
3440 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00518)
3441 "StartServers of %d not allowed, increasing to 1",
3442 ap_daemons_to_start);
3444 ap_daemons_to_start = 1;
3447 if (min_spare_threads < 1) {
3449 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00519)
3450 "WARNING: MinSpareThreads of %d not allowed, "
3451 "increasing to 1", min_spare_threads);
3452 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(03115)
3453 " to avoid almost certain server failure.");
3454 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(03116)
3455 " Please read the documentation.");
3457 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00520)
3458 "MinSpareThreads of %d not allowed, increasing to 1",
3461 min_spare_threads = 1;
3464 /* max_spare_threads < min_spare_threads + threads_per_child
3465 * checked in ap_mpm_run()
3471 static void event_hooks(apr_pool_t * p)
3473 /* Our open_logs hook function must run before the core's, or stderr
3474 * will be redirected to a file, and the messages won't print to the
3477 static const char *const aszSucc[] = { "core.c", NULL };
3480 ap_hook_open_logs(event_open_logs, NULL, aszSucc, APR_HOOK_REALLY_FIRST);
3481 /* we need to set the MPM state before other pre-config hooks use MPM query
3482 * to retrieve it, so register as REALLY_FIRST
3484 ap_hook_pre_config(event_pre_config, NULL, NULL, APR_HOOK_REALLY_FIRST);
3485 ap_hook_post_config(event_post_config, NULL, NULL, APR_HOOK_MIDDLE);
3486 ap_hook_check_config(event_check_config, NULL, NULL, APR_HOOK_MIDDLE);
3487 ap_hook_mpm(event_run, NULL, NULL, APR_HOOK_MIDDLE);
3488 ap_hook_mpm_query(event_query, NULL, NULL, APR_HOOK_MIDDLE);
3489 ap_hook_mpm_register_timed_callback(event_register_timed_callback, NULL, NULL,
3491 ap_hook_pre_read_request(event_pre_read_request, NULL, NULL, APR_HOOK_MIDDLE);
3492 ap_hook_post_read_request(event_post_read_request, NULL, NULL, APR_HOOK_MIDDLE);
3493 ap_hook_mpm_get_name(event_get_name, NULL, NULL, APR_HOOK_MIDDLE);
3496 static const char *set_daemons_to_start(cmd_parms *cmd, void *dummy,
3499 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3504 ap_daemons_to_start = atoi(arg);
3508 static const char *set_min_spare_threads(cmd_parms * cmd, void *dummy,
3511 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3516 min_spare_threads = atoi(arg);
3520 static const char *set_max_spare_threads(cmd_parms * cmd, void *dummy,
3523 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3528 max_spare_threads = atoi(arg);
3532 static const char *set_max_workers(cmd_parms * cmd, void *dummy,
3535 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3539 if (!strcasecmp(cmd->cmd->name, "MaxClients")) {
3540 ap_log_error(APLOG_MARK, APLOG_INFO, 0, NULL, APLOGNO(00521)
3541 "MaxClients is deprecated, use MaxRequestWorkers "
3544 max_workers = atoi(arg);
3548 static const char *set_threads_per_child(cmd_parms * cmd, void *dummy,
3551 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3556 threads_per_child = atoi(arg);
3559 static const char *set_server_limit (cmd_parms *cmd, void *dummy, const char *arg)
3561 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3566 server_limit = atoi(arg);
3570 static const char *set_thread_limit(cmd_parms * cmd, void *dummy,
3573 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3578 thread_limit = atoi(arg);
3582 static const char *set_worker_factor(cmd_parms * cmd, void *dummy,
3587 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3592 val = strtod(arg, &endptr);
3594 return "error parsing value";
3597 return "AsyncRequestWorkerFactor argument must be a positive number";
3599 worker_factor = val * WORKER_FACTOR_SCALE;
3600 if (worker_factor == 0)
3606 static const command_rec event_cmds[] = {
3608 AP_INIT_TAKE1("StartServers", set_daemons_to_start, NULL, RSRC_CONF,
3609 "Number of child processes launched at server startup"),
3610 AP_INIT_TAKE1("ServerLimit", set_server_limit, NULL, RSRC_CONF,
3611 "Maximum number of child processes for this run of Apache"),
3612 AP_INIT_TAKE1("MinSpareThreads", set_min_spare_threads, NULL, RSRC_CONF,
3613 "Minimum number of idle threads, to handle request spikes"),
3614 AP_INIT_TAKE1("MaxSpareThreads", set_max_spare_threads, NULL, RSRC_CONF,
3615 "Maximum number of idle threads"),
3616 AP_INIT_TAKE1("MaxClients", set_max_workers, NULL, RSRC_CONF,
3617 "Deprecated name of MaxRequestWorkers"),
3618 AP_INIT_TAKE1("MaxRequestWorkers", set_max_workers, NULL, RSRC_CONF,
3619 "Maximum number of threads alive at the same time"),
3620 AP_INIT_TAKE1("ThreadsPerChild", set_threads_per_child, NULL, RSRC_CONF,
3621 "Number of threads each child creates"),
3622 AP_INIT_TAKE1("ThreadLimit", set_thread_limit, NULL, RSRC_CONF,
3623 "Maximum number of worker threads per child process for this "
3624 "run of Apache - Upper limit for ThreadsPerChild"),
3625 AP_INIT_TAKE1("AsyncRequestWorkerFactor", set_worker_factor, NULL, RSRC_CONF,
3626 "How many additional connects will be accepted per idle "
3628 AP_GRACEFUL_SHUTDOWN_TIMEOUT_COMMAND,
3632 AP_DECLARE_MODULE(mpm_event) = {
3634 NULL, /* hook to run before apache parses args */
3635 NULL, /* create per-directory config structure */
3636 NULL, /* merge per-directory config structures */
3637 NULL, /* create per-server config structure */
3638 NULL, /* merge per-server config structures */
3639 event_cmds, /* command apr_table_t */
3640 event_hooks /* register_hooks */