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;
163 /* AsyncRequestWorkerFactor * 16 */
165 static int threads_per_child = 0; /* ThreadsPerChild */
166 static int ap_daemons_to_start = 0; /* StartServers */
167 static int min_spare_threads = 0; /* MinSpareThreads */
168 static int max_spare_threads = 0; /* MaxSpareThreads */
169 static int active_daemons_limit = 0; /* MaxRequestWorkers / ThreadsPerChild */
170 static int active_daemons = 0; /* workers that still active, i.e. are
171 not shutting down gracefully */
172 static int max_workers = 0; /* MaxRequestWorkers */
173 static int server_limit = 0; /* ServerLimit */
174 static int thread_limit = 0; /* ThreadLimit */
175 static int had_healthy_child = 0;
176 static int dying = 0;
177 static int workers_may_exit = 0;
178 static int start_thread_may_exit = 0;
179 static int listener_may_exit = 0;
180 static int listener_is_wakeable = 0; /* Pollset supports APR_POLLSET_WAKEABLE */
181 static int num_listensocks = 0;
182 static apr_int32_t conns_this_child; /* MaxConnectionsPerChild, only access
183 in listener thread */
184 static apr_uint32_t connection_count = 0; /* Number of open connections */
185 static apr_uint32_t lingering_count = 0; /* Number of connections in lingering close */
186 static apr_uint32_t suspended_count = 0; /* Number of suspended connections */
187 static apr_uint32_t clogged_count = 0; /* Number of threads processing ssl conns */
188 static apr_uint32_t threads_shutdown = 0; /* Number of threads that have shutdown
189 early during graceful termination */
190 static int resource_shortage = 0;
191 static fd_queue_t *worker_queue;
192 static fd_queue_info_t *worker_queue_info;
194 static apr_thread_mutex_t *timeout_mutex;
196 module AP_MODULE_DECLARE_DATA mpm_event_module;
198 /* forward declare */
199 struct event_srv_cfg_s;
200 typedef struct event_srv_cfg_s event_srv_cfg;
202 static apr_pollfd_t *listener_pollfd;
205 * The pollset for sockets that are in any of the timeout queues. Currently
206 * we use the timeout_mutex to make sure that connections are added/removed
207 * atomically to/from both event_pollset and a timeout queue. Otherwise
208 * some confusion can happen under high load if timeout queues and pollset
210 * XXX: It should be possible to make the lock unnecessary in many or even all
213 static apr_pollset_t *event_pollset;
216 * The chain of connections to be shutdown by a worker thread (deferred),
217 * linked list updated atomically.
219 static event_conn_state_t *volatile defer_linger_chain;
221 struct event_conn_state_t {
222 /** APR_RING of expiration timeouts */
223 APR_RING_ENTRY(event_conn_state_t) timeout_list;
224 /** the time when the entry was queued */
225 apr_time_t queue_timestamp;
226 /** connection record this struct refers to */
228 /** request record (if any) this struct refers to */
230 /** server config this struct refers to */
232 /** is the current conn_rec suspended? (disassociated with
233 * a particular MPM thread; for suspend_/resume_connection
237 /** memory pool to allocate from */
239 /** bucket allocator */
240 apr_bucket_alloc_t *bucket_alloc;
241 /** poll file descriptor information */
243 /** public parts of the connection state */
245 /** chaining in defer_linger_chain */
246 struct event_conn_state_t *chain;
249 APR_RING_HEAD(timeout_head_t, event_conn_state_t);
251 struct timeout_queue {
252 struct timeout_head_t head;
253 apr_interval_time_t timeout;
254 apr_uint32_t count; /* for this queue */
255 apr_uint32_t *total; /* for all chained/related queues */
256 struct timeout_queue *next; /* chaining */
259 * Several timeout queues that use different timeouts, so that we always can
260 * simply append to the end.
261 * write_completion_q uses vhost's TimeOut
262 * keepalive_q uses vhost's KeepAliveTimeOut
263 * linger_q uses MAX_SECS_TO_LINGER
264 * short_linger_q uses SECONDS_TO_LINGER
266 static struct timeout_queue *write_completion_q,
270 static volatile apr_time_t queues_next_expiry;
272 /* Prevent extra poll/wakeup calls for timeouts close in the future (queues
273 * have the granularity of a second anyway).
274 * XXX: Wouldn't 0.5s (instead of 0.1s) be "enough"?
276 #define TIMEOUT_FUDGE_FACTOR apr_time_from_msec(100)
279 * Macros for accessing struct timeout_queue.
280 * For TO_QUEUE_APPEND and TO_QUEUE_REMOVE, timeout_mutex must be held.
282 static void TO_QUEUE_APPEND(struct timeout_queue *q, event_conn_state_t *el)
285 apr_time_t next_expiry;
287 APR_RING_INSERT_TAIL(&q->head, el, event_conn_state_t, timeout_list);
288 apr_atomic_inc32(q->total);
291 /* Cheaply update the overall queues' next expiry according to the
292 * first entry of this queue (oldest), if necessary.
294 el = APR_RING_FIRST(&q->head);
295 q_expiry = el->queue_timestamp + q->timeout;
296 next_expiry = queues_next_expiry;
297 if (!next_expiry || next_expiry > q_expiry + TIMEOUT_FUDGE_FACTOR) {
298 queues_next_expiry = q_expiry;
299 /* Unblock the poll()ing listener for it to update its timeout. */
300 if (listener_is_wakeable) {
301 apr_pollset_wakeup(event_pollset);
306 static void TO_QUEUE_REMOVE(struct timeout_queue *q, event_conn_state_t *el)
308 APR_RING_REMOVE(el, timeout_list);
309 APR_RING_ELEM_INIT(el, timeout_list);
310 apr_atomic_dec32(q->total);
314 static struct timeout_queue *TO_QUEUE_MAKE(apr_pool_t *p, apr_time_t t,
315 struct timeout_queue *ref)
317 struct timeout_queue *q;
319 q = apr_pcalloc(p, sizeof *q);
320 APR_RING_INIT(&q->head, event_conn_state_t, timeout_list);
321 q->total = (ref) ? ref->total : apr_pcalloc(p, sizeof *q->total);
327 #define TO_QUEUE_ELEM_INIT(el) \
328 APR_RING_ELEM_INIT((el), timeout_list)
330 /* The structure used to pass unique initialization info to each thread */
333 int pslot; /* process slot */
334 int tslot; /* worker slot of the thread */
337 /* Structure used to pass information to the thread responsible for
338 * creating the rest of the threads.
342 apr_thread_t **threads;
343 apr_thread_t *listener;
345 apr_threadattr_t *threadattr;
358 } listener_poll_type;
360 /* data retained by event across load/unload of the module
361 * allocated on first call to pre-config hook; located on
362 * subsequent calls to pre-config hook
364 typedef struct event_retained_data {
365 ap_unixd_mpm_retained_data *mpm;
367 int first_server_limit;
368 int first_thread_limit;
369 int sick_child_detected;
370 int maxclients_reported;
372 * The max child slot ever assigned, preserved across restarts. Necessary
373 * to deal with MaxRequestWorkers changes across AP_SIG_GRACEFUL restarts.
374 * We use this value to optimize routines that have to scan the entire
377 int max_daemons_limit;
380 * All running workers, active and shutting down, including those that
381 * may be left from before a graceful restart.
382 * Not kept up-to-date when shutdown is pending.
387 * idle_spawn_rate is the number of children that will be spawned on the
388 * next maintenance cycle if there aren't enough idle servers. It is
389 * maintained per listeners bucket, doubled up to MAX_SPAWN_RATE, and
390 * reset only when a cycle goes by without the need to spawn.
392 int *idle_spawn_rate;
393 #ifndef MAX_SPAWN_RATE
394 #define MAX_SPAWN_RATE (32)
396 int hold_off_on_exponential_spawning;
397 } event_retained_data;
398 static event_retained_data *retained;
400 typedef struct event_child_bucket {
402 ap_listen_rec *listeners;
403 } event_child_bucket;
404 static event_child_bucket *all_buckets, /* All listeners buckets */
405 *my_bucket; /* Current child bucket */
407 struct event_srv_cfg_s {
408 struct timeout_queue *wc_q,
412 #define ID_FROM_CHILD_THREAD(c, t) ((c * thread_limit) + t)
414 /* The event MPM respects a couple of runtime flags that can aid
415 * in debugging. Setting the -DNO_DETACH flag will prevent the root process
416 * from detaching from its controlling terminal. Additionally, setting
417 * the -DONE_PROCESS flag (which implies -DNO_DETACH) will get you the
418 * child_main loop running in the process which originally started up.
419 * This gives you a pretty nice debugging environment. (You'll get a SIGHUP
420 * early in standalone_main; just continue through. This is the server
421 * trying to kill off any child processes which it might have lying
422 * around --- Apache doesn't keep track of their pids, it just sends
423 * SIGHUP to the process group, ignoring it in the root process.
424 * Continue through and you'll be fine.).
427 static int one_process = 0;
430 int raise_sigstop_flags;
433 static apr_pool_t *pconf; /* Pool for config stuff */
434 static apr_pool_t *pchild; /* Pool for httpd child stuff */
436 static pid_t ap_my_pid; /* Linux getpid() doesn't work except in main
437 thread. Use this instead */
438 static pid_t parent_pid;
439 static apr_os_thread_t *listener_os_thread;
441 /* The LISTENER_SIGNAL signal will be sent from the main thread to the
442 * listener thread to wake it up for graceful termination (what a child
443 * process from an old generation does when the admin does "apachectl
444 * graceful"). This signal will be blocked in all threads of a child
445 * process except for the listener thread.
447 #define LISTENER_SIGNAL SIGHUP
449 /* An array of socket descriptors in use by each thread used to
450 * perform a non-graceful (forced) shutdown of the server.
452 static apr_socket_t **worker_sockets;
454 static void disable_listensocks(int process_slot)
457 for (i = 0; i < num_listensocks; i++) {
458 apr_pollset_remove(event_pollset, &listener_pollfd[i]);
460 ap_scoreboard_image->parent[process_slot].not_accepting = 1;
463 static void enable_listensocks(int process_slot)
466 if (listener_may_exit) {
469 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(00457)
470 "Accepting new connections again: "
471 "%u active conns (%u lingering/%u clogged/%u suspended), "
473 apr_atomic_read32(&connection_count),
474 apr_atomic_read32(&lingering_count),
475 apr_atomic_read32(&clogged_count),
476 apr_atomic_read32(&suspended_count),
477 ap_queue_info_get_idlers(worker_queue_info));
478 for (i = 0; i < num_listensocks; i++)
479 apr_pollset_add(event_pollset, &listener_pollfd[i]);
481 * XXX: This is not yet optimal. If many workers suddenly become available,
482 * XXX: the parent may kill some processes off too soon.
484 ap_scoreboard_image->parent[process_slot].not_accepting = 0;
487 static void abort_socket_nonblocking(apr_socket_t *csd)
490 apr_socket_timeout_set(csd, 0);
491 #if defined(SOL_SOCKET) && defined(SO_LINGER)
492 /* This socket is over now, and we don't want to block nor linger
493 * anymore, so reset it. A normal close could still linger in the
494 * system, while RST is fast, nonblocking, and what the peer will
495 * get if it sends us further data anyway.
498 apr_os_sock_t osd = -1;
501 opt.l_linger = 0; /* zero timeout is RST */
502 apr_os_sock_get(&osd, csd);
503 setsockopt(osd, SOL_SOCKET, SO_LINGER, (void *)&opt, sizeof opt);
506 rv = apr_socket_close(csd);
507 if (rv != APR_SUCCESS) {
508 ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf, APLOGNO(00468)
509 "error closing socket");
514 static void close_worker_sockets(void)
517 for (i = 0; i < threads_per_child; i++) {
518 apr_socket_t *csd = worker_sockets[i];
520 worker_sockets[i] = NULL;
521 abort_socket_nonblocking(csd);
525 event_conn_state_t *cs = defer_linger_chain;
529 if (apr_atomic_casptr((void *)&defer_linger_chain, cs->chain,
531 /* Race lost, try again */
535 abort_socket_nonblocking(cs->pfd.desc.s);
539 static void wakeup_listener(void)
541 listener_may_exit = 1;
542 if (!listener_os_thread) {
543 /* XXX there is an obscure path that this doesn't handle perfectly:
544 * right after listener thread is created but before
545 * listener_os_thread is set, the first worker thread hits an
546 * error and starts graceful termination
551 /* Unblock the listener if it's poll()ing */
552 if (listener_is_wakeable) {
553 apr_pollset_wakeup(event_pollset);
556 /* unblock the listener if it's waiting for a worker */
557 ap_queue_info_term(worker_queue_info);
560 * we should just be able to "kill(ap_my_pid, LISTENER_SIGNAL)" on all
561 * platforms and wake up the listener thread since it is the only thread
562 * with SIGHUP unblocked, but that doesn't work on Linux
564 #ifdef HAVE_PTHREAD_KILL
565 pthread_kill(*listener_os_thread, LISTENER_SIGNAL);
567 kill(ap_my_pid, LISTENER_SIGNAL);
572 #define ST_GRACEFUL 1
573 #define ST_UNGRACEFUL 2
575 static int terminate_mode = ST_INIT;
577 static void signal_threads(int mode)
579 if (terminate_mode == mode) {
582 terminate_mode = mode;
583 retained->mpm->mpm_state = AP_MPMQ_STOPPING;
585 /* in case we weren't called from the listener thread, wake up the
590 /* for ungraceful termination, let the workers exit now;
591 * for graceful termination, the listener thread will notify the
592 * workers to exit once it has stopped accepting new connections
594 if (mode == ST_UNGRACEFUL) {
595 workers_may_exit = 1;
596 ap_queue_interrupt_all(worker_queue);
597 close_worker_sockets(); /* forcefully kill all current connections */
601 static int event_query(int query_code, int *result, apr_status_t *rv)
604 switch (query_code) {
605 case AP_MPMQ_MAX_DAEMON_USED:
606 *result = retained->max_daemons_limit;
608 case AP_MPMQ_IS_THREADED:
609 *result = AP_MPMQ_STATIC;
611 case AP_MPMQ_IS_FORKED:
612 *result = AP_MPMQ_DYNAMIC;
614 case AP_MPMQ_IS_ASYNC:
617 case AP_MPMQ_HARD_LIMIT_DAEMONS:
618 *result = server_limit;
620 case AP_MPMQ_HARD_LIMIT_THREADS:
621 *result = thread_limit;
623 case AP_MPMQ_MAX_THREADS:
624 *result = threads_per_child;
626 case AP_MPMQ_MIN_SPARE_DAEMONS:
629 case AP_MPMQ_MIN_SPARE_THREADS:
630 *result = min_spare_threads;
632 case AP_MPMQ_MAX_SPARE_DAEMONS:
635 case AP_MPMQ_MAX_SPARE_THREADS:
636 *result = max_spare_threads;
638 case AP_MPMQ_MAX_REQUESTS_DAEMON:
639 *result = ap_max_requests_per_child;
641 case AP_MPMQ_MAX_DAEMONS:
642 *result = active_daemons_limit;
644 case AP_MPMQ_MPM_STATE:
645 *result = retained->mpm->mpm_state;
647 case AP_MPMQ_GENERATION:
648 *result = retained->mpm->my_generation;
657 static void event_note_child_killed(int childnum, pid_t pid, ap_generation_t gen)
659 if (childnum != -1) { /* child had a scoreboard slot? */
660 ap_run_child_status(ap_server_conf,
661 ap_scoreboard_image->parent[childnum].pid,
662 ap_scoreboard_image->parent[childnum].generation,
663 childnum, MPM_CHILD_EXITED);
664 ap_scoreboard_image->parent[childnum].pid = 0;
667 ap_run_child_status(ap_server_conf, pid, gen, -1, MPM_CHILD_EXITED);
671 static void event_note_child_started(int slot, pid_t pid)
673 ap_scoreboard_image->parent[slot].pid = pid;
674 ap_run_child_status(ap_server_conf,
675 ap_scoreboard_image->parent[slot].pid,
676 retained->mpm->my_generation, slot, MPM_CHILD_STARTED);
679 static const char *event_get_name(void)
684 /* a clean exit from a child with proper cleanup */
685 static void clean_child_exit(int code) __attribute__ ((noreturn));
686 static void clean_child_exit(int code)
688 retained->mpm->mpm_state = AP_MPMQ_STOPPING;
690 apr_pool_destroy(pchild);
694 event_note_child_killed(/* slot */ 0, 0, 0);
700 static void just_die(int sig)
705 /*****************************************************************
706 * Connection structures and accounting...
709 static int child_fatal;
711 static apr_status_t decrement_connection_count(void *cs_)
713 event_conn_state_t *cs = cs_;
714 switch (cs->pub.state) {
715 case CONN_STATE_LINGER_NORMAL:
716 case CONN_STATE_LINGER_SHORT:
717 apr_atomic_dec32(&lingering_count);
719 case CONN_STATE_SUSPENDED:
720 apr_atomic_dec32(&suspended_count);
725 /* Unblock the listener if it's waiting for connection_count = 0 */
726 if (!apr_atomic_dec32(&connection_count)
727 && listener_is_wakeable && listener_may_exit) {
728 apr_pollset_wakeup(event_pollset);
733 static void notify_suspend(event_conn_state_t *cs)
735 ap_run_suspend_connection(cs->c, cs->r);
740 static void notify_resume(event_conn_state_t *cs, ap_sb_handle_t *sbh)
744 ap_run_resume_connection(cs->c, cs->r);
748 * Close our side of the connection, flushing data to the client first.
749 * Pre-condition: cs is not in any timeout queue and not in the pollset,
750 * timeout_mutex is not locked
751 * return: 0 if connection is fully closed,
752 * 1 if connection is lingering
753 * May only be called by worker thread.
755 static int start_lingering_close_blocking(event_conn_state_t *cs)
758 struct timeout_queue *q;
759 apr_socket_t *csd = cs->pfd.desc.s;
761 if (ap_start_lingering_close(cs->c)) {
763 apr_socket_close(csd);
764 ap_push_pool(worker_queue_info, cs->p);
770 rv = apr_socket_timeout_set(csd, 0);
771 AP_DEBUG_ASSERT(rv == APR_SUCCESS);
774 apr_socket_timeout_set(csd, 0);
777 cs->queue_timestamp = apr_time_now();
779 * If some module requested a shortened waiting period, only wait for
780 * 2s (SECONDS_TO_LINGER). This is useful for mitigating certain
783 if (apr_table_get(cs->c->notes, "short-lingering-close")) {
785 cs->pub.state = CONN_STATE_LINGER_SHORT;
789 cs->pub.state = CONN_STATE_LINGER_NORMAL;
791 apr_atomic_inc32(&lingering_count);
794 cs->pfd.reqevents = (
795 cs->pub.sense == CONN_SENSE_WANT_WRITE ? APR_POLLOUT :
796 APR_POLLIN) | APR_POLLHUP | APR_POLLERR;
797 cs->pub.sense = CONN_SENSE_DEFAULT;
798 apr_thread_mutex_lock(timeout_mutex);
799 TO_QUEUE_APPEND(q, cs);
800 rv = apr_pollset_add(event_pollset, &cs->pfd);
801 if (rv != APR_SUCCESS && !APR_STATUS_IS_EEXIST(rv)) {
802 TO_QUEUE_REMOVE(q, cs);
803 apr_thread_mutex_unlock(timeout_mutex);
804 ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf, APLOGNO(03092)
805 "start_lingering_close: apr_pollset_add failure");
806 apr_socket_close(cs->pfd.desc.s);
807 ap_push_pool(worker_queue_info, cs->p);
810 apr_thread_mutex_unlock(timeout_mutex);
815 * Defer flush and close of the connection by adding it to defer_linger_chain,
816 * for a worker to grab it and do the job (should that be blocking).
817 * Pre-condition: cs is not in any timeout queue and not in the pollset,
818 * timeout_mutex is not locked
819 * return: 1 connection is alive (but aside and about to linger)
820 * May be called by listener thread.
822 static int start_lingering_close_nonblocking(event_conn_state_t *cs)
824 event_conn_state_t *chain;
826 cs->chain = chain = defer_linger_chain;
827 if (apr_atomic_casptr((void *)&defer_linger_chain, cs,
829 /* Race lost, try again */
837 * forcibly close a lingering connection after the lingering period has
839 * Pre-condition: cs is not in any timeout queue and not in the pollset
840 * return: irrelevant (need same prototype as start_lingering_close)
842 static int stop_lingering_close(event_conn_state_t *cs)
844 apr_socket_t *csd = ap_get_conn_socket(cs->c);
845 ap_log_error(APLOG_MARK, APLOG_TRACE4, 0, ap_server_conf,
846 "socket reached timeout in lingering-close state");
847 abort_socket_nonblocking(csd);
848 ap_push_pool(worker_queue_info, cs->p);
850 ap_queue_interrupt_one(worker_queue);
855 * This runs before any non-MPM cleanup code on the connection;
856 * if the connection is currently suspended as far as modules
857 * know, provide notification of resumption.
859 static apr_status_t ptrans_pre_cleanup(void *dummy)
861 event_conn_state_t *cs = dummy;
864 notify_resume(cs, NULL);
870 * event_pre_read_request() and event_request_cleanup() track the
871 * current r for a given connection.
873 static apr_status_t event_request_cleanup(void *dummy)
876 event_conn_state_t *cs = ap_get_module_config(c->conn_config,
883 static void event_pre_read_request(request_rec *r, conn_rec *c)
885 event_conn_state_t *cs = ap_get_module_config(c->conn_config,
889 cs->sc = ap_get_module_config(ap_server_conf->module_config,
891 apr_pool_cleanup_register(r->pool, c, event_request_cleanup,
892 apr_pool_cleanup_null);
896 * event_post_read_request() tracks the current server config for a
899 static int event_post_read_request(request_rec *r)
901 conn_rec *c = r->connection;
902 event_conn_state_t *cs = ap_get_module_config(c->conn_config,
905 /* To preserve legacy behaviour (consistent with other MPMs), use
906 * the keepalive timeout from the base server (first on this IP:port)
907 * when none is explicitly configured on this server.
909 if (r->server->keep_alive_timeout_set) {
910 cs->sc = ap_get_module_config(r->server->module_config,
914 cs->sc = ap_get_module_config(c->base_server->module_config,
921 * process one connection in the worker
923 static void process_socket(apr_thread_t *thd, apr_pool_t * p, apr_socket_t * sock,
924 event_conn_state_t * cs, int my_child_num,
928 long conn_id = ID_FROM_CHILD_THREAD(my_child_num, my_thread_num);
932 /* XXX: This will cause unbounded mem usage for long lasting connections */
933 ap_create_sb_handle(&sbh, p, my_child_num, my_thread_num);
935 if (cs == NULL) { /* This is a new connection */
936 listener_poll_type *pt = apr_pcalloc(p, sizeof(*pt));
937 cs = apr_pcalloc(p, sizeof(event_conn_state_t));
938 cs->bucket_alloc = apr_bucket_alloc_create(p);
939 c = ap_run_create_connection(p, ap_server_conf, sock,
940 conn_id, sbh, cs->bucket_alloc);
942 ap_push_pool(worker_queue_info, p);
945 apr_atomic_inc32(&connection_count);
946 apr_pool_cleanup_register(c->pool, cs, decrement_connection_count,
947 apr_pool_cleanup_null);
948 ap_set_module_config(c->conn_config, &mpm_event_module, cs);
949 c->current_thread = thd;
953 cs->sc = ap_get_module_config(ap_server_conf->module_config,
955 cs->pfd.desc_type = APR_POLL_SOCKET;
956 cs->pfd.reqevents = APR_POLLIN;
957 cs->pfd.desc.s = sock;
960 cs->pfd.client_data = pt;
961 apr_pool_pre_cleanup_register(p, cs, ptrans_pre_cleanup);
962 TO_QUEUE_ELEM_INIT(cs);
964 ap_update_vhost_given_ip(c);
966 rc = ap_run_pre_connection(c, sock);
967 if (rc != OK && rc != DONE) {
968 ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(00469)
969 "process_socket: connection aborted");
974 * XXX If the platform does not have a usable way of bundling
975 * accept() with a socket readability check, like Win32,
976 * and there are measurable delays before the
977 * socket is readable due to the first data packet arriving,
978 * it might be better to create the cs on the listener thread
979 * with the state set to CONN_STATE_CHECK_REQUEST_LINE_READABLE
981 * FreeBSD users will want to enable the HTTP accept filter
982 * module in their kernel for the highest performance
983 * When the accept filter is active, sockets are kept in the
984 * kernel until a HTTP request is received.
986 cs->pub.state = CONN_STATE_READ_REQUEST_LINE;
988 cs->pub.sense = CONN_SENSE_DEFAULT;
992 notify_resume(cs, sbh);
993 c->current_thread = thd;
994 /* Subsequent request on a conn, and thread number is part of ID */
998 cs->pub.state = CONN_STATE_LINGER;
1002 if (cs->pub.state == CONN_STATE_LINGER) {
1003 /* do lingering close below */
1005 else if (c->clogging_input_filters) {
1006 /* Since we have an input filter which 'clogs' the input stream,
1007 * like mod_ssl used to, lets just do the normal read from input
1008 * filters, like the Worker MPM does. Filters that need to write
1009 * where they would otherwise read, or read where they would
1010 * otherwise write, should set the sense appropriately.
1012 apr_atomic_inc32(&clogged_count);
1013 ap_run_process_connection(c);
1014 if (cs->pub.state != CONN_STATE_SUSPENDED) {
1015 cs->pub.state = CONN_STATE_LINGER;
1017 apr_atomic_dec32(&clogged_count);
1019 else if (cs->pub.state == CONN_STATE_READ_REQUEST_LINE) {
1021 ap_run_process_connection(c);
1023 /* state will be updated upon return
1024 * fall thru to either wait for readability/timeout or
1025 * do lingering close
1029 if (cs->pub.state == CONN_STATE_WRITE_COMPLETION) {
1030 ap_filter_t *output_filter = c->output_filters;
1032 ap_update_child_status(sbh, SERVER_BUSY_WRITE, NULL);
1033 while (output_filter->next != NULL) {
1034 output_filter = output_filter->next;
1036 rv = output_filter->frec->filter_func.out_func(output_filter, NULL);
1037 if (rv != APR_SUCCESS) {
1038 ap_log_cerror(APLOG_MARK, APLOG_DEBUG, rv, c, APLOGNO(00470)
1039 "network write failure in core output filter");
1040 cs->pub.state = CONN_STATE_LINGER;
1042 else if (c->data_in_output_filters) {
1043 /* Still in WRITE_COMPLETION_STATE:
1044 * Set a write timeout for this connection, and let the
1045 * event thread poll for writeability.
1047 cs->queue_timestamp = apr_time_now();
1049 cs->pfd.reqevents = (
1050 cs->pub.sense == CONN_SENSE_WANT_READ ? APR_POLLIN :
1051 APR_POLLOUT) | APR_POLLHUP | APR_POLLERR;
1052 cs->pub.sense = CONN_SENSE_DEFAULT;
1053 apr_thread_mutex_lock(timeout_mutex);
1054 TO_QUEUE_APPEND(cs->sc->wc_q, cs);
1055 rc = apr_pollset_add(event_pollset, &cs->pfd);
1056 if (rc != APR_SUCCESS && !APR_STATUS_IS_EEXIST(rc)) {
1057 TO_QUEUE_REMOVE(cs->sc->wc_q, cs);
1058 apr_thread_mutex_unlock(timeout_mutex);
1059 ap_log_error(APLOG_MARK, APLOG_ERR, rc, ap_server_conf, APLOGNO(03465)
1060 "process_socket: apr_pollset_add failure for "
1061 "write completion");
1062 apr_socket_close(cs->pfd.desc.s);
1063 ap_push_pool(worker_queue_info, cs->p);
1066 apr_thread_mutex_unlock(timeout_mutex);
1070 else if (c->keepalive != AP_CONN_KEEPALIVE || c->aborted ||
1071 listener_may_exit) {
1072 cs->pub.state = CONN_STATE_LINGER;
1074 else if (c->data_in_input_filters) {
1075 cs->pub.state = CONN_STATE_READ_REQUEST_LINE;
1079 cs->pub.state = CONN_STATE_CHECK_REQUEST_LINE_READABLE;
1083 if (cs->pub.state == CONN_STATE_LINGER) {
1084 start_lingering_close_blocking(cs);
1086 else if (cs->pub.state == CONN_STATE_CHECK_REQUEST_LINE_READABLE) {
1087 /* It greatly simplifies the logic to use a single timeout value per q
1088 * because the new element can just be added to the end of the list and
1089 * it will stay sorted in expiration time sequence. If brand new
1090 * sockets are sent to the event thread for a readability check, this
1091 * will be a slight behavior change - they use the non-keepalive
1092 * timeout today. With a normal client, the socket will be readable in
1093 * a few milliseconds anyway.
1095 cs->queue_timestamp = apr_time_now();
1098 /* Add work to pollset. */
1099 cs->pfd.reqevents = APR_POLLIN;
1100 apr_thread_mutex_lock(timeout_mutex);
1101 TO_QUEUE_APPEND(cs->sc->ka_q, cs);
1102 rc = apr_pollset_add(event_pollset, &cs->pfd);
1103 if (rc != APR_SUCCESS && !APR_STATUS_IS_EEXIST(rc)) {
1104 TO_QUEUE_REMOVE(cs->sc->ka_q, cs);
1105 apr_thread_mutex_unlock(timeout_mutex);
1106 ap_log_error(APLOG_MARK, APLOG_ERR, rc, ap_server_conf, APLOGNO(03093)
1107 "process_socket: apr_pollset_add failure for "
1109 apr_socket_close(cs->pfd.desc.s);
1110 ap_push_pool(worker_queue_info, cs->p);
1113 apr_thread_mutex_unlock(timeout_mutex);
1115 else if (cs->pub.state == CONN_STATE_SUSPENDED) {
1116 apr_atomic_inc32(&suspended_count);
1121 /* conns_this_child has gone to zero or below. See if the admin coded
1122 "MaxConnectionsPerChild 0", and keep going in that case. Doing it this way
1123 simplifies the hot path in worker_thread */
1124 static void check_infinite_requests(void)
1126 if (ap_max_requests_per_child) {
1127 ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, ap_server_conf,
1128 "Stopping process due to MaxConnectionsPerChild");
1129 signal_threads(ST_GRACEFUL);
1133 conns_this_child = APR_INT32_MAX;
1137 static void close_listeners(int process_slot, int *closed)
1141 disable_listensocks(process_slot);
1142 ap_close_listeners_ex(my_bucket->listeners);
1145 ap_scoreboard_image->parent[process_slot].quiescing = 1;
1146 for (i = 0; i < threads_per_child; ++i) {
1147 ap_update_child_status_from_indexes(process_slot, i,
1148 SERVER_GRACEFUL, NULL);
1150 /* wake up the main thread */
1151 kill(ap_my_pid, SIGTERM);
1153 ap_free_idle_pools(worker_queue_info);
1154 ap_queue_interrupt_all(worker_queue);
1158 static void unblock_signal(int sig)
1162 sigemptyset(&sig_mask);
1163 sigaddset(&sig_mask, sig);
1164 #if defined(SIGPROCMASK_SETS_THREAD_MASK)
1165 sigprocmask(SIG_UNBLOCK, &sig_mask, NULL);
1167 pthread_sigmask(SIG_UNBLOCK, &sig_mask, NULL);
1171 static void dummy_signal_handler(int sig)
1173 /* XXX If specifying SIG_IGN is guaranteed to unblock a syscall,
1174 * then we don't need this goofy function.
1179 static apr_status_t init_pollset(apr_pool_t *p)
1182 listener_poll_type *pt;
1185 listener_pollfd = apr_palloc(p, sizeof(apr_pollfd_t) * num_listensocks);
1186 for (lr = my_bucket->listeners; lr != NULL; lr = lr->next, i++) {
1188 AP_DEBUG_ASSERT(i < num_listensocks);
1189 pfd = &listener_pollfd[i];
1190 pt = apr_pcalloc(p, sizeof(*pt));
1191 pfd->desc_type = APR_POLL_SOCKET;
1192 pfd->desc.s = lr->sd;
1193 pfd->reqevents = APR_POLLIN;
1195 pt->type = PT_ACCEPT;
1198 pfd->client_data = pt;
1200 apr_socket_opt_set(pfd->desc.s, APR_SO_NONBLOCK, 1);
1201 apr_pollset_add(event_pollset, pfd);
1203 lr->accept_func = ap_unixd_accept;
1209 static apr_status_t push_timer2worker(timer_event_t* te)
1211 return ap_queue_push_timer(worker_queue, te);
1215 * Pre-condition: cs is neither in event_pollset nor a timeout queue
1216 * this function may only be called by the listener
1218 static apr_status_t push2worker(event_conn_state_t *cs, apr_socket_t *csd,
1224 csd = cs->pfd.desc.s;
1227 rc = ap_queue_push(worker_queue, csd, cs, ptrans);
1228 if (rc != APR_SUCCESS) {
1229 ap_log_error(APLOG_MARK, APLOG_CRIT, rc, ap_server_conf, APLOGNO(00471)
1230 "push2worker: ap_queue_push failed");
1231 /* trash the connection; we couldn't queue the connected
1232 * socket to a worker
1235 abort_socket_nonblocking(csd);
1238 ap_push_pool(worker_queue_info, ptrans);
1240 signal_threads(ST_GRACEFUL);
1247 * If *have_idle_worker_p == 0, reserve a worker thread, and set
1248 * *have_idle_worker_p = 1.
1249 * If *have_idle_worker_p is already 1, will do nothing.
1250 * If blocking == 1, block if all workers are currently busy.
1251 * If no worker was available immediately, will set *all_busy to 1.
1252 * XXX: If there are no workers, we should not block immediately but
1253 * XXX: close all keep-alive connections first.
1255 static void get_worker(int *have_idle_worker_p, int blocking, int *all_busy)
1259 if (*have_idle_worker_p) {
1260 /* already reserved a worker thread - must have hit a
1261 * transient error on a previous pass
1267 rc = ap_queue_info_wait_for_idler(worker_queue_info, all_busy);
1269 rc = ap_queue_info_try_get_idler(worker_queue_info);
1271 if (rc == APR_SUCCESS || APR_STATUS_IS_EOF(rc)) {
1272 *have_idle_worker_p = 1;
1274 else if (!blocking && rc == APR_EAGAIN) {
1278 ap_log_error(APLOG_MARK, APLOG_ERR, rc, ap_server_conf, APLOGNO(00472)
1279 "ap_queue_info_wait_for_idler failed. "
1280 "Attempting to shutdown process gracefully");
1281 signal_threads(ST_GRACEFUL);
1285 /* Structures to reuse */
1286 static APR_RING_HEAD(timer_free_ring_t, timer_event_t) timer_free_ring;
1288 static apr_skiplist *timer_skiplist;
1289 static volatile apr_time_t timers_next_expiry;
1291 /* Same goal as for TIMEOUT_FUDGE_FACTOR (avoid extra poll calls), but applied
1292 * to timers. Since their timeouts are custom (user defined), we can't be too
1293 * approximative here (hence using 0.01s).
1295 #define EVENT_FUDGE_FACTOR apr_time_from_msec(10)
1297 /* The following compare function is used by apr_skiplist_insert() to keep the
1298 * elements (timers) sorted and provide O(log n) complexity (this is also true
1299 * for apr_skiplist_{find,remove}(), but those are not used in MPM event where
1300 * inserted timers are not searched nor removed, but with apr_skiplist_pop()
1301 * which does use any compare function). It is meant to return 0 when a == b,
1302 * <0 when a < b, and >0 when a > b. However apr_skiplist_insert() will not
1303 * add duplicates (i.e. a == b), and apr_skiplist_add() is only available in
1304 * APR 1.6, yet multiple timers could possibly be created in the same micro-
1305 * second (duplicates with regard to apr_time_t); therefore we implement the
1306 * compare function to return +1 instead of 0 when compared timers are equal,
1307 * thus duplicates are still added after each other (in order of insertion).
1309 static int timer_comp(void *a, void *b)
1311 apr_time_t t1 = (apr_time_t) ((timer_event_t *)a)->when;
1312 apr_time_t t2 = (apr_time_t) ((timer_event_t *)b)->when;
1313 AP_DEBUG_ASSERT(t1);
1314 AP_DEBUG_ASSERT(t2);
1315 return ((t1 < t2) ? -1 : 1);
1318 static apr_thread_mutex_t *g_timer_skiplist_mtx;
1320 static apr_status_t event_register_timed_callback(apr_time_t t,
1321 ap_mpm_callback_fn_t *cbfn,
1325 /* oh yeah, and make locking smarter/fine grained. */
1326 apr_thread_mutex_lock(g_timer_skiplist_mtx);
1328 if (!APR_RING_EMPTY(&timer_free_ring, timer_event_t, link)) {
1329 te = APR_RING_FIRST(&timer_free_ring);
1330 APR_RING_REMOVE(te, link);
1333 te = apr_skiplist_alloc(timer_skiplist, sizeof(timer_event_t));
1334 APR_RING_ELEM_INIT(te, link);
1339 /* XXXXX: optimize */
1340 te->when = t + apr_time_now();
1343 apr_time_t next_expiry;
1345 /* Okay, add sorted by when.. */
1346 apr_skiplist_insert(timer_skiplist, te);
1348 /* Cheaply update the overall timers' next expiry according to
1349 * this event, if necessary.
1351 next_expiry = timers_next_expiry;
1352 if (!next_expiry || next_expiry > te->when + EVENT_FUDGE_FACTOR) {
1353 timers_next_expiry = te->when;
1354 /* Unblock the poll()ing listener for it to update its timeout. */
1355 if (listener_is_wakeable) {
1356 apr_pollset_wakeup(event_pollset);
1361 apr_thread_mutex_unlock(g_timer_skiplist_mtx);
1368 * Close socket and clean up if remote closed its end while we were in
1370 * Only to be called in the listener thread;
1371 * Pre-condition: cs is in one of the linger queues and in the pollset
1373 static void process_lingering_close(event_conn_state_t *cs, const apr_pollfd_t *pfd)
1375 apr_socket_t *csd = ap_get_conn_socket(cs->c);
1376 char dummybuf[2048];
1379 struct timeout_queue *q;
1380 q = (cs->pub.state == CONN_STATE_LINGER_SHORT) ? short_linger_q : linger_q;
1382 /* socket is already in non-blocking state */
1384 nbytes = sizeof(dummybuf);
1385 rv = apr_socket_recv(csd, dummybuf, &nbytes);
1386 } while (rv == APR_SUCCESS);
1388 if (APR_STATUS_IS_EAGAIN(rv)) {
1392 apr_thread_mutex_lock(timeout_mutex);
1393 TO_QUEUE_REMOVE(q, cs);
1394 rv = apr_pollset_remove(event_pollset, pfd);
1395 apr_thread_mutex_unlock(timeout_mutex);
1396 AP_DEBUG_ASSERT(rv == APR_SUCCESS || APR_STATUS_IS_NOTFOUND(rv));
1398 rv = apr_socket_close(csd);
1399 AP_DEBUG_ASSERT(rv == APR_SUCCESS);
1401 ap_push_pool(worker_queue_info, cs->p);
1403 ap_queue_interrupt_one(worker_queue);
1406 /* call 'func' for all elements of 'q' with timeout less than 'timeout_time'.
1407 * Pre-condition: timeout_mutex must already be locked
1408 * Post-condition: timeout_mutex will be locked again
1410 static void process_timeout_queue(struct timeout_queue *q,
1411 apr_time_t timeout_time,
1412 int (*func)(event_conn_state_t *))
1414 apr_uint32_t total = 0, count;
1415 event_conn_state_t *first, *cs, *last;
1416 struct timeout_head_t trash;
1417 struct timeout_queue *qp;
1420 if (!apr_atomic_read32(q->total)) {
1424 APR_RING_INIT(&trash, event_conn_state_t, timeout_list);
1425 for (qp = q; qp; qp = qp->next) {
1427 cs = first = last = APR_RING_FIRST(&qp->head);
1428 while (cs != APR_RING_SENTINEL(&qp->head, event_conn_state_t,
1430 /* Trash the entry if:
1431 * - no timeout_time was given (asked for all), or
1432 * - it expired (according to the queue timeout), or
1433 * - the system clock skewed in the past: no entry should be
1434 * registered above the given timeout_time (~now) + the queue
1435 * timeout, we won't keep any here (eg. for centuries).
1437 * Otherwise stop, no following entry will match thanks to the
1438 * single timeout per queue (entries are added to the end!).
1439 * This allows maintenance in O(1).
1442 && cs->queue_timestamp + qp->timeout > timeout_time
1443 && cs->queue_timestamp < timeout_time + qp->timeout) {
1444 /* Since this is the next expiring of this queue, update the
1445 * overall queues' next expiry if it's later than this one.
1447 apr_time_t q_expiry = cs->queue_timestamp + qp->timeout;
1448 apr_time_t next_expiry = queues_next_expiry;
1449 if (!next_expiry || next_expiry > q_expiry) {
1450 queues_next_expiry = q_expiry;
1456 rv = apr_pollset_remove(event_pollset, &cs->pfd);
1457 if (rv != APR_SUCCESS && !APR_STATUS_IS_NOTFOUND(rv)) {
1458 ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, cs->c, APLOGNO(00473)
1459 "apr_pollset_remove failed");
1461 cs = APR_RING_NEXT(cs, timeout_list);
1467 APR_RING_UNSPLICE(first, last, timeout_list);
1468 APR_RING_SPLICE_TAIL(&trash, first, last, event_conn_state_t,
1470 AP_DEBUG_ASSERT(apr_atomic_read32(q->total) >= count);
1471 apr_atomic_sub32(q->total, count);
1478 apr_thread_mutex_unlock(timeout_mutex);
1479 first = APR_RING_FIRST(&trash);
1481 cs = APR_RING_NEXT(first, timeout_list);
1482 TO_QUEUE_ELEM_INIT(first);
1486 apr_thread_mutex_lock(timeout_mutex);
1489 static void process_keepalive_queue(apr_time_t timeout_time)
1491 /* If all workers are busy, we kill older keep-alive connections so
1492 * that they may connect to another process.
1494 if (!timeout_time) {
1495 ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, ap_server_conf,
1496 "All workers are busy or dying, will close %u "
1497 "keep-alive connections",
1498 apr_atomic_read32(keepalive_q->total));
1500 process_timeout_queue(keepalive_q, timeout_time,
1501 start_lingering_close_nonblocking);
1504 static void * APR_THREAD_FUNC listener_thread(apr_thread_t * thd, void *dummy)
1508 proc_info *ti = dummy;
1509 int process_slot = ti->pslot;
1510 struct process_score *ps = ap_get_scoreboard_process(process_slot);
1511 apr_pool_t *tpool = apr_thread_pool_get(thd);
1513 apr_pool_t *ptrans; /* Pool for per-transaction stuff */
1515 int have_idle_worker = 0;
1516 const apr_pollfd_t *out_pfd;
1517 apr_int32_t num = 0;
1518 apr_interval_time_t timeout_interval;
1519 apr_time_t timeout_time = 0, now, last_log;
1520 listener_poll_type *pt;
1521 int closed = 0, listeners_disabled = 0;
1523 last_log = apr_time_now();
1526 rc = init_pollset(tpool);
1527 if (rc != APR_SUCCESS) {
1528 ap_log_error(APLOG_MARK, APLOG_ERR, rc, ap_server_conf,
1529 "failed to initialize pollset, "
1530 "attempting to shutdown process gracefully");
1531 signal_threads(ST_GRACEFUL);
1535 /* Unblock the signal used to wake this thread up, and set a handler for
1538 unblock_signal(LISTENER_SIGNAL);
1539 apr_signal(LISTENER_SIGNAL, dummy_signal_handler);
1542 int workers_were_busy = 0;
1544 if (listener_may_exit) {
1545 close_listeners(process_slot, &closed);
1546 if (terminate_mode == ST_UNGRACEFUL
1547 || apr_atomic_read32(&connection_count) == 0)
1551 if (conns_this_child <= 0)
1552 check_infinite_requests();
1554 now = apr_time_now();
1555 if (APLOGtrace6(ap_server_conf)) {
1556 /* trace log status every second */
1557 if (now - last_log > apr_time_from_sec(1)) {
1559 apr_thread_mutex_lock(timeout_mutex);
1560 ap_log_error(APLOG_MARK, APLOG_TRACE6, 0, ap_server_conf,
1561 "connections: %u (clogged: %u write-completion: %d "
1562 "keep-alive: %d lingering: %d suspended: %u)",
1563 apr_atomic_read32(&connection_count),
1564 apr_atomic_read32(&clogged_count),
1565 apr_atomic_read32(write_completion_q->total),
1566 apr_atomic_read32(keepalive_q->total),
1567 apr_atomic_read32(&lingering_count),
1568 apr_atomic_read32(&suspended_count));
1570 ap_log_error(APLOG_MARK, APLOG_TRACE6, 0, ap_server_conf,
1571 "%u/%u workers shutdown",
1572 apr_atomic_read32(&threads_shutdown),
1575 apr_thread_mutex_unlock(timeout_mutex);
1579 /* Start with an infinite poll() timeout and update it according to
1580 * the next expiring timer or queue entry. If there are none, either
1581 * the listener is wakeable and it can poll() indefinitely until a wake
1582 * up occurs, otherwise periodic checks (maintenance, shutdown, ...)
1583 * must be performed.
1585 timeout_interval = -1;
1587 /* Push expired timers to a worker, the first remaining one determines
1588 * the maximum time to poll() below, if any.
1590 timeout_time = timers_next_expiry;
1591 if (timeout_time && timeout_time < now + EVENT_FUDGE_FACTOR) {
1592 apr_thread_mutex_lock(g_timer_skiplist_mtx);
1593 while ((te = apr_skiplist_peek(timer_skiplist))) {
1594 if (te->when > now + EVENT_FUDGE_FACTOR) {
1595 timers_next_expiry = te->when;
1596 timeout_interval = te->when - now;
1599 apr_skiplist_pop(timer_skiplist, NULL);
1600 push_timer2worker(te);
1603 timers_next_expiry = 0;
1605 apr_thread_mutex_unlock(g_timer_skiplist_mtx);
1608 /* Same for queues, use their next expiry, if any. */
1609 timeout_time = queues_next_expiry;
1611 && (timeout_interval < 0
1612 || timeout_time <= now
1613 || timeout_interval > timeout_time - now)) {
1614 timeout_interval = timeout_time > now ? timeout_time - now : 1;
1617 /* When non-wakeable, don't wait more than 100 ms, in any case. */
1618 #define NON_WAKEABLE_POLL_TIMEOUT apr_time_from_msec(100)
1619 if (!listener_is_wakeable
1620 && (timeout_interval < 0
1621 || timeout_interval > NON_WAKEABLE_POLL_TIMEOUT)) {
1622 timeout_interval = NON_WAKEABLE_POLL_TIMEOUT;
1625 rc = apr_pollset_poll(event_pollset, timeout_interval, &num, &out_pfd);
1626 if (rc != APR_SUCCESS) {
1627 if (APR_STATUS_IS_EINTR(rc)) {
1628 /* Woken up, if we are exiting we must fall through to kill
1629 * kept-alive connections, otherwise we only need to update
1630 * timeouts (logic is above, so restart the loop).
1632 if (!listener_may_exit) {
1637 else if (!APR_STATUS_IS_TIMEUP(rc)) {
1638 ap_log_error(APLOG_MARK, APLOG_CRIT, rc, ap_server_conf,
1639 "apr_pollset_poll failed. Attempting to "
1640 "shutdown process gracefully");
1641 signal_threads(ST_GRACEFUL);
1646 if (listener_may_exit) {
1647 close_listeners(process_slot, &closed);
1648 if (terminate_mode == ST_UNGRACEFUL
1649 || apr_atomic_read32(&connection_count) == 0)
1654 pt = (listener_poll_type *) out_pfd->client_data;
1655 if (pt->type == PT_CSD) {
1656 /* one of the sockets is readable */
1657 event_conn_state_t *cs = (event_conn_state_t *) pt->baton;
1658 struct timeout_queue *remove_from_q = cs->sc->wc_q;
1661 switch (cs->pub.state) {
1662 case CONN_STATE_CHECK_REQUEST_LINE_READABLE:
1663 cs->pub.state = CONN_STATE_READ_REQUEST_LINE;
1664 remove_from_q = cs->sc->ka_q;
1665 /* don't wait for a worker for a keepalive request */
1668 case CONN_STATE_WRITE_COMPLETION:
1669 get_worker(&have_idle_worker, blocking,
1670 &workers_were_busy);
1671 apr_thread_mutex_lock(timeout_mutex);
1672 TO_QUEUE_REMOVE(remove_from_q, cs);
1673 rc = apr_pollset_remove(event_pollset, &cs->pfd);
1674 apr_thread_mutex_unlock(timeout_mutex);
1677 * Some of the pollset backends, like KQueue or Epoll
1678 * automagically remove the FD if the socket is closed,
1679 * therefore, we can accept _SUCCESS or _NOTFOUND,
1680 * and we still want to keep going
1682 if (rc != APR_SUCCESS && !APR_STATUS_IS_NOTFOUND(rc)) {
1683 ap_log_error(APLOG_MARK, APLOG_ERR, rc, ap_server_conf,
1684 APLOGNO(03094) "pollset remove failed");
1685 start_lingering_close_nonblocking(cs);
1689 /* If we didn't get a worker immediately for a keep-alive
1690 * request, we close the connection, so that the client can
1691 * re-connect to a different process.
1693 if (!have_idle_worker) {
1694 start_lingering_close_nonblocking(cs);
1696 else if (push2worker(cs, NULL, NULL) == APR_SUCCESS) {
1697 have_idle_worker = 0;
1701 case CONN_STATE_LINGER_NORMAL:
1702 case CONN_STATE_LINGER_SHORT:
1703 process_lingering_close(cs, out_pfd);
1707 ap_log_error(APLOG_MARK, APLOG_CRIT, rc,
1708 ap_server_conf, APLOGNO(03096)
1709 "event_loop: unexpected state %d",
1714 else if (pt->type == PT_ACCEPT) {
1715 /* A Listener Socket is ready for an accept() */
1716 if (workers_were_busy) {
1717 if (!listeners_disabled)
1718 disable_listensocks(process_slot);
1719 listeners_disabled = 1;
1720 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
1721 "All workers busy, not accepting new conns "
1724 else if ( (int)apr_atomic_read32(&connection_count)
1725 - (int)apr_atomic_read32(&lingering_count)
1727 + ap_queue_info_get_idlers(worker_queue_info) *
1728 worker_factor / WORKER_FACTOR_SCALE)
1730 if (!listeners_disabled)
1731 disable_listensocks(process_slot);
1732 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
1733 "Too many open connections (%u), "
1734 "not accepting new conns in this process",
1735 apr_atomic_read32(&connection_count));
1736 ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, ap_server_conf,
1738 ap_queue_info_get_idlers(worker_queue_info));
1739 listeners_disabled = 1;
1741 else if (listeners_disabled) {
1742 listeners_disabled = 0;
1743 enable_listensocks(process_slot);
1745 if (!listeners_disabled) {
1746 lr = (ap_listen_rec *) pt->baton;
1747 ap_pop_pool(&ptrans, worker_queue_info);
1749 if (ptrans == NULL) {
1750 /* create a new transaction pool for each accepted socket */
1751 apr_allocator_t *allocator;
1753 apr_allocator_create(&allocator);
1754 apr_allocator_max_free_set(allocator,
1756 apr_pool_create_ex(&ptrans, pconf, NULL, allocator);
1757 apr_allocator_owner_set(allocator, ptrans);
1758 if (ptrans == NULL) {
1759 ap_log_error(APLOG_MARK, APLOG_CRIT, rc,
1760 ap_server_conf, APLOGNO(03097)
1761 "Failed to create transaction pool");
1762 signal_threads(ST_GRACEFUL);
1766 apr_pool_tag(ptrans, "transaction");
1768 get_worker(&have_idle_worker, 1, &workers_were_busy);
1769 rc = lr->accept_func(&csd, lr, ptrans);
1771 /* later we trash rv and rely on csd to indicate
1774 AP_DEBUG_ASSERT(rc == APR_SUCCESS || !csd);
1776 if (rc == APR_EGENERAL) {
1777 /* E[NM]FILE, ENOMEM, etc */
1778 resource_shortage = 1;
1779 signal_threads(ST_GRACEFUL);
1784 if (push2worker(NULL, csd, ptrans) == APR_SUCCESS) {
1785 have_idle_worker = 0;
1789 ap_push_pool(worker_queue_info, ptrans);
1792 } /* if:else on pt->type */
1795 } /* while for processing poll */
1797 /* XXX possible optimization: stash the current time for use as
1798 * r->request_time for new requests
1800 /* We process the timeout queues here only when their overall next
1801 * expiry (read once above) is over. This happens accurately since
1802 * adding to the queues (in workers) can only decrease this expiry,
1803 * while latest ones are only taken into account here (in listener)
1804 * during queues' processing, with the lock held. This works both
1805 * with and without wake-ability.
1807 if (timeout_time && timeout_time < (now = apr_time_now())) {
1808 timeout_time = now + TIMEOUT_FUDGE_FACTOR;
1810 /* handle timed out sockets */
1811 apr_thread_mutex_lock(timeout_mutex);
1813 /* Processing all the queues below will recompute this. */
1814 queues_next_expiry = 0;
1816 /* Step 1: keepalive timeouts */
1817 if (workers_were_busy || dying) {
1818 process_keepalive_queue(0); /* kill'em all \m/ */
1821 process_keepalive_queue(timeout_time);
1823 /* Step 2: write completion timeouts */
1824 process_timeout_queue(write_completion_q, timeout_time,
1825 start_lingering_close_nonblocking);
1826 /* Step 3: (normal) lingering close completion timeouts */
1827 process_timeout_queue(linger_q, timeout_time,
1828 stop_lingering_close);
1829 /* Step 4: (short) lingering close completion timeouts */
1830 process_timeout_queue(short_linger_q, timeout_time,
1831 stop_lingering_close);
1833 apr_thread_mutex_unlock(timeout_mutex);
1835 ps->keep_alive = apr_atomic_read32(keepalive_q->total);
1836 ps->write_completion = apr_atomic_read32(write_completion_q->total);
1837 ps->connections = apr_atomic_read32(&connection_count);
1838 ps->suspended = apr_atomic_read32(&suspended_count);
1839 ps->lingering_close = apr_atomic_read32(&lingering_count);
1841 else if ((workers_were_busy || dying)
1842 && apr_atomic_read32(keepalive_q->total)) {
1843 apr_thread_mutex_lock(timeout_mutex);
1844 process_keepalive_queue(0); /* kill'em all \m/ */
1845 apr_thread_mutex_unlock(timeout_mutex);
1849 /* If there are some lingering closes to defer (to a worker), schedule
1850 * them now. We might wakeup a worker spuriously if another one empties
1851 * defer_linger_chain in the meantime, but there also may be no active
1852 * or all busy workers for an undefined time. In any case a deferred
1853 * lingering close can't starve if we do that here since the chain is
1854 * filled only above in the listener and it's emptied only in the
1855 * worker(s); thus a NULL here means it will stay so while the listener
1856 * waits (possibly indefinitely) in poll().
1858 if (defer_linger_chain) {
1859 get_worker(&have_idle_worker, 0, &workers_were_busy);
1860 if (have_idle_worker
1861 && defer_linger_chain /* re-test */
1862 && push2worker(NULL, NULL, NULL) == APR_SUCCESS) {
1863 have_idle_worker = 0;
1867 if (listeners_disabled && !workers_were_busy
1868 && (int)apr_atomic_read32(&connection_count)
1869 - (int)apr_atomic_read32(&lingering_count)
1870 < ((int)ap_queue_info_get_idlers(worker_queue_info) - 1)
1871 * worker_factor / WORKER_FACTOR_SCALE + threads_per_child)
1873 listeners_disabled = 0;
1874 enable_listensocks(process_slot);
1877 * XXX: do we need to set some timeout that re-enables the listensocks
1878 * XXX: in case no other event occurs?
1880 } /* listener main loop */
1882 close_listeners(process_slot, &closed);
1883 ap_queue_term(worker_queue);
1885 apr_thread_exit(thd, APR_SUCCESS);
1890 * During graceful shutdown, if there are more running worker threads than
1891 * open connections, exit one worker thread.
1893 * return 1 if thread should exit, 0 if it should continue running.
1895 static int worker_thread_should_exit_early(void)
1898 apr_uint32_t conns = apr_atomic_read32(&connection_count);
1899 apr_uint32_t dead = apr_atomic_read32(&threads_shutdown);
1900 apr_uint32_t newdead;
1902 AP_DEBUG_ASSERT(dead <= threads_per_child);
1903 if (conns >= threads_per_child - dead)
1907 if (apr_atomic_cas32(&threads_shutdown, newdead, dead) == dead) {
1909 * No other thread has exited in the mean time, safe to exit
1917 /* XXX For ungraceful termination/restart, we definitely don't want to
1918 * wait for active connections to finish but we may want to wait
1919 * for idle workers to get out of the queue code and release mutexes,
1920 * since those mutexes are cleaned up pretty soon and some systems
1921 * may not react favorably (i.e., segfault) if operations are attempted
1922 * on cleaned-up mutexes.
1924 static void *APR_THREAD_FUNC worker_thread(apr_thread_t * thd, void *dummy)
1926 proc_info *ti = dummy;
1927 int process_slot = ti->pslot;
1928 int thread_slot = ti->tslot;
1929 apr_socket_t *csd = NULL;
1930 event_conn_state_t *cs;
1931 apr_pool_t *ptrans; /* Pool for per-transaction stuff */
1934 timer_event_t *te = NULL;
1938 ap_scoreboard_image->servers[process_slot][thread_slot].pid = ap_my_pid;
1939 ap_scoreboard_image->servers[process_slot][thread_slot].tid = apr_os_thread_current();
1940 ap_scoreboard_image->servers[process_slot][thread_slot].generation = retained->mpm->my_generation;
1941 ap_update_child_status_from_indexes(process_slot, thread_slot,
1942 SERVER_STARTING, NULL);
1944 while (!workers_may_exit) {
1946 rv = ap_queue_info_set_idle(worker_queue_info, NULL);
1947 if (rv != APR_SUCCESS) {
1948 ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
1949 "ap_queue_info_set_idle failed. Attempting to "
1950 "shutdown process gracefully.");
1951 signal_threads(ST_GRACEFUL);
1957 ap_update_child_status_from_indexes(process_slot, thread_slot,
1958 dying ? SERVER_GRACEFUL
1959 : SERVER_READY, NULL);
1961 if (workers_may_exit) {
1964 if (dying && worker_thread_should_exit_early()) {
1969 rv = ap_queue_pop_something(worker_queue, &csd, &cs, &ptrans, &te);
1971 if (rv != APR_SUCCESS) {
1972 /* We get APR_EOF during a graceful shutdown once all the
1973 * connections accepted by this server process have been handled.
1975 if (APR_STATUS_IS_EOF(rv)) {
1978 /* We get APR_EINTR whenever ap_queue_pop() has been interrupted
1979 * from an explicit call to ap_queue_interrupt_all(). This allows
1980 * us to unblock threads stuck in ap_queue_pop() when a shutdown
1983 * If workers_may_exit is set and this is ungraceful termination/
1984 * restart, we are bound to get an error on some systems (e.g.,
1985 * AIX, which sanity-checks mutex operations) since the queue
1986 * may have already been cleaned up. Don't log the "error" if
1987 * workers_may_exit is set.
1989 else if (APR_STATUS_IS_EINTR(rv)) {
1992 /* We got some other error. */
1993 else if (!workers_may_exit) {
1994 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
1995 APLOGNO(03099) "ap_queue_pop failed");
2000 te->cbfunc(te->baton);
2003 apr_thread_mutex_lock(g_timer_skiplist_mtx);
2004 APR_RING_INSERT_TAIL(&timer_free_ring, te, timer_event_t, link);
2005 apr_thread_mutex_unlock(g_timer_skiplist_mtx);
2011 worker_sockets[thread_slot] = csd;
2012 process_socket(thd, ptrans, csd, cs, process_slot, thread_slot);
2013 worker_sockets[thread_slot] = NULL;
2017 /* If there are deferred lingering closes, handle them now. */
2018 while (!workers_may_exit) {
2019 cs = defer_linger_chain;
2023 if (apr_atomic_casptr((void *)&defer_linger_chain, cs->chain,
2025 /* Race lost, try again */
2030 worker_sockets[thread_slot] = csd = cs->pfd.desc.s;
2032 rv = apr_socket_timeout_set(csd, SECONDS_TO_LINGER);
2033 AP_DEBUG_ASSERT(rv == APR_SUCCESS);
2035 apr_socket_timeout_set(csd, SECONDS_TO_LINGER);
2037 cs->pub.state = CONN_STATE_LINGER;
2038 process_socket(thd, cs->p, csd, cs, process_slot, thread_slot);
2039 worker_sockets[thread_slot] = NULL;
2043 ap_update_child_status_from_indexes(process_slot, thread_slot,
2045 : SERVER_GRACEFUL, NULL);
2047 apr_thread_exit(thd, APR_SUCCESS);
2051 static int check_signal(int signum)
2063 static void create_listener_thread(thread_starter * ts)
2065 int my_child_num = ts->child_num_arg;
2066 apr_threadattr_t *thread_attr = ts->threadattr;
2070 my_info = (proc_info *) ap_malloc(sizeof(proc_info));
2071 my_info->pslot = my_child_num;
2072 my_info->tslot = -1; /* listener thread doesn't have a thread slot */
2073 rv = apr_thread_create(&ts->listener, thread_attr, listener_thread,
2075 if (rv != APR_SUCCESS) {
2076 ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf, APLOGNO(00474)
2077 "apr_thread_create: unable to create listener thread");
2078 /* let the parent decide how bad this really is */
2079 clean_child_exit(APEXIT_CHILDSICK);
2081 apr_os_thread_get(&listener_os_thread, ts->listener);
2084 /* XXX under some circumstances not understood, children can get stuck
2085 * in start_threads forever trying to take over slots which will
2086 * never be cleaned up; for now there is an APLOG_DEBUG message issued
2087 * every so often when this condition occurs
2089 static void *APR_THREAD_FUNC start_threads(apr_thread_t * thd, void *dummy)
2091 thread_starter *ts = dummy;
2092 apr_thread_t **threads = ts->threads;
2093 apr_threadattr_t *thread_attr = ts->threadattr;
2094 int my_child_num = ts->child_num_arg;
2098 int threads_created = 0;
2099 int listener_started = 0;
2101 int prev_threads_created;
2102 int max_recycled_pools = -1;
2103 int good_methods[] = {APR_POLLSET_KQUEUE, APR_POLLSET_PORT, APR_POLLSET_EPOLL};
2104 /* XXX don't we need more to handle K-A or lingering close? */
2105 const apr_uint32_t pollset_size = threads_per_child * 2;
2107 /* We must create the fd queues before we start up the listener
2108 * and worker threads. */
2109 worker_queue = apr_pcalloc(pchild, sizeof(*worker_queue));
2110 rv = ap_queue_init(worker_queue, threads_per_child, pchild);
2111 if (rv != APR_SUCCESS) {
2112 ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf, APLOGNO(03100)
2113 "ap_queue_init() failed");
2114 clean_child_exit(APEXIT_CHILDFATAL);
2117 if (ap_max_mem_free != APR_ALLOCATOR_MAX_FREE_UNLIMITED) {
2118 /* If we want to conserve memory, let's not keep an unlimited number of
2119 * pools & allocators.
2120 * XXX: This should probably be a separate config directive
2122 max_recycled_pools = threads_per_child * 3 / 4 ;
2124 rv = ap_queue_info_create(&worker_queue_info, pchild,
2125 threads_per_child, max_recycled_pools);
2126 if (rv != APR_SUCCESS) {
2127 ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf, APLOGNO(03101)
2128 "ap_queue_info_create() failed");
2129 clean_child_exit(APEXIT_CHILDFATAL);
2132 /* Create the timeout mutex and main pollset before the listener
2135 rv = apr_thread_mutex_create(&timeout_mutex, APR_THREAD_MUTEX_DEFAULT,
2137 if (rv != APR_SUCCESS) {
2138 ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf, APLOGNO(03102)
2139 "creation of the timeout mutex failed.");
2140 clean_child_exit(APEXIT_CHILDFATAL);
2143 /* Create the main pollset */
2144 for (i = 0; i < sizeof(good_methods) / sizeof(good_methods[0]); i++) {
2145 apr_uint32_t flags = APR_POLLSET_THREADSAFE | APR_POLLSET_NOCOPY |
2146 APR_POLLSET_NODEFAULT | APR_POLLSET_WAKEABLE;
2147 rv = apr_pollset_create_ex(&event_pollset, pollset_size, pchild, flags,
2149 if (rv == APR_SUCCESS) {
2150 listener_is_wakeable = 1;
2153 flags &= ~APR_POLLSET_WAKEABLE;
2154 rv = apr_pollset_create_ex(&event_pollset, pollset_size, pchild, flags,
2156 if (rv == APR_SUCCESS) {
2160 if (rv != APR_SUCCESS) {
2161 rv = apr_pollset_create(&event_pollset, pollset_size, pchild,
2162 APR_POLLSET_THREADSAFE | APR_POLLSET_NOCOPY);
2164 if (rv != APR_SUCCESS) {
2165 ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf, APLOGNO(03103)
2166 "apr_pollset_create with Thread Safety failed.");
2167 clean_child_exit(APEXIT_CHILDFATAL);
2170 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02471)
2171 "start_threads: Using %s (%swakeable)",
2172 apr_pollset_method_name(event_pollset),
2173 listener_is_wakeable ? "" : "not ");
2174 worker_sockets = apr_pcalloc(pchild, threads_per_child
2175 * sizeof(apr_socket_t *));
2177 loops = prev_threads_created = 0;
2179 /* threads_per_child does not include the listener thread */
2180 for (i = 0; i < threads_per_child; i++) {
2182 ap_scoreboard_image->servers[my_child_num][i].status;
2184 if (status != SERVER_DEAD) {
2188 my_info = (proc_info *) ap_malloc(sizeof(proc_info));
2189 my_info->pslot = my_child_num;
2192 /* We are creating threads right now */
2193 ap_update_child_status_from_indexes(my_child_num, i,
2194 SERVER_STARTING, NULL);
2195 /* We let each thread update its own scoreboard entry. This is
2196 * done because it lets us deal with tid better.
2198 rv = apr_thread_create(&threads[i], thread_attr,
2199 worker_thread, my_info, pchild);
2200 if (rv != APR_SUCCESS) {
2201 ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
2203 "apr_thread_create: unable to create worker thread");
2204 /* let the parent decide how bad this really is */
2205 clean_child_exit(APEXIT_CHILDSICK);
2210 /* Start the listener only when there are workers available */
2211 if (!listener_started && threads_created) {
2212 create_listener_thread(ts);
2213 listener_started = 1;
2217 if (start_thread_may_exit || threads_created == threads_per_child) {
2220 /* wait for previous generation to clean up an entry */
2221 apr_sleep(apr_time_from_sec(1));
2223 if (loops % 120 == 0) { /* every couple of minutes */
2224 if (prev_threads_created == threads_created) {
2225 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
2226 "child %" APR_PID_T_FMT " isn't taking over "
2227 "slots very quickly (%d of %d)",
2228 ap_my_pid, threads_created,
2231 prev_threads_created = threads_created;
2235 /* What state should this child_main process be listed as in the
2237 * ap_update_child_status_from_indexes(my_child_num, i, SERVER_STARTING,
2238 * (request_rec *) NULL);
2240 * This state should be listed separately in the scoreboard, in some kind
2241 * of process_status, not mixed in with the worker threads' status.
2242 * "life_status" is almost right, but it's in the worker's structure, and
2243 * the name could be clearer. gla
2245 apr_thread_exit(thd, APR_SUCCESS);
2249 static void join_workers(apr_thread_t * listener, apr_thread_t ** threads)
2252 apr_status_t rv, thread_rv;
2257 /* deal with a rare timing window which affects waking up the
2258 * listener thread... if the signal sent to the listener thread
2259 * is delivered between the time it verifies that the
2260 * listener_may_exit flag is clear and the time it enters a
2261 * blocking syscall, the signal didn't do any good... work around
2262 * that by sleeping briefly and sending it again
2266 while (iter < 10 && !dying) {
2267 /* listener has not stopped accepting yet */
2268 apr_sleep(apr_time_make(0, 500000));
2273 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(00475)
2274 "the listener thread didn't stop accepting");
2277 rv = apr_thread_join(&thread_rv, listener);
2278 if (rv != APR_SUCCESS) {
2279 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf, APLOGNO(00476)
2280 "apr_thread_join: unable to join listener thread");
2285 for (i = 0; i < threads_per_child; i++) {
2286 if (threads[i]) { /* if we ever created this thread */
2287 rv = apr_thread_join(&thread_rv, threads[i]);
2288 if (rv != APR_SUCCESS) {
2289 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf, APLOGNO(00477)
2290 "apr_thread_join: unable to join worker "
2297 static void join_start_thread(apr_thread_t * start_thread_id)
2299 apr_status_t rv, thread_rv;
2301 start_thread_may_exit = 1; /* tell it to give up in case it is still
2302 * trying to take over slots from a
2303 * previous generation
2305 rv = apr_thread_join(&thread_rv, start_thread_id);
2306 if (rv != APR_SUCCESS) {
2307 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf, APLOGNO(00478)
2308 "apr_thread_join: unable to join the start " "thread");
2312 static void child_main(int child_num_arg, int child_bucket)
2314 apr_thread_t **threads;
2317 apr_threadattr_t *thread_attr;
2318 apr_thread_t *start_thread_id;
2321 /* for benefit of any hooks that run as this child initializes */
2322 retained->mpm->mpm_state = AP_MPMQ_STARTING;
2324 ap_my_pid = getpid();
2325 ap_fatal_signal_child_setup(ap_server_conf);
2326 apr_pool_create(&pchild, pconf);
2328 /* close unused listeners and pods */
2329 for (i = 0; i < retained->mpm->num_buckets; i++) {
2330 if (i != child_bucket) {
2331 ap_close_listeners_ex(all_buckets[i].listeners);
2332 ap_mpm_podx_close(all_buckets[i].pod);
2336 /*stuff to do before we switch id's, so we have permissions. */
2337 ap_reopen_scoreboard(pchild, NULL, 0);
2339 if (ap_run_drop_privileges(pchild, ap_server_conf)) {
2340 clean_child_exit(APEXIT_CHILDFATAL);
2343 apr_thread_mutex_create(&g_timer_skiplist_mtx, APR_THREAD_MUTEX_DEFAULT, pchild);
2344 APR_RING_INIT(&timer_free_ring, timer_event_t, link);
2345 apr_skiplist_init(&timer_skiplist, pchild);
2346 apr_skiplist_set_compare(timer_skiplist, timer_comp, timer_comp);
2347 ap_run_child_init(pchild, ap_server_conf);
2349 /* done with init critical section */
2351 /* Just use the standard apr_setup_signal_thread to block all signals
2352 * from being received. The child processes no longer use signals for
2353 * any communication with the parent process.
2355 rv = apr_setup_signal_thread();
2356 if (rv != APR_SUCCESS) {
2357 ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf, APLOGNO(00479)
2358 "Couldn't initialize signal thread");
2359 clean_child_exit(APEXIT_CHILDFATAL);
2362 if (ap_max_requests_per_child) {
2363 conns_this_child = ap_max_requests_per_child;
2366 /* coding a value of zero means infinity */
2367 conns_this_child = APR_INT32_MAX;
2370 /* Setup worker threads */
2372 /* clear the storage; we may not create all our threads immediately,
2373 * and we want a 0 entry to indicate a thread which was not created
2375 threads = ap_calloc(threads_per_child, sizeof(apr_thread_t *));
2376 ts = apr_palloc(pchild, sizeof(*ts));
2378 apr_threadattr_create(&thread_attr, pchild);
2379 /* 0 means PTHREAD_CREATE_JOINABLE */
2380 apr_threadattr_detach_set(thread_attr, 0);
2382 if (ap_thread_stacksize != 0) {
2383 rv = apr_threadattr_stacksize_set(thread_attr, ap_thread_stacksize);
2384 if (rv != APR_SUCCESS && rv != APR_ENOTIMPL) {
2385 ap_log_error(APLOG_MARK, APLOG_WARNING, rv, ap_server_conf, APLOGNO(02436)
2386 "WARNING: ThreadStackSize of %" APR_SIZE_T_FMT " is "
2387 "inappropriate, using default",
2388 ap_thread_stacksize);
2392 ts->threads = threads;
2393 ts->listener = NULL;
2394 ts->child_num_arg = child_num_arg;
2395 ts->threadattr = thread_attr;
2397 rv = apr_thread_create(&start_thread_id, thread_attr, start_threads,
2399 if (rv != APR_SUCCESS) {
2400 ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf, APLOGNO(00480)
2401 "apr_thread_create: unable to create worker thread");
2402 /* let the parent decide how bad this really is */
2403 clean_child_exit(APEXIT_CHILDSICK);
2406 retained->mpm->mpm_state = AP_MPMQ_RUNNING;
2408 /* If we are only running in one_process mode, we will want to
2409 * still handle signals. */
2411 /* Block until we get a terminating signal. */
2412 apr_signal_thread(check_signal);
2413 /* make sure the start thread has finished; signal_threads()
2414 * and join_workers() depend on that
2416 /* XXX join_start_thread() won't be awakened if one of our
2417 * threads encounters a critical error and attempts to
2418 * shutdown this child
2420 join_start_thread(start_thread_id);
2422 /* helps us terminate a little more quickly than the dispatch of the
2423 * signal thread; beats the Pipe of Death and the browsers
2425 signal_threads(ST_UNGRACEFUL);
2427 /* A terminating signal was received. Now join each of the
2428 * workers to clean them up.
2429 * If the worker already exited, then the join frees
2430 * their resources and returns.
2431 * If the worker hasn't exited, then this blocks until
2432 * they have (then cleans up).
2434 join_workers(ts->listener, threads);
2436 else { /* !one_process */
2437 /* remove SIGTERM from the set of blocked signals... if one of
2438 * the other threads in the process needs to take us down
2439 * (e.g., for MaxConnectionsPerChild) it will send us SIGTERM
2441 unblock_signal(SIGTERM);
2442 apr_signal(SIGTERM, dummy_signal_handler);
2443 /* Watch for any messages from the parent over the POD */
2445 rv = ap_mpm_podx_check(my_bucket->pod);
2446 if (rv == AP_MPM_PODX_NORESTART) {
2447 /* see if termination was triggered while we slept */
2448 switch (terminate_mode) {
2450 rv = AP_MPM_PODX_GRACEFUL;
2453 rv = AP_MPM_PODX_RESTART;
2457 if (rv == AP_MPM_PODX_GRACEFUL || rv == AP_MPM_PODX_RESTART) {
2458 /* make sure the start thread has finished;
2459 * signal_threads() and join_workers depend on that
2461 join_start_thread(start_thread_id);
2462 signal_threads(rv ==
2463 AP_MPM_PODX_GRACEFUL ? ST_GRACEFUL : ST_UNGRACEFUL);
2468 /* A terminating signal was received. Now join each of the
2469 * workers to clean them up.
2470 * If the worker already exited, then the join frees
2471 * their resources and returns.
2472 * If the worker hasn't exited, then this blocks until
2473 * they have (then cleans up).
2475 join_workers(ts->listener, threads);
2480 clean_child_exit(resource_shortage ? APEXIT_CHILDSICK : 0);
2483 static int make_child(server_rec * s, int slot, int bucket)
2487 if (slot + 1 > retained->max_daemons_limit) {
2488 retained->max_daemons_limit = slot + 1;
2491 if (ap_scoreboard_image->parent[slot].pid != 0) {
2492 /* XXX replace with assert or remove ? */
2493 ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, APLOGNO(03455)
2494 "BUG: Scoreboard slot %d should be empty but is "
2495 "in use by pid %" APR_PID_T_FMT,
2496 slot, ap_scoreboard_image->parent[slot].pid);
2501 my_bucket = &all_buckets[0];
2503 event_note_child_started(slot, getpid());
2504 child_main(slot, 0);
2510 if ((pid = fork()) == -1) {
2511 ap_log_error(APLOG_MARK, APLOG_ERR, errno, s, APLOGNO(00481)
2512 "fork: Unable to fork new process");
2514 /* fork didn't succeed. There's no need to touch the scoreboard;
2515 * if we were trying to replace a failed child process, then
2516 * server_main_loop() marked its workers SERVER_DEAD, and if
2517 * we were trying to replace a child process that exited normally,
2518 * its worker_thread()s left SERVER_DEAD or SERVER_GRACEFUL behind.
2521 /* In case system resources are maxxed out, we don't want
2522 Apache running away with the CPU trying to fork over and
2523 over and over again. */
2524 apr_sleep(apr_time_from_sec(10));
2530 my_bucket = &all_buckets[bucket];
2532 #ifdef HAVE_BINDPROCESSOR
2533 /* By default, AIX binds to a single processor. This bit unbinds
2534 * children which will then bind to another CPU.
2536 int status = bindprocessor(BINDPROCESS, (int) getpid(),
2537 PROCESSOR_CLASS_ANY);
2539 ap_log_error(APLOG_MARK, APLOG_DEBUG, errno,
2540 ap_server_conf, APLOGNO(00482)
2541 "processor unbind failed");
2543 RAISE_SIGSTOP(MAKE_CHILD);
2545 apr_signal(SIGTERM, just_die);
2546 child_main(slot, bucket);
2552 ap_scoreboard_image->parent[slot].quiescing = 0;
2553 ap_scoreboard_image->parent[slot].not_accepting = 0;
2554 ap_scoreboard_image->parent[slot].bucket = bucket;
2555 event_note_child_started(slot, pid);
2557 retained->total_daemons++;
2561 /* start up a bunch of children */
2562 static void startup_children(int number_to_start)
2566 for (i = 0; number_to_start && i < server_limit; ++i) {
2567 if (ap_scoreboard_image->parent[i].pid != 0) {
2570 if (make_child(ap_server_conf, i, i % retained->mpm->num_buckets) < 0) {
2577 static void perform_idle_server_maintenance(int child_bucket, int num_buckets)
2580 int idle_thread_count = 0;
2583 int free_length = 0;
2584 int free_slots[MAX_SPAWN_RATE];
2585 int last_non_dead = -1;
2586 int active_thread_count = 0;
2588 for (i = 0; i < server_limit; ++i) {
2589 /* Initialization to satisfy the compiler. It doesn't know
2590 * that threads_per_child is always > 0 */
2591 int status = SERVER_DEAD;
2592 int child_threads_active = 0;
2594 if (i >= retained->max_daemons_limit &&
2595 free_length == retained->idle_spawn_rate[child_bucket]) {
2596 /* short cut if all active processes have been examined and
2597 * enough empty scoreboard slots have been found
2602 ps = &ap_scoreboard_image->parent[i];
2604 for (j = 0; j < threads_per_child; j++) {
2605 ws = &ap_scoreboard_image->servers[i][j];
2606 status = ws->status;
2608 /* We consider a starting server as idle because we started it
2609 * at least a cycle ago, and if it still hasn't finished starting
2610 * then we're just going to swamp things worse by forking more.
2611 * So we hopefully won't need to fork more if we count it.
2612 * This depends on the ordering of SERVER_READY and SERVER_STARTING.
2614 if (status <= SERVER_READY && !ps->quiescing && !ps->not_accepting
2615 && ps->generation == retained->mpm->my_generation
2616 && ps->bucket == child_bucket)
2618 ++idle_thread_count;
2620 if (status >= SERVER_READY && status < SERVER_GRACEFUL) {
2621 ++child_threads_active;
2626 active_thread_count += child_threads_active;
2627 if (!ps->pid && free_length < retained->idle_spawn_rate[child_bucket])
2628 free_slots[free_length++] = i;
2629 else if (child_threads_active == threads_per_child)
2630 had_healthy_child = 1;
2633 if (retained->sick_child_detected) {
2634 if (had_healthy_child) {
2635 /* Assume this is a transient error, even though it may not be. Leave
2636 * the server up in case it is able to serve some requests or the
2637 * problem will be resolved.
2639 retained->sick_child_detected = 0;
2642 /* looks like a basket case, as no child ever fully initialized; give up.
2644 retained->mpm->shutdown_pending = 1;
2646 ap_log_error(APLOG_MARK, APLOG_ALERT, 0,
2647 ap_server_conf, APLOGNO(02324)
2648 "A resource shortage or other unrecoverable failure "
2649 "was encountered before any child process initialized "
2650 "successfully... httpd is exiting!");
2651 /* the child already logged the failure details */
2656 retained->max_daemons_limit = last_non_dead + 1;
2658 if (idle_thread_count > max_spare_threads / num_buckets)
2661 * Child processes that we ask to shut down won't die immediately
2662 * but may stay around for a long time when they finish their
2663 * requests. If the server load changes many times, many such
2664 * gracefully finishing processes may accumulate, filling up the
2665 * scoreboard. To avoid running out of scoreboard entries, we
2666 * don't shut down more processes when the total number of processes
2669 * XXX It would be nice if we could
2670 * XXX - kill processes without keepalive connections first
2671 * XXX - tell children to stop accepting new connections, and
2672 * XXX depending on server load, later be able to resurrect them
2675 if (retained->total_daemons <= active_daemons_limit &&
2676 retained->total_daemons < server_limit) {
2677 /* Kill off one child */
2678 ap_mpm_podx_signal(all_buckets[child_bucket].pod,
2679 AP_MPM_PODX_GRACEFUL);
2680 retained->idle_spawn_rate[child_bucket] = 1;
2683 ap_log_error(APLOG_MARK, APLOG_TRACE5, 0, ap_server_conf,
2684 "Not shutting down child: total daemons %d / "
2685 "active limit %d / ServerLimit %d",
2686 retained->total_daemons, active_daemons_limit,
2690 else if (idle_thread_count < min_spare_threads / num_buckets) {
2691 if (active_thread_count >= max_workers) {
2692 if (!retained->maxclients_reported) {
2693 /* only report this condition once */
2694 ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, APLOGNO(00484)
2695 "server reached MaxRequestWorkers setting, "
2696 "consider raising the MaxRequestWorkers "
2698 retained->maxclients_reported = 1;
2700 retained->idle_spawn_rate[child_bucket] = 1;
2702 else if (free_length == 0) { /* scoreboard is full, can't fork */
2703 ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, APLOGNO(03490)
2704 "scoreboard is full, not at MaxRequestWorkers."
2705 "Increase ServerLimit.");
2706 retained->idle_spawn_rate[child_bucket] = 1;
2709 if (free_length > retained->idle_spawn_rate[child_bucket]) {
2710 free_length = retained->idle_spawn_rate[child_bucket];
2712 if (retained->idle_spawn_rate[child_bucket] >= 8) {
2713 ap_log_error(APLOG_MARK, APLOG_INFO, 0, ap_server_conf, APLOGNO(00486)
2714 "server seems busy, (you may need "
2715 "to increase StartServers, ThreadsPerChild "
2716 "or Min/MaxSpareThreads), "
2717 "spawning %d children, there are around %d idle "
2718 "threads, %d active children, and %d children "
2719 "that are shutting down", free_length,
2720 idle_thread_count, active_daemons,
2721 retained->total_daemons);
2723 for (i = 0; i < free_length; ++i) {
2724 ap_log_error(APLOG_MARK, APLOG_TRACE5, 0, ap_server_conf,
2725 "Spawning new child: slot %d active / "
2726 "total daemons: %d/%d",
2727 free_slots[i], active_daemons,
2728 retained->total_daemons);
2729 make_child(ap_server_conf, free_slots[i], child_bucket);
2731 /* the next time around we want to spawn twice as many if this
2732 * wasn't good enough, but not if we've just done a graceful
2734 if (retained->hold_off_on_exponential_spawning) {
2735 --retained->hold_off_on_exponential_spawning;
2737 else if (retained->idle_spawn_rate[child_bucket]
2738 < MAX_SPAWN_RATE / num_buckets) {
2739 retained->idle_spawn_rate[child_bucket] *= 2;
2744 retained->idle_spawn_rate[child_bucket] = 1;
2748 static void server_main_loop(int remaining_children_to_start, int num_buckets)
2751 apr_exit_why_e exitwhy;
2752 int status, processed_status;
2756 while (!retained->mpm->restart_pending && !retained->mpm->shutdown_pending) {
2757 ap_wait_or_timeout(&exitwhy, &status, &pid, pconf, ap_server_conf);
2759 if (pid.pid != -1) {
2760 processed_status = ap_process_child_status(&pid, exitwhy, status);
2761 child_slot = ap_find_child_by_pid(&pid);
2762 if (processed_status == APEXIT_CHILDFATAL) {
2763 /* fix race condition found in PR 39311
2764 * A child created at the same time as a graceful happens
2765 * can find the lock missing and create a fatal error.
2766 * It is not fatal for the last generation to be in this state.
2769 || ap_get_scoreboard_process(child_slot)->generation
2770 == retained->mpm->my_generation) {
2771 retained->mpm->shutdown_pending = 1;
2774 * total_daemons counting will be off now, but as we
2775 * are shutting down, that is not an issue anymore.
2780 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ap_server_conf, APLOGNO(00487)
2781 "Ignoring fatal error in child of previous "
2782 "generation (pid %ld).",
2784 retained->sick_child_detected = 1;
2787 else if (processed_status == APEXIT_CHILDSICK) {
2788 /* tell perform_idle_server_maintenance to check into this
2789 * on the next timer pop
2791 retained->sick_child_detected = 1;
2793 /* non-fatal death... note that it's gone in the scoreboard. */
2794 if (child_slot >= 0) {
2797 for (i = 0; i < threads_per_child; i++)
2798 ap_update_child_status_from_indexes(child_slot, i,
2801 event_note_child_killed(child_slot, 0, 0);
2802 ps = &ap_scoreboard_image->parent[child_slot];
2806 /* NOTE: We don't dec in the (child_slot < 0) case! */
2807 retained->total_daemons--;
2808 if (processed_status == APEXIT_CHILDSICK) {
2809 /* resource shortage, minimize the fork rate */
2810 retained->idle_spawn_rate[ps->bucket] = 1;
2812 else if (remaining_children_to_start) {
2813 /* we're still doing a 1-for-1 replacement of dead
2814 * children with new children
2816 make_child(ap_server_conf, child_slot, ps->bucket);
2817 --remaining_children_to_start;
2820 #if APR_HAS_OTHER_CHILD
2821 else if (apr_proc_other_child_alert(&pid, APR_OC_REASON_DEATH,
2826 else if (retained->mpm->was_graceful) {
2827 /* Great, we've probably just lost a slot in the
2828 * scoreboard. Somehow we don't know about this child.
2830 ap_log_error(APLOG_MARK, APLOG_WARNING, 0,
2831 ap_server_conf, APLOGNO(00488)
2832 "long lost child came home! (pid %ld)",
2835 /* Don't perform idle maintenance when a child dies,
2836 * only do it when there's a timeout. Remember only a
2837 * finite number of children can die, and it's pretty
2838 * pathological for a lot to die suddenly.
2842 else if (remaining_children_to_start) {
2843 /* we hit a 1 second timeout in which none of the previous
2844 * generation of children needed to be reaped... so assume
2845 * they're all done, and pick up the slack if any is left.
2847 startup_children(remaining_children_to_start);
2848 remaining_children_to_start = 0;
2849 /* In any event we really shouldn't do the code below because
2850 * few of the servers we just started are in the IDLE state
2851 * yet, so we'd mistakenly create an extra server.
2856 for (i = 0; i < num_buckets; i++) {
2857 perform_idle_server_maintenance(i, num_buckets);
2862 static int event_run(apr_pool_t * _pconf, apr_pool_t * plog, server_rec * s)
2864 int num_buckets = retained->mpm->num_buckets;
2865 int remaining_children_to_start;
2868 ap_log_pid(pconf, ap_pid_fname);
2870 if (!retained->mpm->was_graceful) {
2871 if (ap_run_pre_mpm(s->process->pool, SB_SHARED) != OK) {
2872 retained->mpm->mpm_state = AP_MPMQ_STOPPING;
2875 /* fix the generation number in the global score; we just got a new,
2876 * cleared scoreboard
2878 ap_scoreboard_image->global->running_generation = retained->mpm->my_generation;
2882 ap_fatal_signal_setup(ap_server_conf, pconf);
2884 ap_unixd_mpm_set_signals(pconf, one_process);
2886 /* Don't thrash since num_buckets depends on the
2887 * system and the number of online CPU cores...
2889 if (active_daemons_limit < num_buckets)
2890 active_daemons_limit = num_buckets;
2891 if (ap_daemons_to_start < num_buckets)
2892 ap_daemons_to_start = num_buckets;
2893 /* We want to create as much children at a time as the number of buckets,
2894 * so to optimally accept connections (evenly distributed across buckets).
2895 * Thus min_spare_threads should at least maintain num_buckets children,
2896 * and max_spare_threads allow num_buckets more children w/o triggering
2897 * immediately (e.g. num_buckets idle threads margin, one per bucket).
2899 if (min_spare_threads < threads_per_child * (num_buckets - 1) + num_buckets)
2900 min_spare_threads = threads_per_child * (num_buckets - 1) + num_buckets;
2901 if (max_spare_threads < min_spare_threads + (threads_per_child + 1) * num_buckets)
2902 max_spare_threads = min_spare_threads + (threads_per_child + 1) * num_buckets;
2904 /* If we're doing a graceful_restart then we're going to see a lot
2905 * of children exiting immediately when we get into the main loop
2906 * below (because we just sent them AP_SIG_GRACEFUL). This happens pretty
2907 * rapidly... and for each one that exits we may start a new one, until
2908 * there are at least min_spare_threads idle threads, counting across
2909 * all children. But we may be permitted to start more children than
2910 * that, so we'll just keep track of how many we're
2911 * supposed to start up without the 1 second penalty between each fork.
2913 remaining_children_to_start = ap_daemons_to_start;
2914 if (remaining_children_to_start > active_daemons_limit) {
2915 remaining_children_to_start = active_daemons_limit;
2917 if (!retained->mpm->was_graceful) {
2918 startup_children(remaining_children_to_start);
2919 remaining_children_to_start = 0;
2922 /* give the system some time to recover before kicking into
2923 * exponential mode */
2924 retained->hold_off_on_exponential_spawning = 10;
2927 ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, APLOGNO(00489)
2928 "%s configured -- resuming normal operations",
2929 ap_get_server_description());
2930 ap_log_error(APLOG_MARK, APLOG_INFO, 0, ap_server_conf, APLOGNO(00490)
2931 "Server built: %s", ap_get_server_built());
2932 ap_log_command_line(plog, s);
2933 ap_log_mpm_common(s);
2935 retained->mpm->mpm_state = AP_MPMQ_RUNNING;
2937 server_main_loop(remaining_children_to_start, num_buckets);
2938 retained->mpm->mpm_state = AP_MPMQ_STOPPING;
2940 if (retained->mpm->shutdown_pending && retained->mpm->is_ungraceful) {
2941 /* Time to shut down:
2942 * Kill child processes, tell them to call child_exit, etc...
2944 for (i = 0; i < num_buckets; i++) {
2945 ap_mpm_podx_killpg(all_buckets[i].pod, active_daemons_limit,
2946 AP_MPM_PODX_RESTART);
2948 ap_reclaim_child_processes(1, /* Start with SIGTERM */
2949 event_note_child_killed);
2952 /* cleanup pid file on normal shutdown */
2953 ap_remove_pid(pconf, ap_pid_fname);
2954 ap_log_error(APLOG_MARK, APLOG_NOTICE, 0,
2955 ap_server_conf, APLOGNO(00491) "caught SIGTERM, shutting down");
2961 if (retained->mpm->shutdown_pending) {
2962 /* Time to gracefully shut down:
2963 * Kill child processes, tell them to call child_exit, etc...
2965 int active_children;
2967 apr_time_t cutoff = 0;
2969 /* Close our listeners, and then ask our children to do same */
2970 ap_close_listeners();
2971 for (i = 0; i < num_buckets; i++) {
2972 ap_mpm_podx_killpg(all_buckets[i].pod, active_daemons_limit,
2973 AP_MPM_PODX_GRACEFUL);
2975 ap_relieve_child_processes(event_note_child_killed);
2978 /* cleanup pid file on normal shutdown */
2979 ap_remove_pid(pconf, ap_pid_fname);
2980 ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, APLOGNO(00492)
2981 "caught " AP_SIG_GRACEFUL_STOP_STRING
2982 ", shutting down gracefully");
2985 if (ap_graceful_shutdown_timeout) {
2986 cutoff = apr_time_now() +
2987 apr_time_from_sec(ap_graceful_shutdown_timeout);
2990 /* Don't really exit until each child has finished */
2991 retained->mpm->shutdown_pending = 0;
2993 /* Pause for a second */
2994 apr_sleep(apr_time_from_sec(1));
2996 /* Relieve any children which have now exited */
2997 ap_relieve_child_processes(event_note_child_killed);
2999 active_children = 0;
3000 for (index = 0; index < retained->max_daemons_limit; ++index) {
3001 if (ap_mpm_safe_kill(MPM_CHILD_PID(index), 0) == APR_SUCCESS) {
3002 active_children = 1;
3003 /* Having just one child is enough to stay around */
3007 } while (!retained->mpm->shutdown_pending && active_children &&
3008 (!ap_graceful_shutdown_timeout || apr_time_now() < cutoff));
3010 /* We might be here because we received SIGTERM, either
3011 * way, try and make sure that all of our processes are
3014 for (i = 0; i < num_buckets; i++) {
3015 ap_mpm_podx_killpg(all_buckets[i].pod, active_daemons_limit,
3016 AP_MPM_PODX_RESTART);
3018 ap_reclaim_child_processes(1, event_note_child_killed);
3023 /* we've been told to restart */
3025 /* not worth thinking about */
3029 /* advance to the next generation */
3030 /* XXX: we really need to make sure this new generation number isn't in
3031 * use by any of the children.
3033 ++retained->mpm->my_generation;
3034 ap_scoreboard_image->global->running_generation = retained->mpm->my_generation;
3036 if (!retained->mpm->is_ungraceful) {
3037 ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, APLOGNO(00493)
3038 AP_SIG_GRACEFUL_STRING
3039 " received. Doing graceful restart");
3040 /* wake up the children...time to die. But we'll have more soon */
3041 for (i = 0; i < num_buckets; i++) {
3042 ap_mpm_podx_killpg(all_buckets[i].pod, active_daemons_limit,
3043 AP_MPM_PODX_GRACEFUL);
3046 /* This is mostly for debugging... so that we know what is still
3047 * gracefully dealing with existing request.
3052 /* Kill 'em all. Since the child acts the same on the parents SIGTERM
3053 * and a SIGHUP, we may as well use the same signal, because some user
3054 * pthreads are stealing signals from us left and right.
3056 for (i = 0; i < num_buckets; i++) {
3057 ap_mpm_podx_killpg(all_buckets[i].pod, active_daemons_limit,
3058 AP_MPM_PODX_RESTART);
3061 ap_reclaim_child_processes(1, /* Start with SIGTERM */
3062 event_note_child_killed);
3063 ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, APLOGNO(00494)
3064 "SIGHUP received. Attempting to restart");
3072 static void setup_slave_conn(conn_rec *c, void *csd)
3074 event_conn_state_t *mcs;
3075 event_conn_state_t *cs;
3077 mcs = ap_get_module_config(c->master->conn_config, &mpm_event_module);
3079 cs = apr_pcalloc(c->pool, sizeof(*cs));
3085 cs->bucket_alloc = c->bucket_alloc;
3088 cs->pub.state = CONN_STATE_READ_REQUEST_LINE;
3089 cs->pub.sense = CONN_SENSE_DEFAULT;
3092 ap_set_module_config(c->conn_config, &mpm_event_module, cs);
3095 static int event_pre_connection(conn_rec *c, void *csd)
3097 if (c->master && (!c->cs || c->cs == c->master->cs)) {
3098 setup_slave_conn(c, csd);
3103 static int event_protocol_switch(conn_rec *c, request_rec *r, server_rec *s,
3104 const char *protocol)
3107 /* connection based switching of protocol, set the correct server
3108 * configuration, so that timeouts, keepalives and such are used
3109 * for the server that the connection was switched on.
3110 * Normally, we set this on post_read_request, but on a protocol
3111 * other than http/1.1, this might never happen.
3113 event_conn_state_t *cs;
3115 cs = ap_get_module_config(c->conn_config, &mpm_event_module);
3116 cs->sc = ap_get_module_config(s->module_config, &mpm_event_module);
3121 /* This really should be a post_config hook, but the error log is already
3122 * redirected by that point, so we need to do this in the open_logs phase.
3124 static int event_open_logs(apr_pool_t * p, apr_pool_t * plog,
3125 apr_pool_t * ptemp, server_rec * s)
3128 int level_flags = 0;
3129 int num_buckets = 0;
3130 ap_listen_rec **listen_buckets;
3136 /* the reverse of pre_config, we want this only the first time around */
3137 if (retained->mpm->module_loads == 1) {
3139 level_flags |= APLOG_STARTUP;
3142 if ((num_listensocks = ap_setup_listeners(ap_server_conf)) < 1) {
3143 ap_log_error(APLOG_MARK, APLOG_ALERT | level_flags, 0,
3144 (startup ? NULL : s),
3145 "no listening sockets available, shutting down");
3152 else if (retained->mpm->was_graceful) {
3153 /* Preserve the number of buckets on graceful restarts. */
3154 num_buckets = retained->mpm->num_buckets;
3156 if ((rv = ap_duplicate_listeners(pconf, ap_server_conf,
3157 &listen_buckets, &num_buckets))) {
3158 ap_log_error(APLOG_MARK, APLOG_CRIT | level_flags, rv,
3159 (startup ? NULL : s),
3160 "could not duplicate listeners");
3164 all_buckets = apr_pcalloc(pconf, num_buckets * sizeof(*all_buckets));
3165 for (i = 0; i < num_buckets; i++) {
3166 if (!one_process && /* no POD in one_process mode */
3167 (rv = ap_mpm_podx_open(pconf, &all_buckets[i].pod))) {
3168 ap_log_error(APLOG_MARK, APLOG_CRIT | level_flags, rv,
3169 (startup ? NULL : s),
3170 "could not open pipe-of-death");
3173 all_buckets[i].listeners = listen_buckets[i];
3176 if (retained->mpm->max_buckets < num_buckets) {
3177 int new_max, *new_ptr;
3178 new_max = retained->mpm->max_buckets * 2;
3179 if (new_max < num_buckets) {
3180 new_max = num_buckets;
3182 new_ptr = (int *)apr_palloc(ap_pglobal, new_max * sizeof(int));
3183 memcpy(new_ptr, retained->idle_spawn_rate,
3184 retained->mpm->num_buckets * sizeof(int));
3185 retained->idle_spawn_rate = new_ptr;
3186 retained->mpm->max_buckets = new_max;
3188 if (retained->mpm->num_buckets < num_buckets) {
3190 /* If new buckets are added, set their idle spawn rate to
3191 * the highest so far, so that they get filled as quickly
3192 * as the existing ones.
3194 for (i = 0; i < retained->mpm->num_buckets; i++) {
3195 if (rate_max < retained->idle_spawn_rate[i]) {
3196 rate_max = retained->idle_spawn_rate[i];
3199 for (/* up to date i */; i < num_buckets; i++) {
3200 retained->idle_spawn_rate[i] = rate_max;
3203 retained->mpm->num_buckets = num_buckets;
3206 srand((unsigned int)apr_time_now());
3210 static int event_pre_config(apr_pool_t * pconf, apr_pool_t * plog,
3213 int no_detach, debug, foreground;
3215 const char *userdata_key = "mpm_event_module";
3216 int test_atomics = 0;
3218 debug = ap_exists_config_define("DEBUG");
3221 foreground = one_process = 1;
3225 one_process = ap_exists_config_define("ONE_PROCESS");
3226 no_detach = ap_exists_config_define("NO_DETACH");
3227 foreground = ap_exists_config_define("FOREGROUND");
3230 retained = ap_retained_data_get(userdata_key);
3232 retained = ap_retained_data_create(userdata_key, sizeof(*retained));
3233 retained->mpm = ap_unixd_mpm_get_retained_data();
3234 retained->max_daemons_limit = -1;
3235 if (retained->mpm->module_loads) {
3239 retained->mpm->mpm_state = AP_MPMQ_STARTING;
3240 if (retained->mpm->baton != retained) {
3241 retained->mpm->was_graceful = 0;
3242 retained->mpm->baton = retained;
3244 ++retained->mpm->module_loads;
3246 /* test once for correct operation of fdqueue */
3247 if (test_atomics || retained->mpm->module_loads == 2) {
3248 static apr_uint32_t foo1, foo2;
3250 apr_atomic_set32(&foo1, 100);
3251 foo2 = apr_atomic_add32(&foo1, -10);
3252 if (foo2 != 100 || foo1 != 90) {
3253 ap_log_error(APLOG_MARK, APLOG_CRIT, 0, NULL, APLOGNO(02405)
3254 "atomics not working as expected - add32 of negative number");
3255 return HTTP_INTERNAL_SERVER_ERROR;
3259 /* sigh, want this only the second time around */
3260 if (retained->mpm->module_loads == 2) {
3261 rv = apr_pollset_create(&event_pollset, 1, plog,
3262 APR_POLLSET_THREADSAFE | APR_POLLSET_NOCOPY);
3263 if (rv != APR_SUCCESS) {
3264 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL, APLOGNO(00495)
3265 "Couldn't create a Thread Safe Pollset. "
3266 "Is it supported on your platform?"
3267 "Also check system or user limits!");
3268 return HTTP_INTERNAL_SERVER_ERROR;
3270 apr_pollset_destroy(event_pollset);
3272 if (!one_process && !foreground) {
3273 /* before we detach, setup crash handlers to log to errorlog */
3274 ap_fatal_signal_setup(ap_server_conf, pconf);
3275 rv = apr_proc_detach(no_detach ? APR_PROC_DETACH_FOREGROUND
3276 : APR_PROC_DETACH_DAEMONIZE);
3277 if (rv != APR_SUCCESS) {
3278 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL, APLOGNO(00496)
3279 "apr_proc_detach failed");
3280 return HTTP_INTERNAL_SERVER_ERROR;
3285 parent_pid = ap_my_pid = getpid();
3287 ap_listen_pre_config();
3288 ap_daemons_to_start = DEFAULT_START_DAEMON;
3289 min_spare_threads = DEFAULT_MIN_FREE_DAEMON * DEFAULT_THREADS_PER_CHILD;
3290 max_spare_threads = DEFAULT_MAX_FREE_DAEMON * DEFAULT_THREADS_PER_CHILD;
3291 server_limit = DEFAULT_SERVER_LIMIT;
3292 thread_limit = DEFAULT_THREAD_LIMIT;
3293 active_daemons_limit = server_limit;
3294 threads_per_child = DEFAULT_THREADS_PER_CHILD;
3295 max_workers = active_daemons_limit * threads_per_child;
3296 defer_linger_chain = NULL;
3297 had_healthy_child = 0;
3298 ap_extended_status = 0;
3303 static int event_post_config(apr_pool_t *pconf, apr_pool_t *plog,
3304 apr_pool_t *ptemp, server_rec *s)
3307 struct timeout_queue *tail, *q;
3311 /* Not needed in pre_config stage */
3312 if (ap_state_query(AP_SQ_MAIN_STATE) == AP_SQ_MS_CREATE_PRE_CONFIG) {
3316 wc.tail = ka.tail = NULL;
3317 wc.hash = apr_hash_make(ptemp);
3318 ka.hash = apr_hash_make(ptemp);
3320 linger_q = TO_QUEUE_MAKE(pconf, apr_time_from_sec(MAX_SECS_TO_LINGER),
3322 short_linger_q = TO_QUEUE_MAKE(pconf, apr_time_from_sec(SECONDS_TO_LINGER),
3325 for (; s; s = s->next) {
3326 event_srv_cfg *sc = apr_pcalloc(pconf, sizeof *sc);
3328 ap_set_module_config(s->module_config, &mpm_event_module, sc);
3330 /* The main server uses the global queues */
3331 wc.q = TO_QUEUE_MAKE(pconf, s->timeout, NULL);
3332 apr_hash_set(wc.hash, &s->timeout, sizeof s->timeout, wc.q);
3333 wc.tail = write_completion_q = wc.q;
3335 ka.q = TO_QUEUE_MAKE(pconf, s->keep_alive_timeout, NULL);
3336 apr_hash_set(ka.hash, &s->keep_alive_timeout,
3337 sizeof s->keep_alive_timeout, ka.q);
3338 ka.tail = keepalive_q = ka.q;
3341 /* The vhosts use any existing queue with the same timeout,
3342 * or their own queue(s) if there isn't */
3343 wc.q = apr_hash_get(wc.hash, &s->timeout, sizeof s->timeout);
3345 wc.q = TO_QUEUE_MAKE(pconf, s->timeout, wc.tail);
3346 apr_hash_set(wc.hash, &s->timeout, sizeof s->timeout, wc.q);
3347 wc.tail = wc.tail->next = wc.q;
3350 ka.q = apr_hash_get(ka.hash, &s->keep_alive_timeout,
3351 sizeof s->keep_alive_timeout);
3353 ka.q = TO_QUEUE_MAKE(pconf, s->keep_alive_timeout, ka.tail);
3354 apr_hash_set(ka.hash, &s->keep_alive_timeout,
3355 sizeof s->keep_alive_timeout, ka.q);
3356 ka.tail = ka.tail->next = ka.q;
3366 static int event_check_config(apr_pool_t *p, apr_pool_t *plog,
3367 apr_pool_t *ptemp, server_rec *s)
3371 /* the reverse of pre_config, we want this only the first time around */
3372 if (retained->mpm->module_loads == 1) {
3376 if (server_limit > MAX_SERVER_LIMIT) {
3378 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00497)
3379 "WARNING: ServerLimit of %d exceeds compile-time "
3380 "limit of %d servers, decreasing to %d.",
3381 server_limit, MAX_SERVER_LIMIT, MAX_SERVER_LIMIT);
3383 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00498)
3384 "ServerLimit of %d exceeds compile-time limit "
3385 "of %d, decreasing to match",
3386 server_limit, MAX_SERVER_LIMIT);
3388 server_limit = MAX_SERVER_LIMIT;
3390 else if (server_limit < 1) {
3392 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00499)
3393 "WARNING: ServerLimit of %d not allowed, "
3394 "increasing to 1.", server_limit);
3396 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00500)
3397 "ServerLimit of %d not allowed, increasing to 1",
3403 /* you cannot change ServerLimit across a restart; ignore
3406 if (!retained->first_server_limit) {
3407 retained->first_server_limit = server_limit;
3409 else if (server_limit != retained->first_server_limit) {
3410 /* don't need a startup console version here */
3411 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00501)
3412 "changing ServerLimit to %d from original value of %d "
3413 "not allowed during restart",
3414 server_limit, retained->first_server_limit);
3415 server_limit = retained->first_server_limit;
3418 if (thread_limit > MAX_THREAD_LIMIT) {
3420 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00502)
3421 "WARNING: ThreadLimit of %d exceeds compile-time "
3422 "limit of %d threads, decreasing to %d.",
3423 thread_limit, MAX_THREAD_LIMIT, MAX_THREAD_LIMIT);
3425 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00503)
3426 "ThreadLimit of %d exceeds compile-time limit "
3427 "of %d, decreasing to match",
3428 thread_limit, MAX_THREAD_LIMIT);
3430 thread_limit = MAX_THREAD_LIMIT;
3432 else if (thread_limit < 1) {
3434 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00504)
3435 "WARNING: ThreadLimit of %d not allowed, "
3436 "increasing to 1.", thread_limit);
3438 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00505)
3439 "ThreadLimit of %d not allowed, increasing to 1",
3445 /* you cannot change ThreadLimit across a restart; ignore
3448 if (!retained->first_thread_limit) {
3449 retained->first_thread_limit = thread_limit;
3451 else if (thread_limit != retained->first_thread_limit) {
3452 /* don't need a startup console version here */
3453 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00506)
3454 "changing ThreadLimit to %d from original value of %d "
3455 "not allowed during restart",
3456 thread_limit, retained->first_thread_limit);
3457 thread_limit = retained->first_thread_limit;
3460 if (threads_per_child > thread_limit) {
3462 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00507)
3463 "WARNING: ThreadsPerChild of %d exceeds ThreadLimit "
3464 "of %d threads, decreasing to %d. "
3465 "To increase, please see the ThreadLimit directive.",
3466 threads_per_child, thread_limit, thread_limit);
3468 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00508)
3469 "ThreadsPerChild of %d exceeds ThreadLimit "
3470 "of %d, decreasing to match",
3471 threads_per_child, thread_limit);
3473 threads_per_child = thread_limit;
3475 else if (threads_per_child < 1) {
3477 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00509)
3478 "WARNING: ThreadsPerChild of %d not allowed, "
3479 "increasing to 1.", threads_per_child);
3481 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00510)
3482 "ThreadsPerChild of %d not allowed, increasing to 1",
3485 threads_per_child = 1;
3488 if (max_workers < threads_per_child) {
3490 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00511)
3491 "WARNING: MaxRequestWorkers of %d is less than "
3492 "ThreadsPerChild of %d, increasing to %d. "
3493 "MaxRequestWorkers must be at least as large "
3494 "as the number of threads in a single server.",
3495 max_workers, threads_per_child, threads_per_child);
3497 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00512)
3498 "MaxRequestWorkers of %d is less than ThreadsPerChild "
3499 "of %d, increasing to match",
3500 max_workers, threads_per_child);
3502 max_workers = threads_per_child;
3505 active_daemons_limit = max_workers / threads_per_child;
3507 if (max_workers % threads_per_child) {
3508 int tmp_max_workers = active_daemons_limit * threads_per_child;
3511 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00513)
3512 "WARNING: MaxRequestWorkers of %d is not an integer "
3513 "multiple of ThreadsPerChild of %d, decreasing to nearest "
3514 "multiple %d, for a maximum of %d servers.",
3515 max_workers, threads_per_child, tmp_max_workers,
3516 active_daemons_limit);
3518 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00514)
3519 "MaxRequestWorkers of %d is not an integer multiple "
3520 "of ThreadsPerChild of %d, decreasing to nearest "
3521 "multiple %d", max_workers, threads_per_child,
3524 max_workers = tmp_max_workers;
3527 if (active_daemons_limit > server_limit) {
3529 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00515)
3530 "WARNING: MaxRequestWorkers of %d would require %d servers "
3531 "and would exceed ServerLimit of %d, decreasing to %d. "
3532 "To increase, please see the ServerLimit directive.",
3533 max_workers, active_daemons_limit, server_limit,
3534 server_limit * threads_per_child);
3536 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00516)
3537 "MaxRequestWorkers of %d would require %d servers and "
3538 "exceed ServerLimit of %d, decreasing to %d",
3539 max_workers, active_daemons_limit, server_limit,
3540 server_limit * threads_per_child);
3542 active_daemons_limit = server_limit;
3545 /* ap_daemons_to_start > active_daemons_limit checked in ap_mpm_run() */
3546 if (ap_daemons_to_start < 1) {
3548 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00517)
3549 "WARNING: StartServers of %d not allowed, "
3550 "increasing to 1.", ap_daemons_to_start);
3552 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00518)
3553 "StartServers of %d not allowed, increasing to 1",
3554 ap_daemons_to_start);
3556 ap_daemons_to_start = 1;
3559 if (min_spare_threads < 1) {
3561 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00519)
3562 "WARNING: MinSpareThreads of %d not allowed, "
3563 "increasing to 1 to avoid almost certain server "
3564 "failure. Please read the documentation.",
3567 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00520)
3568 "MinSpareThreads of %d not allowed, increasing to 1",
3571 min_spare_threads = 1;
3574 /* max_spare_threads < min_spare_threads + threads_per_child
3575 * checked in ap_mpm_run()
3581 static void event_hooks(apr_pool_t * p)
3583 /* Our open_logs hook function must run before the core's, or stderr
3584 * will be redirected to a file, and the messages won't print to the
3587 static const char *const aszSucc[] = { "core.c", NULL };
3590 ap_hook_open_logs(event_open_logs, NULL, aszSucc, APR_HOOK_REALLY_FIRST);
3591 /* we need to set the MPM state before other pre-config hooks use MPM query
3592 * to retrieve it, so register as REALLY_FIRST
3594 ap_hook_pre_config(event_pre_config, NULL, NULL, APR_HOOK_REALLY_FIRST);
3595 ap_hook_post_config(event_post_config, NULL, NULL, APR_HOOK_MIDDLE);
3596 ap_hook_check_config(event_check_config, NULL, NULL, APR_HOOK_MIDDLE);
3597 ap_hook_mpm(event_run, NULL, NULL, APR_HOOK_MIDDLE);
3598 ap_hook_mpm_query(event_query, NULL, NULL, APR_HOOK_MIDDLE);
3599 ap_hook_mpm_register_timed_callback(event_register_timed_callback, NULL, NULL,
3601 ap_hook_pre_read_request(event_pre_read_request, NULL, NULL, APR_HOOK_MIDDLE);
3602 ap_hook_post_read_request(event_post_read_request, NULL, NULL, APR_HOOK_MIDDLE);
3603 ap_hook_mpm_get_name(event_get_name, NULL, NULL, APR_HOOK_MIDDLE);
3605 ap_hook_pre_connection(event_pre_connection, NULL, NULL, APR_HOOK_REALLY_FIRST);
3606 ap_hook_protocol_switch(event_protocol_switch, NULL, NULL, APR_HOOK_REALLY_FIRST);
3609 static const char *set_daemons_to_start(cmd_parms *cmd, void *dummy,
3612 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3617 ap_daemons_to_start = atoi(arg);
3621 static const char *set_min_spare_threads(cmd_parms * cmd, void *dummy,
3624 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3629 min_spare_threads = atoi(arg);
3633 static const char *set_max_spare_threads(cmd_parms * cmd, void *dummy,
3636 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3641 max_spare_threads = atoi(arg);
3645 static const char *set_max_workers(cmd_parms * cmd, void *dummy,
3648 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3652 if (!strcasecmp(cmd->cmd->name, "MaxClients")) {
3653 ap_log_error(APLOG_MARK, APLOG_INFO, 0, NULL, APLOGNO(00521)
3654 "MaxClients is deprecated, use MaxRequestWorkers "
3657 max_workers = atoi(arg);
3661 static const char *set_threads_per_child(cmd_parms * cmd, void *dummy,
3664 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3669 threads_per_child = atoi(arg);
3672 static const char *set_server_limit (cmd_parms *cmd, void *dummy, const char *arg)
3674 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3679 server_limit = atoi(arg);
3683 static const char *set_thread_limit(cmd_parms * cmd, void *dummy,
3686 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3691 thread_limit = atoi(arg);
3695 static const char *set_worker_factor(cmd_parms * cmd, void *dummy,
3700 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3705 val = strtod(arg, &endptr);
3707 return "error parsing value";
3710 return "AsyncRequestWorkerFactor argument must be a positive number";
3712 worker_factor = val * WORKER_FACTOR_SCALE;
3713 if (worker_factor == 0)
3719 static const command_rec event_cmds[] = {
3721 AP_INIT_TAKE1("StartServers", set_daemons_to_start, NULL, RSRC_CONF,
3722 "Number of child processes launched at server startup"),
3723 AP_INIT_TAKE1("ServerLimit", set_server_limit, NULL, RSRC_CONF,
3724 "Maximum number of child processes for this run of Apache"),
3725 AP_INIT_TAKE1("MinSpareThreads", set_min_spare_threads, NULL, RSRC_CONF,
3726 "Minimum number of idle threads, to handle request spikes"),
3727 AP_INIT_TAKE1("MaxSpareThreads", set_max_spare_threads, NULL, RSRC_CONF,
3728 "Maximum number of idle threads"),
3729 AP_INIT_TAKE1("MaxClients", set_max_workers, NULL, RSRC_CONF,
3730 "Deprecated name of MaxRequestWorkers"),
3731 AP_INIT_TAKE1("MaxRequestWorkers", set_max_workers, NULL, RSRC_CONF,
3732 "Maximum number of threads alive at the same time"),
3733 AP_INIT_TAKE1("ThreadsPerChild", set_threads_per_child, NULL, RSRC_CONF,
3734 "Number of threads each child creates"),
3735 AP_INIT_TAKE1("ThreadLimit", set_thread_limit, NULL, RSRC_CONF,
3736 "Maximum number of worker threads per child process for this "
3737 "run of Apache - Upper limit for ThreadsPerChild"),
3738 AP_INIT_TAKE1("AsyncRequestWorkerFactor", set_worker_factor, NULL, RSRC_CONF,
3739 "How many additional connects will be accepted per idle "
3741 AP_GRACEFUL_SHUTDOWN_TIMEOUT_COMMAND,
3745 AP_DECLARE_MODULE(mpm_event) = {
3747 NULL, /* hook to run before apache parses args */
3748 NULL, /* create per-directory config structure */
3749 NULL, /* merge per-directory config structures */
3750 NULL, /* create per-server config structure */
3751 NULL, /* merge per-server config structures */
3752 event_cmds, /* command apr_table_t */
3753 event_hooks /* register_hooks */