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 * signifigant 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 Listenting 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 not preform 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"
65 #if APR_HAVE_SYS_SOCKET_H
66 #include <sys/socket.h>
68 #if APR_HAVE_SYS_WAIT_H
71 #ifdef HAVE_SYS_PROCESSOR_H
72 #include <sys/processor.h> /* for bindprocessor() */
76 #error The Event MPM requires APR threads, but they are unavailable.
79 #include "ap_config.h"
81 #include "http_main.h"
83 #include "http_config.h" /* for read_config */
84 #include "http_core.h" /* for get_remote_host */
85 #include "http_connection.h"
88 #include "mpm_common.h"
89 #include "ap_listen.h"
90 #include "scoreboard.h"
92 #include "mpm_default.h"
93 #include "http_vhost.h"
97 #include <limits.h> /* for INT_MAX */
101 #include "mod_serf.h"
105 /* Limit on the total --- clients will be locked out if more servers than
106 * this are needed. It is intended solely to keep the server from crashing
107 * when things get out of hand.
109 * We keep a hard maximum number of servers, for two reasons --- first off,
110 * in case something goes seriously wrong, we want to stop the fork bomb
111 * short of actually crashing the machine we're running on by filling some
112 * kernel table. Secondly, it keeps the size of the scoreboard file small
113 * enough that we can read the whole thing without worrying too much about
116 #ifndef DEFAULT_SERVER_LIMIT
117 #define DEFAULT_SERVER_LIMIT 16
120 /* Admin can't tune ServerLimit beyond MAX_SERVER_LIMIT. We want
121 * some sort of compile-time limit to help catch typos.
123 #ifndef MAX_SERVER_LIMIT
124 #define MAX_SERVER_LIMIT 20000
127 /* Limit on the threads per process. Clients will be locked out if more than
130 * We keep this for one reason it keeps the size of the scoreboard file small
131 * enough that we can read the whole thing without worrying too much about
134 #ifndef DEFAULT_THREAD_LIMIT
135 #define DEFAULT_THREAD_LIMIT 64
138 /* Admin can't tune ThreadLimit beyond MAX_THREAD_LIMIT. We want
139 * some sort of compile-time limit to help catch typos.
141 #ifndef MAX_THREAD_LIMIT
142 #define MAX_THREAD_LIMIT 100000
145 #define MPM_CHILD_PID(i) (ap_scoreboard_image->parent[i].pid)
147 #if !APR_VERSION_AT_LEAST(1,4,0)
148 #define apr_time_from_msec(x) (x * 1000)
151 #ifndef MAX_SECS_TO_LINGER
152 #define MAX_SECS_TO_LINGER 30
154 #define SECONDS_TO_LINGER 2
157 * Actual definitions of config globals
160 static int threads_per_child = 0; /* Worker threads per child */
161 static int ap_daemons_to_start = 0;
162 static int min_spare_threads = 0;
163 static int max_spare_threads = 0;
164 static int ap_daemons_limit = 0;
165 static int max_clients = 0;
166 static int server_limit = 0;
167 static int thread_limit = 0;
168 static int dying = 0;
169 static int workers_may_exit = 0;
170 static int start_thread_may_exit = 0;
171 static int listener_may_exit = 0;
172 static int requests_this_child;
173 static int num_listensocks = 0;
174 static apr_uint32_t connection_count = 0;
175 static int resource_shortage = 0;
176 static fd_queue_t *worker_queue;
177 static fd_queue_info_t *worker_queue_info;
178 static int mpm_state = AP_MPMQ_STARTING;
180 static apr_thread_mutex_t *timeout_mutex;
181 APR_RING_HEAD(timeout_head_t, conn_state_t);
182 struct timeout_queue {
183 struct timeout_head_t head;
187 static struct timeout_queue write_completion_q, keepalive_q, linger_q,
189 static apr_pollfd_t *listener_pollfd;
192 * Macros for accessing struct timeout_queue.
193 * For TO_QUEUE_APPEND and TO_QUEUE_REMOVE, timeout_mutex must be held.
195 #define TO_QUEUE_APPEND(q, el) \
197 APR_RING_INSERT_TAIL(&(q).head, el, conn_state_t, timeout_list); \
201 #define TO_QUEUE_REMOVE(q, el) \
203 APR_RING_REMOVE(el, timeout_list); \
207 #define TO_QUEUE_INIT(q) \
209 APR_RING_INIT(&(q).head, conn_state_t, timeout_list); \
213 #define TO_QUEUE_ELEM_INIT(el) APR_RING_ELEM_INIT(el, timeout_list)
215 static apr_pollset_t *event_pollset;
219 apr_pollset_t *pollset;
223 static serf_context_t *g_serf;
226 /* The structure used to pass unique initialization info to each thread */
234 /* Structure used to pass information to the thread responsible for
235 * creating the rest of the threads.
239 apr_thread_t **threads;
240 apr_thread_t *listener;
242 apr_threadattr_t *threadattr;
258 } listener_poll_type;
260 /* data retained by event across load/unload of the module
261 * allocated on first call to pre-config hook; located on
262 * subsequent calls to pre-config hook
264 typedef struct event_retained_data {
265 int first_server_limit;
266 int first_thread_limit;
268 int sick_child_detected;
269 ap_generation_t my_generation;
270 int volatile is_graceful; /* set from signal handler */
271 int maxclients_reported;
273 * The max child slot ever assigned, preserved across restarts. Necessary
274 * to deal with MaxClients changes across AP_SIG_GRACEFUL restarts. We
275 * use this value to optimize routines that have to scan the entire
278 int max_daemons_limit;
280 * idle_spawn_rate is the number of children that will be spawned on the
281 * next maintenance cycle if there aren't enough idle servers. It is
282 * doubled up to MAX_SPAWN_RATE, and reset only when a cycle goes by
283 * without the need to spawn.
286 #ifndef MAX_SPAWN_RATE
287 #define MAX_SPAWN_RATE (32)
289 int hold_off_on_exponential_spawning;
290 } event_retained_data;
291 static event_retained_data *retained;
293 #define ID_FROM_CHILD_THREAD(c, t) ((c * thread_limit) + t)
295 static ap_event_pod_t *pod;
297 /* The event MPM respects a couple of runtime flags that can aid
298 * in debugging. Setting the -DNO_DETACH flag will prevent the root process
299 * from detaching from its controlling terminal. Additionally, setting
300 * the -DONE_PROCESS flag (which implies -DNO_DETACH) will get you the
301 * child_main loop running in the process which originally started up.
302 * This gives you a pretty nice debugging environment. (You'll get a SIGHUP
303 * early in standalone_main; just continue through. This is the server
304 * trying to kill off any child processes which it might have lying
305 * around --- Apache doesn't keep track of their pids, it just sends
306 * SIGHUP to the process group, ignoring it in the root process.
307 * Continue through and you'll be fine.).
310 static int one_process = 0;
313 int raise_sigstop_flags;
316 static apr_pool_t *pconf; /* Pool for config stuff */
317 static apr_pool_t *pchild; /* Pool for httpd child stuff */
319 static pid_t ap_my_pid; /* Linux getpid() doesn't work except in main
320 thread. Use this instead */
321 static pid_t parent_pid;
322 static apr_os_thread_t *listener_os_thread;
324 /* The LISTENER_SIGNAL signal will be sent from the main thread to the
325 * listener thread to wake it up for graceful termination (what a child
326 * process from an old generation does when the admin does "apachectl
327 * graceful"). This signal will be blocked in all threads of a child
328 * process except for the listener thread.
330 #define LISTENER_SIGNAL SIGHUP
332 /* An array of socket descriptors in use by each thread used to
333 * perform a non-graceful (forced) shutdown of the server.
335 static apr_socket_t **worker_sockets;
337 static void disable_listensocks(int process_slot)
340 for (i = 0; i < num_listensocks; i++) {
341 apr_pollset_remove(event_pollset, &listener_pollfd[i]);
343 ap_scoreboard_image->parent[process_slot].not_accepting = 1;
346 static void enable_listensocks(int process_slot)
349 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
350 "Accepting new connections again: "
351 "%u active conns, %u idle workers",
352 apr_atomic_read32(&connection_count),
353 ap_queue_info_get_idlers(worker_queue_info));
354 for (i = 0; i < num_listensocks; i++)
355 apr_pollset_add(event_pollset, &listener_pollfd[i]);
357 * XXX: This is not yet optimal. If many workers suddenly become available,
358 * XXX: the parent may kill some processes off too soon.
360 ap_scoreboard_image->parent[process_slot].not_accepting = 0;
363 static void close_worker_sockets(void)
366 for (i = 0; i < threads_per_child; i++) {
367 if (worker_sockets[i]) {
368 apr_socket_close(worker_sockets[i]);
369 worker_sockets[i] = NULL;
374 static void wakeup_listener(void)
376 listener_may_exit = 1;
377 if (!listener_os_thread) {
378 /* XXX there is an obscure path that this doesn't handle perfectly:
379 * right after listener thread is created but before
380 * listener_os_thread is set, the first worker thread hits an
381 * error and starts graceful termination
386 /* unblock the listener if it's waiting for a worker */
387 ap_queue_info_term(worker_queue_info);
390 * we should just be able to "kill(ap_my_pid, LISTENER_SIGNAL)" on all
391 * platforms and wake up the listener thread since it is the only thread
392 * with SIGHUP unblocked, but that doesn't work on Linux
394 #ifdef HAVE_PTHREAD_KILL
395 pthread_kill(*listener_os_thread, LISTENER_SIGNAL);
397 kill(ap_my_pid, LISTENER_SIGNAL);
402 #define ST_GRACEFUL 1
403 #define ST_UNGRACEFUL 2
405 static int terminate_mode = ST_INIT;
407 static void signal_threads(int mode)
409 if (terminate_mode == mode) {
412 terminate_mode = mode;
413 mpm_state = AP_MPMQ_STOPPING;
415 /* in case we weren't called from the listener thread, wake up the
420 /* for ungraceful termination, let the workers exit now;
421 * for graceful termination, the listener thread will notify the
422 * workers to exit once it has stopped accepting new connections
424 if (mode == ST_UNGRACEFUL) {
425 workers_may_exit = 1;
426 ap_queue_interrupt_all(worker_queue);
427 close_worker_sockets(); /* forcefully kill all current connections */
431 static int event_query(int query_code, int *result, apr_status_t *rv)
434 switch (query_code) {
435 case AP_MPMQ_MAX_DAEMON_USED:
436 *result = retained->max_daemons_limit;
438 case AP_MPMQ_IS_THREADED:
439 *result = AP_MPMQ_STATIC;
441 case AP_MPMQ_IS_FORKED:
442 *result = AP_MPMQ_DYNAMIC;
444 case AP_MPMQ_IS_ASYNC:
447 case AP_MPMQ_HAS_SERF:
450 case AP_MPMQ_HARD_LIMIT_DAEMONS:
451 *result = server_limit;
453 case AP_MPMQ_HARD_LIMIT_THREADS:
454 *result = thread_limit;
456 case AP_MPMQ_MAX_THREADS:
457 *result = threads_per_child;
459 case AP_MPMQ_MIN_SPARE_DAEMONS:
462 case AP_MPMQ_MIN_SPARE_THREADS:
463 *result = min_spare_threads;
465 case AP_MPMQ_MAX_SPARE_DAEMONS:
468 case AP_MPMQ_MAX_SPARE_THREADS:
469 *result = max_spare_threads;
471 case AP_MPMQ_MAX_REQUESTS_DAEMON:
472 *result = ap_max_requests_per_child;
474 case AP_MPMQ_MAX_DAEMONS:
475 *result = ap_daemons_limit;
477 case AP_MPMQ_MPM_STATE:
480 case AP_MPMQ_GENERATION:
481 *result = retained->my_generation;
490 static void event_note_child_killed(int childnum, pid_t pid, ap_generation_t gen)
492 if (childnum != -1) { /* child had a scoreboard slot? */
493 ap_run_child_status(ap_server_conf,
494 ap_scoreboard_image->parent[childnum].pid,
495 ap_scoreboard_image->parent[childnum].generation,
496 childnum, MPM_CHILD_EXITED);
497 ap_scoreboard_image->parent[childnum].pid = 0;
500 ap_run_child_status(ap_server_conf, pid, gen, -1, MPM_CHILD_EXITED);
504 static void event_note_child_started(int slot, pid_t pid)
506 ap_scoreboard_image->parent[slot].pid = pid;
507 ap_run_child_status(ap_server_conf,
508 ap_scoreboard_image->parent[slot].pid,
509 retained->my_generation, slot, MPM_CHILD_STARTED);
512 static void event_note_child_lost_slot(int slot, pid_t newpid)
514 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
515 "pid %" APR_PID_T_FMT " taking over scoreboard slot from "
516 "%" APR_PID_T_FMT "%s",
518 ap_scoreboard_image->parent[slot].pid,
519 ap_scoreboard_image->parent[slot].quiescing ?
520 " (quiescing)" : "");
521 ap_run_child_status(ap_server_conf,
522 ap_scoreboard_image->parent[slot].pid,
523 ap_scoreboard_image->parent[slot].generation,
524 slot, MPM_CHILD_LOST_SLOT);
525 /* Don't forget about this exiting child process, or we
526 * won't be able to kill it if it doesn't exit by the
527 * time the server is shut down.
529 ap_register_extra_mpm_process(ap_scoreboard_image->parent[slot].pid,
530 ap_scoreboard_image->parent[slot].generation);
533 static const char *event_get_name(void)
538 /* a clean exit from a child with proper cleanup */
539 static void clean_child_exit(int code) __attribute__ ((noreturn));
540 static void clean_child_exit(int code)
542 mpm_state = AP_MPMQ_STOPPING;
544 apr_pool_destroy(pchild);
548 event_note_child_killed(/* slot */ 0, 0, 0);
554 static void just_die(int sig)
559 /*****************************************************************
560 * Connection structures and accounting...
563 static int child_fatal;
565 /* volatile because they're updated from a signal handler */
566 static int volatile shutdown_pending;
567 static int volatile restart_pending;
568 ap_generation_t volatile ap_my_generation = 0;
570 static apr_status_t decrement_connection_count(void *dummy) {
571 apr_atomic_dec32(&connection_count);
576 * ap_start_shutdown() and ap_start_restart(), below, are a first stab at
577 * functions to initiate shutdown or restart without relying on signals.
578 * Previously this was initiated in sig_term() and restart() signal handlers,
579 * but we want to be able to start a shutdown/restart from other sources --
580 * e.g. on Win32, from the service manager. Now the service manager can
581 * call ap_start_shutdown() or ap_start_restart() as appropiate. Note that
582 * these functions can also be called by the child processes, since global
583 * variables are no longer used to pass on the required action to the parent.
585 * These should only be called from the parent process itself, since the
586 * parent process will use the shutdown_pending and restart_pending variables
587 * to determine whether to shutdown or restart. The child process should
588 * call signal_parent() directly to tell the parent to die -- this will
589 * cause neither of those variable to be set, which the parent will
590 * assume means something serious is wrong (which it will be, for the
591 * child to force an exit) and so do an exit anyway.
594 static void ap_start_shutdown(int graceful)
596 mpm_state = AP_MPMQ_STOPPING;
597 if (shutdown_pending == 1) {
598 /* Um, is this _probably_ not an error, if the user has
599 * tried to do a shutdown twice quickly, so we won't
600 * worry about reporting it.
604 shutdown_pending = 1;
605 retained->is_graceful = graceful;
608 /* do a graceful restart if graceful == 1 */
609 static void ap_start_restart(int graceful)
611 mpm_state = AP_MPMQ_STOPPING;
612 if (restart_pending == 1) {
613 /* Probably not an error - don't bother reporting it */
617 retained->is_graceful = graceful;
620 static void sig_term(int sig)
622 ap_start_shutdown(sig == AP_SIG_GRACEFUL_STOP);
625 static void restart(int sig)
627 ap_start_restart(sig == AP_SIG_GRACEFUL);
630 static void set_signals(void)
632 #ifndef NO_USE_SIGACTION
637 ap_fatal_signal_setup(ap_server_conf, pconf);
640 #ifndef NO_USE_SIGACTION
641 sigemptyset(&sa.sa_mask);
644 sa.sa_handler = sig_term;
645 if (sigaction(SIGTERM, &sa, NULL) < 0)
646 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
647 "sigaction(SIGTERM)");
648 #ifdef AP_SIG_GRACEFUL_STOP
649 if (sigaction(AP_SIG_GRACEFUL_STOP, &sa, NULL) < 0)
650 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
651 "sigaction(" AP_SIG_GRACEFUL_STOP_STRING ")");
654 if (sigaction(SIGINT, &sa, NULL) < 0)
655 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
656 "sigaction(SIGINT)");
659 sa.sa_handler = SIG_DFL;
660 if (sigaction(SIGXCPU, &sa, NULL) < 0)
661 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
662 "sigaction(SIGXCPU)");
665 /* For systems following the LFS standard, ignoring SIGXFSZ allows
666 * a write() beyond the 2GB limit to fail gracefully with E2BIG
667 * rather than terminate the process. */
668 sa.sa_handler = SIG_IGN;
669 if (sigaction(SIGXFSZ, &sa, NULL) < 0)
670 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
671 "sigaction(SIGXFSZ)");
674 sa.sa_handler = SIG_IGN;
675 if (sigaction(SIGPIPE, &sa, NULL) < 0)
676 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
677 "sigaction(SIGPIPE)");
680 /* we want to ignore HUPs and AP_SIG_GRACEFUL while we're busy
682 sigaddset(&sa.sa_mask, SIGHUP);
683 sigaddset(&sa.sa_mask, AP_SIG_GRACEFUL);
684 sa.sa_handler = restart;
685 if (sigaction(SIGHUP, &sa, NULL) < 0)
686 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
687 "sigaction(SIGHUP)");
688 if (sigaction(AP_SIG_GRACEFUL, &sa, NULL) < 0)
689 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
690 "sigaction(" AP_SIG_GRACEFUL_STRING ")");
694 apr_signal(SIGXCPU, SIG_DFL);
697 apr_signal(SIGXFSZ, SIG_IGN);
701 apr_signal(SIGTERM, sig_term);
703 apr_signal(SIGHUP, restart);
705 #ifdef AP_SIG_GRACEFUL
706 apr_signal(AP_SIG_GRACEFUL, restart);
707 #endif /* AP_SIG_GRACEFUL */
708 #ifdef AP_SIG_GRACEFUL_STOP
709 apr_signal(AP_SIG_GRACEFUL_STOP, sig_term);
710 #endif /* AP_SIG_GRACEFUL_STOP */
712 apr_signal(SIGPIPE, SIG_IGN);
718 static int start_lingering_close(conn_state_t *cs)
721 if (ap_start_lingering_close(cs->c)) {
722 apr_pool_clear(cs->p);
723 ap_push_pool(worker_queue_info, cs->p);
727 apr_socket_t *csd = ap_get_conn_socket(cs->c);
728 struct timeout_queue *q;
730 rv = apr_socket_timeout_set(csd, 0);
731 AP_DEBUG_ASSERT(rv == APR_SUCCESS);
733 * If some module requested a shortened waiting period, only wait for
734 * 2s (SECONDS_TO_LINGER). This is useful for mitigating certain
737 if (apr_table_get(cs->c->notes, "short-lingering-close")) {
738 cs->expiration_time =
739 apr_time_now() + apr_time_from_sec(SECONDS_TO_LINGER);
741 cs->state = CONN_STATE_LINGER_SHORT;
744 cs->expiration_time =
745 apr_time_now() + apr_time_from_sec(MAX_SECS_TO_LINGER);
747 cs->state = CONN_STATE_LINGER_NORMAL;
749 apr_thread_mutex_lock(timeout_mutex);
750 TO_QUEUE_APPEND(*q, cs);
751 apr_thread_mutex_unlock(timeout_mutex);
752 cs->pfd.reqevents = APR_POLLIN | APR_POLLHUP | APR_POLLERR;
753 rv = apr_pollset_add(event_pollset, &cs->pfd);
754 if (rv != APR_SUCCESS && !APR_STATUS_IS_EEXIST(rv)) {
755 ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf,
756 "start_lingering_close: apr_pollset_add failure");
763 static int stop_lingering_close(conn_state_t *cs)
766 apr_socket_t *csd = ap_get_conn_socket(cs->c);
767 ap_log_error(APLOG_MARK, APLOG_TRACE4, 0, ap_server_conf,
768 "socket reached timeout in lingering-close state");
769 rv = apr_socket_close(csd);
770 if (rv != APR_SUCCESS) {
771 ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf, "error closing socket");
774 apr_pool_clear(cs->p);
775 ap_push_pool(worker_queue_info, cs->p);
781 /*****************************************************************
782 * Child process main loop.
785 static int process_socket(apr_thread_t *thd, apr_pool_t * p, apr_socket_t * sock,
786 conn_state_t * cs, int my_child_num,
790 listener_poll_type *pt;
791 long conn_id = ID_FROM_CHILD_THREAD(my_child_num, my_thread_num);
795 ap_create_sb_handle(&sbh, p, my_child_num, my_thread_num);
797 if (cs == NULL) { /* This is a new connection */
799 cs = apr_pcalloc(p, sizeof(conn_state_t));
801 pt = apr_pcalloc(p, sizeof(*pt));
803 cs->bucket_alloc = apr_bucket_alloc_create(p);
804 c = ap_run_create_connection(p, ap_server_conf, sock,
805 conn_id, sbh, cs->bucket_alloc);
806 apr_atomic_inc32(&connection_count);
807 apr_pool_cleanup_register(c->pool, NULL, decrement_connection_count, apr_pool_cleanup_null);
808 c->current_thread = thd;
812 cs->pfd.desc_type = APR_POLL_SOCKET;
813 cs->pfd.reqevents = APR_POLLIN;
814 cs->pfd.desc.s = sock;
817 cs->pfd.client_data = pt;
818 TO_QUEUE_ELEM_INIT(cs);
820 ap_update_vhost_given_ip(c);
822 rc = ap_run_pre_connection(c, sock);
823 if (rc != OK && rc != DONE) {
824 ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c,
825 "process_socket: connection aborted");
830 * XXX If the platform does not have a usable way of bundling
831 * accept() with a socket readability check, like Win32,
832 * and there are measurable delays before the
833 * socket is readable due to the first data packet arriving,
834 * it might be better to create the cs on the listener thread
835 * with the state set to CONN_STATE_CHECK_REQUEST_LINE_READABLE
837 * FreeBSD users will want to enable the HTTP accept filter
838 * module in their kernel for the highest performance
839 * When the accept filter is active, sockets are kept in the
840 * kernel until a HTTP request is received.
842 cs->state = CONN_STATE_READ_REQUEST_LINE;
848 pt = cs->pfd.client_data;
849 c->current_thread = thd;
852 if (c->clogging_input_filters && !c->aborted) {
853 /* Since we have an input filter which 'cloggs' the input stream,
854 * like mod_ssl, lets just do the normal read from input filters,
855 * like the Worker MPM does.
857 ap_run_process_connection(c);
858 if (cs->state != CONN_STATE_SUSPENDED) {
859 cs->state = CONN_STATE_LINGER;
864 if (cs->state == CONN_STATE_READ_REQUEST_LINE) {
866 ap_run_process_connection(c);
868 /* state will be updated upon return
869 * fall thru to either wait for readability/timeout or
874 cs->state = CONN_STATE_LINGER;
878 if (cs->state == CONN_STATE_WRITE_COMPLETION) {
879 ap_filter_t *output_filter = c->output_filters;
881 ap_update_child_status_from_conn(sbh, SERVER_BUSY_WRITE, c);
882 while (output_filter->next != NULL) {
883 output_filter = output_filter->next;
885 rv = output_filter->frec->filter_func.out_func(output_filter, NULL);
886 if (rv != APR_SUCCESS) {
887 ap_log_cerror(APLOG_MARK, APLOG_WARNING, rv, c,
888 "network write failure in core output filter");
889 cs->state = CONN_STATE_LINGER;
891 else if (c->data_in_output_filters) {
892 /* Still in WRITE_COMPLETION_STATE:
893 * Set a write timeout for this connection, and let the
894 * event thread poll for writeability.
896 cs->expiration_time = ap_server_conf->timeout + apr_time_now();
897 apr_thread_mutex_lock(timeout_mutex);
898 TO_QUEUE_APPEND(write_completion_q, cs);
899 apr_thread_mutex_unlock(timeout_mutex);
900 cs->pfd.reqevents = APR_POLLOUT | APR_POLLHUP | APR_POLLERR;
901 rc = apr_pollset_add(event_pollset, &cs->pfd);
904 else if (c->keepalive != AP_CONN_KEEPALIVE || c->aborted ||
906 c->cs->state = CONN_STATE_LINGER;
908 else if (c->data_in_input_filters) {
909 cs->state = CONN_STATE_READ_REQUEST_LINE;
913 cs->state = CONN_STATE_CHECK_REQUEST_LINE_READABLE;
917 if (cs->state == CONN_STATE_LINGER) {
918 if (!start_lingering_close(cs))
921 else if (cs->state == CONN_STATE_CHECK_REQUEST_LINE_READABLE) {
924 /* It greatly simplifies the logic to use a single timeout value here
925 * because the new element can just be added to the end of the list and
926 * it will stay sorted in expiration time sequence. If brand new
927 * sockets are sent to the event thread for a readability check, this
928 * will be a slight behavior change - they use the non-keepalive
929 * timeout today. With a normal client, the socket will be readable in
930 * a few milliseconds anyway.
932 cs->expiration_time = ap_server_conf->keep_alive_timeout +
934 apr_thread_mutex_lock(timeout_mutex);
935 TO_QUEUE_APPEND(keepalive_q, cs);
936 apr_thread_mutex_unlock(timeout_mutex);
938 /* Add work to pollset. */
939 cs->pfd.reqevents = APR_POLLIN;
940 rc = apr_pollset_add(event_pollset, &cs->pfd);
942 if (rc != APR_SUCCESS) {
943 ap_log_error(APLOG_MARK, APLOG_ERR, rc, ap_server_conf,
944 "process_socket: apr_pollset_add failure");
945 AP_DEBUG_ASSERT(rc == APR_SUCCESS);
951 /* requests_this_child has gone to zero or below. See if the admin coded
952 "MaxConnectionsPerChild 0", and keep going in that case. Doing it this way
953 simplifies the hot path in worker_thread */
954 static void check_infinite_requests(void)
956 if (ap_max_requests_per_child) {
957 signal_threads(ST_GRACEFUL);
960 requests_this_child = INT_MAX; /* keep going */
964 static void close_listeners(int process_slot, int *closed) {
967 disable_listensocks(process_slot);
968 ap_close_listeners();
971 ap_scoreboard_image->parent[process_slot].quiescing = 1;
972 for (i = 0; i < threads_per_child; ++i) {
973 ap_update_child_status_from_indexes(process_slot, i,
974 SERVER_GRACEFUL, NULL);
976 /* wake up the main thread */
977 kill(ap_my_pid, SIGTERM);
981 static void unblock_signal(int sig)
985 sigemptyset(&sig_mask);
986 sigaddset(&sig_mask, sig);
987 #if defined(SIGPROCMASK_SETS_THREAD_MASK)
988 sigprocmask(SIG_UNBLOCK, &sig_mask, NULL);
990 pthread_sigmask(SIG_UNBLOCK, &sig_mask, NULL);
994 static void dummy_signal_handler(int sig)
996 /* XXX If specifying SIG_IGN is guaranteed to unblock a syscall,
997 * then we don't need this goofy function.
1003 static apr_status_t s_socket_add(void *user_baton,
1007 s_baton_t *s = (s_baton_t*)user_baton;
1008 /* XXXXX: recycle listener_poll_types */
1009 listener_poll_type *pt = malloc(sizeof(*pt));
1011 pt->baton = serf_baton;
1012 pfd->client_data = pt;
1013 return apr_pollset_add(s->pollset, pfd);
1016 static apr_status_t s_socket_remove(void *user_baton,
1020 s_baton_t *s = (s_baton_t*)user_baton;
1021 listener_poll_type *pt = pfd->client_data;
1023 return apr_pollset_remove(s->pollset, pfd);
1027 static apr_status_t init_pollset(apr_pool_t *p)
1030 s_baton_t *baton = NULL;
1033 listener_poll_type *pt;
1036 TO_QUEUE_INIT(write_completion_q);
1037 TO_QUEUE_INIT(keepalive_q);
1038 TO_QUEUE_INIT(linger_q);
1039 TO_QUEUE_INIT(short_linger_q);
1041 listener_pollfd = apr_palloc(p, sizeof(apr_pollfd_t) * num_listensocks);
1042 for (lr = ap_listeners; lr != NULL; lr = lr->next, i++) {
1044 AP_DEBUG_ASSERT(i < num_listensocks);
1045 pfd = &listener_pollfd[i];
1046 pt = apr_pcalloc(p, sizeof(*pt));
1047 pfd->desc_type = APR_POLL_SOCKET;
1048 pfd->desc.s = lr->sd;
1049 pfd->reqevents = APR_POLLIN;
1051 pt->type = PT_ACCEPT;
1054 pfd->client_data = pt;
1056 apr_socket_opt_set(pfd->desc.s, APR_SO_NONBLOCK, 1);
1057 apr_pollset_add(event_pollset, pfd);
1059 lr->accept_func = ap_unixd_accept;
1063 baton = apr_pcalloc(p, sizeof(*baton));
1064 baton->pollset = event_pollset;
1065 /* TODO: subpools, threads, reuse, etc. -- currently use malloc() inside :( */
1068 g_serf = serf_context_create_ex(baton,
1070 s_socket_remove, p);
1072 ap_register_provider(p, "mpm_serf",
1073 "instance", "0", g_serf);
1080 static apr_status_t push_timer2worker(timer_event_t* te)
1082 return ap_queue_push_timer(worker_queue, te);
1085 static apr_status_t push2worker(const apr_pollfd_t * pfd,
1086 apr_pollset_t * pollset)
1088 listener_poll_type *pt = (listener_poll_type *) pfd->client_data;
1089 conn_state_t *cs = (conn_state_t *) pt->baton;
1092 rc = apr_pollset_remove(pollset, pfd);
1095 * Some of the pollset backends, like KQueue or Epoll
1096 * automagically remove the FD if the socket is closed,
1097 * therefore, we can accept _SUCCESS or _NOTFOUND,
1098 * and we still want to keep going
1100 if (rc != APR_SUCCESS && !APR_STATUS_IS_NOTFOUND(rc)) {
1101 ap_log_error(APLOG_MARK, APLOG_ERR, rc, ap_server_conf,
1102 "pollset remove failed");
1103 start_lingering_close(cs);
1107 rc = ap_queue_push(worker_queue, cs->pfd.desc.s, cs, cs->p);
1108 if (rc != APR_SUCCESS) {
1109 /* trash the connection; we couldn't queue the connected
1110 * socket to a worker
1112 apr_bucket_alloc_destroy(cs->bucket_alloc);
1113 apr_socket_close(cs->pfd.desc.s);
1114 ap_log_error(APLOG_MARK, APLOG_CRIT, rc,
1115 ap_server_conf, "push2worker: ap_queue_push failed");
1116 apr_pool_clear(cs->p);
1117 ap_push_pool(worker_queue_info, cs->p);
1124 * If *have_idle_worker_p == 0, reserve a worker thread, and set
1125 * *have_idle_worker_p = 1.
1126 * If *have_idle_worker_p is already 1, will do nothing.
1127 * If blocking == 1, block if all workers are currently busy.
1128 * If no worker was available immediately, will set *all_busy to 1.
1129 * XXX: If there are no workers, we should not block immediately but
1130 * XXX: close all keep-alive connections first.
1132 static void get_worker(int *have_idle_worker_p, int blocking, int *all_busy)
1136 if (*have_idle_worker_p) {
1137 /* already reserved a worker thread - must have hit a
1138 * transient error on a previous pass
1144 rc = ap_queue_info_wait_for_idler(worker_queue_info, all_busy);
1146 rc = ap_queue_info_try_get_idler(worker_queue_info);
1148 if (rc == APR_SUCCESS) {
1149 *have_idle_worker_p = 1;
1151 else if (!blocking && rc == APR_EAGAIN) {
1154 else if (!APR_STATUS_IS_EOF(rc)) {
1155 ap_log_error(APLOG_MARK, APLOG_ERR, rc, ap_server_conf,
1156 "ap_queue_info_wait_for_idler failed. "
1157 "Attempting to shutdown process gracefully");
1158 signal_threads(ST_GRACEFUL);
1162 /* XXXXXX: Convert to skiplist or other better data structure
1163 * (yes, this is VERY VERY VERY VERY BAD)
1166 /* Structures to reuse */
1167 static APR_RING_HEAD(timer_free_ring_t, timer_event_t) timer_free_ring;
1169 static APR_RING_HEAD(timer_ring_t, timer_event_t) timer_ring;
1171 static apr_thread_mutex_t *g_timer_ring_mtx;
1173 static apr_status_t event_register_timed_callback(apr_time_t t,
1174 ap_mpm_callback_fn_t *cbfn,
1180 /* oh yeah, and make locking smarter/fine grained. */
1181 apr_thread_mutex_lock(g_timer_ring_mtx);
1183 if (!APR_RING_EMPTY(&timer_free_ring, timer_event_t, link)) {
1184 te = APR_RING_FIRST(&timer_free_ring);
1185 APR_RING_REMOVE(te, link);
1188 /* XXXXX: lol, pool allocation without a context from any thread.Yeah. Right. MPMs Suck. */
1189 te = malloc(sizeof(timer_event_t));
1190 APR_RING_ELEM_INIT(te, link);
1195 /* XXXXX: optimize */
1196 te->when = t + apr_time_now();
1198 /* Okay, insert sorted by when.. */
1199 for (ep = APR_RING_FIRST(&timer_ring);
1200 ep != APR_RING_SENTINEL(&timer_ring,
1201 timer_event_t, link);
1202 ep = APR_RING_NEXT(ep, link))
1204 if (ep->when > te->when) {
1206 APR_RING_INSERT_BEFORE(ep, te, link);
1212 APR_RING_INSERT_TAIL(&timer_ring, te, timer_event_t, link);
1215 apr_thread_mutex_unlock(g_timer_ring_mtx);
1220 static void process_lingering_close(conn_state_t *cs, const apr_pollfd_t *pfd)
1222 apr_socket_t *csd = ap_get_conn_socket(cs->c);
1223 char dummybuf[2048];
1226 struct timeout_queue *q;
1227 q = (cs->state == CONN_STATE_LINGER_SHORT) ? &short_linger_q : &linger_q;
1229 /* socket is already in non-blocking state */
1231 nbytes = sizeof(dummybuf);
1232 rv = apr_socket_recv(csd, dummybuf, &nbytes);
1233 } while (rv == APR_SUCCESS);
1235 if (!APR_STATUS_IS_EOF(rv)) {
1239 rv = apr_pollset_remove(event_pollset, pfd);
1240 AP_DEBUG_ASSERT(rv == APR_SUCCESS);
1242 rv = apr_socket_close(csd);
1243 AP_DEBUG_ASSERT(rv == APR_SUCCESS);
1245 apr_thread_mutex_lock(timeout_mutex);
1246 TO_QUEUE_REMOVE(*q, cs);
1247 apr_thread_mutex_unlock(timeout_mutex);
1248 TO_QUEUE_ELEM_INIT(cs);
1250 apr_pool_clear(cs->p);
1251 ap_push_pool(worker_queue_info, cs->p);
1254 /* call 'func' for all elements of 'q' with timeout less than 'timeout_time'.
1255 * Pre-condition: timeout_mutex must already be locked
1256 * Post-condition: timeout_mutex will be locked again
1258 static void process_timeout_queue(struct timeout_queue *q,
1259 apr_time_t timeout_time,
1260 int (*func)(conn_state_t *))
1263 conn_state_t *first, *cs, *last;
1267 AP_DEBUG_ASSERT(!APR_RING_EMPTY(&q->head, conn_state_t, timeout_list));
1269 cs = first = APR_RING_FIRST(&q->head);
1270 while (cs != APR_RING_SENTINEL(&q->head, conn_state_t, timeout_list)
1271 && cs->expiration_time < timeout_time) {
1273 cs = APR_RING_NEXT(cs, timeout_list);
1279 APR_RING_UNSPLICE(first, last, timeout_list);
1280 AP_DEBUG_ASSERT(q->count >= count);
1282 apr_thread_mutex_unlock(timeout_mutex);
1284 cs = APR_RING_NEXT(first, timeout_list);
1285 TO_QUEUE_ELEM_INIT(first);
1290 apr_thread_mutex_lock(timeout_mutex);
1293 static void * APR_THREAD_FUNC listener_thread(apr_thread_t * thd, void *dummy)
1298 proc_info *ti = dummy;
1299 int process_slot = ti->pid;
1300 apr_pool_t *tpool = apr_thread_pool_get(thd);
1302 apr_pool_t *ptrans; /* Pool for per-transaction stuff */
1304 int have_idle_worker = 0;
1306 const apr_pollfd_t *out_pfd;
1307 apr_int32_t num = 0;
1308 apr_interval_time_t timeout_interval;
1309 apr_time_t timeout_time = 0, now, last_log;
1310 listener_poll_type *pt;
1311 int closed = 0, listeners_disabled = 0;
1313 last_log = apr_time_now();
1316 /* the following times out events that are really close in the future
1317 * to prevent extra poll calls
1319 * current value is .1 second
1321 #define TIMEOUT_FUDGE_FACTOR 100000
1322 #define EVENT_FUDGE_FACTOR 10000
1324 /* XXX: this should be a config options */
1325 #define WORKER_OVERCOMMIT 2
1327 rc = init_pollset(tpool);
1328 if (rc != APR_SUCCESS) {
1329 ap_log_error(APLOG_MARK, APLOG_ERR, rc, ap_server_conf,
1330 "failed to initialize pollset, "
1331 "attempting to shutdown process gracefully");
1332 signal_threads(ST_GRACEFUL);
1336 /* Unblock the signal used to wake this thread up, and set a handler for
1339 unblock_signal(LISTENER_SIGNAL);
1340 apr_signal(LISTENER_SIGNAL, dummy_signal_handler);
1343 int workers_were_busy = 0;
1344 if (listener_may_exit) {
1345 close_listeners(process_slot, &closed);
1346 if (terminate_mode == ST_UNGRACEFUL
1347 || apr_atomic_read32(&connection_count) == 0)
1351 if (requests_this_child <= 0) {
1352 check_infinite_requests();
1355 now = apr_time_now();
1356 if (APLOGtrace6(ap_server_conf)) {
1357 /* trace log status every second */
1358 if (now - last_log > apr_time_from_msec(1000)) {
1360 apr_thread_mutex_lock(timeout_mutex);
1361 ap_log_error(APLOG_MARK, APLOG_TRACE6, 0, ap_server_conf,
1362 "connections: %d (write-completion: %d "
1363 "keep-alive: %d lingering: %d)",
1364 connection_count, write_completion_q.count,
1366 linger_q.count + short_linger_q.count);
1367 apr_thread_mutex_unlock(timeout_mutex);
1371 apr_thread_mutex_lock(g_timer_ring_mtx);
1372 if (!APR_RING_EMPTY(&timer_ring, timer_event_t, link)) {
1373 te = APR_RING_FIRST(&timer_ring);
1374 if (te->when > now) {
1375 timeout_interval = te->when - now;
1378 timeout_interval = 1;
1382 timeout_interval = apr_time_from_msec(100);
1384 apr_thread_mutex_unlock(g_timer_ring_mtx);
1387 rc = serf_context_prerun(g_serf);
1388 if (rc != APR_SUCCESS) {
1389 /* TOOD: what should do here? ugh. */
1392 rc = apr_pollset_poll(event_pollset, timeout_interval, &num, &out_pfd);
1393 if (rc != APR_SUCCESS) {
1394 if (APR_STATUS_IS_EINTR(rc)) {
1397 if (!APR_STATUS_IS_TIMEUP(rc)) {
1398 ap_log_error(APLOG_MARK, APLOG_CRIT, rc, ap_server_conf,
1399 "apr_pollset_poll failed. Attempting to "
1400 "shutdown process gracefully");
1401 signal_threads(ST_GRACEFUL);
1405 if (listener_may_exit) {
1406 close_listeners(process_slot, &closed);
1407 if (terminate_mode == ST_UNGRACEFUL
1408 || apr_atomic_read32(&connection_count) == 0)
1412 now = apr_time_now();
1413 apr_thread_mutex_lock(g_timer_ring_mtx);
1414 for (ep = APR_RING_FIRST(&timer_ring);
1415 ep != APR_RING_SENTINEL(&timer_ring,
1416 timer_event_t, link);
1417 ep = APR_RING_FIRST(&timer_ring))
1419 if (ep->when < now + EVENT_FUDGE_FACTOR) {
1420 APR_RING_REMOVE(ep, link);
1421 push_timer2worker(ep);
1427 apr_thread_mutex_unlock(g_timer_ring_mtx);
1430 pt = (listener_poll_type *) out_pfd->client_data;
1431 if (pt->type == PT_CSD) {
1432 /* one of the sockets is readable */
1433 struct timeout_queue *remove_from_q = &write_completion_q;
1435 cs = (conn_state_t *) pt->baton;
1436 switch (cs->state) {
1437 case CONN_STATE_CHECK_REQUEST_LINE_READABLE:
1438 cs->state = CONN_STATE_READ_REQUEST_LINE;
1439 remove_from_q = &keepalive_q;
1440 /* don't wait for a worker for a keepalive request */
1443 case CONN_STATE_WRITE_COMPLETION:
1444 get_worker(&have_idle_worker, blocking,
1445 &workers_were_busy);
1446 apr_thread_mutex_lock(timeout_mutex);
1447 TO_QUEUE_REMOVE(*remove_from_q, cs);
1448 apr_thread_mutex_unlock(timeout_mutex);
1449 TO_QUEUE_ELEM_INIT(cs);
1450 /* If we didn't get a worker immediately for a keep-alive
1451 * request, we close the connection, so that the client can
1452 * re-connect to a different process.
1454 if (!have_idle_worker) {
1455 start_lingering_close(cs);
1458 rc = push2worker(out_pfd, event_pollset);
1459 if (rc != APR_SUCCESS) {
1460 ap_log_error(APLOG_MARK, APLOG_CRIT, rc,
1461 ap_server_conf, "push2worker failed");
1464 have_idle_worker = 0;
1467 case CONN_STATE_LINGER_NORMAL:
1468 case CONN_STATE_LINGER_SHORT:
1469 process_lingering_close(cs, out_pfd);
1472 ap_log_error(APLOG_MARK, APLOG_CRIT, rc,
1474 "event_loop: unexpected state %d",
1479 else if (pt->type == PT_ACCEPT) {
1480 /* A Listener Socket is ready for an accept() */
1481 if (workers_were_busy) {
1482 if (!listeners_disabled)
1483 disable_listensocks(process_slot);
1484 listeners_disabled = 1;
1485 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
1486 "All workers busy, not accepting new conns"
1489 else if (apr_atomic_read32(&connection_count) > threads_per_child
1490 + ap_queue_info_get_idlers(worker_queue_info) * WORKER_OVERCOMMIT)
1492 if (!listeners_disabled)
1493 disable_listensocks(process_slot);
1494 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
1495 "Too many open connections (%u), "
1496 "not accepting new conns in this process",
1497 apr_atomic_read32(&connection_count));
1498 ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, ap_server_conf,
1500 ap_queue_info_get_idlers(worker_queue_info));
1501 listeners_disabled = 1;
1503 else if (listeners_disabled) {
1504 listeners_disabled = 0;
1505 enable_listensocks(process_slot);
1507 if (!listeners_disabled) {
1508 lr = (ap_listen_rec *) pt->baton;
1509 ap_pop_pool(&ptrans, worker_queue_info);
1511 if (ptrans == NULL) {
1512 /* create a new transaction pool for each accepted socket */
1513 apr_allocator_t *allocator;
1515 apr_allocator_create(&allocator);
1516 apr_allocator_max_free_set(allocator,
1518 apr_pool_create_ex(&ptrans, pconf, NULL, allocator);
1519 apr_allocator_owner_set(allocator, ptrans);
1520 if (ptrans == NULL) {
1521 ap_log_error(APLOG_MARK, APLOG_CRIT, rc,
1523 "Failed to create transaction pool");
1524 signal_threads(ST_GRACEFUL);
1528 apr_pool_tag(ptrans, "transaction");
1530 get_worker(&have_idle_worker, 1, &workers_were_busy);
1531 rc = lr->accept_func(&csd, lr, ptrans);
1533 /* later we trash rv and rely on csd to indicate
1536 AP_DEBUG_ASSERT(rc == APR_SUCCESS || !csd);
1538 if (rc == APR_EGENERAL) {
1539 /* E[NM]FILE, ENOMEM, etc */
1540 resource_shortage = 1;
1541 signal_threads(ST_GRACEFUL);
1545 rc = ap_queue_push(worker_queue, csd, NULL, ptrans);
1546 if (rc != APR_SUCCESS) {
1547 /* trash the connection; we couldn't queue the connected
1548 * socket to a worker
1550 apr_socket_close(csd);
1551 ap_log_error(APLOG_MARK, APLOG_CRIT, rc,
1553 "ap_queue_push failed");
1554 apr_pool_clear(ptrans);
1555 ap_push_pool(worker_queue_info, ptrans);
1558 have_idle_worker = 0;
1562 apr_pool_clear(ptrans);
1563 ap_push_pool(worker_queue_info, ptrans);
1566 } /* if:else on pt->type */
1568 else if (pt->type == PT_SERF) {
1569 /* send socket to serf. */
1570 /* XXXX: this doesn't require get_worker() */
1571 serf_event_trigger(g_serf, pt->baton, out_pfd);
1576 } /* while for processing poll */
1578 /* XXX possible optimization: stash the current time for use as
1579 * r->request_time for new requests
1581 now = apr_time_now();
1582 /* we only do this once per 0.1s (TIMEOUT_FUDGE_FACTOR) */
1583 if (now > timeout_time) {
1584 struct process_score *ps;
1585 timeout_time = now + TIMEOUT_FUDGE_FACTOR;
1587 /* handle timed out sockets */
1588 apr_thread_mutex_lock(timeout_mutex);
1590 /* Step 1: keepalive timeouts */
1591 /* If all workers are busy, we kill older keep-alive connections so that they
1592 * may connect to another process.
1594 if (workers_were_busy && keepalive_q.count) {
1595 ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, ap_server_conf,
1596 "All workers are busy, will close %d keep-alive "
1599 process_timeout_queue(&keepalive_q,
1600 timeout_time + ap_server_conf->keep_alive_timeout,
1601 start_lingering_close);
1604 process_timeout_queue(&keepalive_q, timeout_time,
1605 start_lingering_close);
1607 /* Step 2: write completion timeouts */
1608 process_timeout_queue(&write_completion_q, timeout_time, start_lingering_close);
1609 /* Step 3: (normal) lingering close completion timeouts */
1610 process_timeout_queue(&linger_q, timeout_time, stop_lingering_close);
1611 /* Step 4: (short) lingering close completion timeouts */
1612 process_timeout_queue(&short_linger_q, timeout_time, stop_lingering_close);
1614 ps = ap_get_scoreboard_process(process_slot);
1615 ps->write_completion = write_completion_q.count;
1616 ps->lingering_close = linger_q.count + short_linger_q.count;
1617 ps->keep_alive = keepalive_q.count;
1618 apr_thread_mutex_unlock(timeout_mutex);
1620 ps->connections = apr_atomic_read32(&connection_count);
1621 /* XXX: should count CONN_STATE_SUSPENDED and set ps->suspended */
1623 if (listeners_disabled && !workers_were_busy &&
1624 (int)apr_atomic_read32(&connection_count) <
1625 ((int)ap_queue_info_get_idlers(worker_queue_info) - 1) * WORKER_OVERCOMMIT +
1628 listeners_disabled = 0;
1629 enable_listensocks(process_slot);
1632 * XXX: do we need to set some timeout that re-enables the listensocks
1633 * XXX: in case no other event occurs?
1635 } /* listener main loop */
1637 close_listeners(process_slot, &closed);
1638 ap_queue_term(worker_queue);
1640 apr_thread_exit(thd, APR_SUCCESS);
1644 /* XXX For ungraceful termination/restart, we definitely don't want to
1645 * wait for active connections to finish but we may want to wait
1646 * for idle workers to get out of the queue code and release mutexes,
1647 * since those mutexes are cleaned up pretty soon and some systems
1648 * may not react favorably (i.e., segfault) if operations are attempted
1649 * on cleaned-up mutexes.
1651 static void *APR_THREAD_FUNC worker_thread(apr_thread_t * thd, void *dummy)
1653 proc_info *ti = dummy;
1654 int process_slot = ti->pid;
1655 int thread_slot = ti->tid;
1656 apr_socket_t *csd = NULL;
1658 apr_pool_t *ptrans; /* Pool for per-transaction stuff */
1661 timer_event_t *te = NULL;
1665 ap_scoreboard_image->servers[process_slot][thread_slot].pid = ap_my_pid;
1666 ap_scoreboard_image->servers[process_slot][thread_slot].tid = apr_os_thread_current();
1667 ap_scoreboard_image->servers[process_slot][thread_slot].generation = retained->my_generation;
1668 ap_update_child_status_from_indexes(process_slot, thread_slot,
1669 SERVER_STARTING, NULL);
1671 while (!workers_may_exit) {
1673 rv = ap_queue_info_set_idle(worker_queue_info, NULL);
1674 if (rv != APR_SUCCESS) {
1675 ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
1676 "ap_queue_info_set_idle failed. Attempting to "
1677 "shutdown process gracefully.");
1678 signal_threads(ST_GRACEFUL);
1684 ap_update_child_status_from_indexes(process_slot, thread_slot,
1685 dying ? SERVER_GRACEFUL : SERVER_READY, NULL);
1687 if (workers_may_exit) {
1692 rv = ap_queue_pop_something(worker_queue, &csd, &cs, &ptrans, &te);
1694 if (rv != APR_SUCCESS) {
1695 /* We get APR_EOF during a graceful shutdown once all the
1696 * connections accepted by this server process have been handled.
1698 if (APR_STATUS_IS_EOF(rv)) {
1701 /* We get APR_EINTR whenever ap_queue_pop() has been interrupted
1702 * from an explicit call to ap_queue_interrupt_all(). This allows
1703 * us to unblock threads stuck in ap_queue_pop() when a shutdown
1706 * If workers_may_exit is set and this is ungraceful termination/
1707 * restart, we are bound to get an error on some systems (e.g.,
1708 * AIX, which sanity-checks mutex operations) since the queue
1709 * may have already been cleaned up. Don't log the "error" if
1710 * workers_may_exit is set.
1712 else if (APR_STATUS_IS_EINTR(rv)) {
1715 /* We got some other error. */
1716 else if (!workers_may_exit) {
1717 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
1718 "ap_queue_pop failed");
1723 te->cbfunc(te->baton);
1726 apr_thread_mutex_lock(g_timer_ring_mtx);
1727 APR_RING_INSERT_TAIL(&timer_free_ring, te, timer_event_t, link);
1728 apr_thread_mutex_unlock(g_timer_ring_mtx);
1733 worker_sockets[thread_slot] = csd;
1734 rv = process_socket(thd, ptrans, csd, cs, process_slot, thread_slot);
1736 requests_this_child--;
1738 worker_sockets[thread_slot] = NULL;
1742 ap_update_child_status_from_indexes(process_slot, thread_slot,
1743 dying ? SERVER_DEAD :
1745 (request_rec *) NULL);
1747 apr_thread_exit(thd, APR_SUCCESS);
1751 static int check_signal(int signum)
1763 static void create_listener_thread(thread_starter * ts)
1765 int my_child_num = ts->child_num_arg;
1766 apr_threadattr_t *thread_attr = ts->threadattr;
1770 my_info = (proc_info *) malloc(sizeof(proc_info));
1771 my_info->pid = my_child_num;
1772 my_info->tid = -1; /* listener thread doesn't have a thread slot */
1774 rv = apr_thread_create(&ts->listener, thread_attr, listener_thread,
1776 if (rv != APR_SUCCESS) {
1777 ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
1778 "apr_thread_create: unable to create listener thread");
1779 /* let the parent decide how bad this really is */
1780 clean_child_exit(APEXIT_CHILDSICK);
1782 apr_os_thread_get(&listener_os_thread, ts->listener);
1785 /* XXX under some circumstances not understood, children can get stuck
1786 * in start_threads forever trying to take over slots which will
1787 * never be cleaned up; for now there is an APLOG_DEBUG message issued
1788 * every so often when this condition occurs
1790 static void *APR_THREAD_FUNC start_threads(apr_thread_t * thd, void *dummy)
1792 thread_starter *ts = dummy;
1793 apr_thread_t **threads = ts->threads;
1794 apr_threadattr_t *thread_attr = ts->threadattr;
1795 int child_num_arg = ts->child_num_arg;
1796 int my_child_num = child_num_arg;
1800 int threads_created = 0;
1801 int listener_started = 0;
1803 int prev_threads_created;
1804 int max_recycled_pools = -1;
1806 /* We must create the fd queues before we start up the listener
1807 * and worker threads. */
1808 worker_queue = apr_pcalloc(pchild, sizeof(*worker_queue));
1809 rv = ap_queue_init(worker_queue, threads_per_child, pchild);
1810 if (rv != APR_SUCCESS) {
1811 ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
1812 "ap_queue_init() failed");
1813 clean_child_exit(APEXIT_CHILDFATAL);
1816 if (ap_max_mem_free != APR_ALLOCATOR_MAX_FREE_UNLIMITED) {
1817 /* If we want to conserve memory, let's not keep an unlimited number of
1818 * pools & allocators.
1819 * XXX: This should probably be a separate config directive
1821 max_recycled_pools = threads_per_child * 3 / 4 ;
1823 rv = ap_queue_info_create(&worker_queue_info, pchild,
1824 threads_per_child, max_recycled_pools);
1825 if (rv != APR_SUCCESS) {
1826 ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
1827 "ap_queue_info_create() failed");
1828 clean_child_exit(APEXIT_CHILDFATAL);
1831 /* Create the timeout mutex and main pollset before the listener
1834 rv = apr_thread_mutex_create(&timeout_mutex, APR_THREAD_MUTEX_DEFAULT,
1836 if (rv != APR_SUCCESS) {
1837 ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf,
1838 "creation of the timeout mutex failed.");
1839 clean_child_exit(APEXIT_CHILDFATAL);
1842 /* Create the main pollset */
1843 rv = apr_pollset_create(&event_pollset,
1844 threads_per_child, /* XXX don't we need more, to handle
1845 * connections in K-A or lingering
1848 pchild, APR_POLLSET_THREADSAFE | APR_POLLSET_NOCOPY);
1849 if (rv != APR_SUCCESS) {
1850 ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf,
1851 "apr_pollset_create with Thread Safety failed.");
1852 clean_child_exit(APEXIT_CHILDFATAL);
1855 worker_sockets = apr_pcalloc(pchild, threads_per_child
1856 * sizeof(apr_socket_t *));
1858 loops = prev_threads_created = 0;
1860 /* threads_per_child does not include the listener thread */
1861 for (i = 0; i < threads_per_child; i++) {
1863 ap_scoreboard_image->servers[child_num_arg][i].status;
1865 if (status != SERVER_GRACEFUL && status != SERVER_DEAD) {
1869 my_info = (proc_info *) malloc(sizeof(proc_info));
1870 if (my_info == NULL) {
1871 ap_log_error(APLOG_MARK, APLOG_ALERT, errno, ap_server_conf,
1872 "malloc: out of memory");
1873 clean_child_exit(APEXIT_CHILDFATAL);
1875 my_info->pid = my_child_num;
1879 /* We are creating threads right now */
1880 ap_update_child_status_from_indexes(my_child_num, i,
1881 SERVER_STARTING, NULL);
1882 /* We let each thread update its own scoreboard entry. This is
1883 * done because it lets us deal with tid better.
1885 rv = apr_thread_create(&threads[i], thread_attr,
1886 worker_thread, my_info, pchild);
1887 if (rv != APR_SUCCESS) {
1888 ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
1889 "apr_thread_create: unable to create worker thread");
1890 /* let the parent decide how bad this really is */
1891 clean_child_exit(APEXIT_CHILDSICK);
1896 /* Start the listener only when there are workers available */
1897 if (!listener_started && threads_created) {
1898 create_listener_thread(ts);
1899 listener_started = 1;
1903 if (start_thread_may_exit || threads_created == threads_per_child) {
1906 /* wait for previous generation to clean up an entry */
1907 apr_sleep(apr_time_from_sec(1));
1909 if (loops % 120 == 0) { /* every couple of minutes */
1910 if (prev_threads_created == threads_created) {
1911 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
1912 "child %" APR_PID_T_FMT " isn't taking over "
1913 "slots very quickly (%d of %d)",
1914 ap_my_pid, threads_created,
1917 prev_threads_created = threads_created;
1921 /* What state should this child_main process be listed as in the
1923 * ap_update_child_status_from_indexes(my_child_num, i, SERVER_STARTING,
1924 * (request_rec *) NULL);
1926 * This state should be listed separately in the scoreboard, in some kind
1927 * of process_status, not mixed in with the worker threads' status.
1928 * "life_status" is almost right, but it's in the worker's structure, and
1929 * the name could be clearer. gla
1931 apr_thread_exit(thd, APR_SUCCESS);
1935 static void join_workers(apr_thread_t * listener, apr_thread_t ** threads)
1938 apr_status_t rv, thread_rv;
1943 /* deal with a rare timing window which affects waking up the
1944 * listener thread... if the signal sent to the listener thread
1945 * is delivered between the time it verifies that the
1946 * listener_may_exit flag is clear and the time it enters a
1947 * blocking syscall, the signal didn't do any good... work around
1948 * that by sleeping briefly and sending it again
1952 while (iter < 10 && !dying) {
1953 /* listener has not stopped accepting yet */
1954 apr_sleep(apr_time_make(0, 500000));
1959 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
1960 "the listener thread didn't stop accepting");
1963 rv = apr_thread_join(&thread_rv, listener);
1964 if (rv != APR_SUCCESS) {
1965 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
1966 "apr_thread_join: unable to join listener thread");
1971 for (i = 0; i < threads_per_child; i++) {
1972 if (threads[i]) { /* if we ever created this thread */
1973 rv = apr_thread_join(&thread_rv, threads[i]);
1974 if (rv != APR_SUCCESS) {
1975 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
1976 "apr_thread_join: unable to join worker "
1983 static void join_start_thread(apr_thread_t * start_thread_id)
1985 apr_status_t rv, thread_rv;
1987 start_thread_may_exit = 1; /* tell it to give up in case it is still
1988 * trying to take over slots from a
1989 * previous generation
1991 rv = apr_thread_join(&thread_rv, start_thread_id);
1992 if (rv != APR_SUCCESS) {
1993 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
1994 "apr_thread_join: unable to join the start " "thread");
1998 static void child_main(int child_num_arg)
2000 apr_thread_t **threads;
2003 apr_threadattr_t *thread_attr;
2004 apr_thread_t *start_thread_id;
2006 mpm_state = AP_MPMQ_STARTING; /* for benefit of any hooks that run as this
2009 ap_my_pid = getpid();
2010 ap_fatal_signal_child_setup(ap_server_conf);
2011 apr_pool_create(&pchild, pconf);
2013 /*stuff to do before we switch id's, so we have permissions. */
2014 ap_reopen_scoreboard(pchild, NULL, 0);
2016 if (ap_run_drop_privileges(pchild, ap_server_conf)) {
2017 clean_child_exit(APEXIT_CHILDFATAL);
2020 apr_thread_mutex_create(&g_timer_ring_mtx, APR_THREAD_MUTEX_DEFAULT, pchild);
2021 APR_RING_INIT(&timer_free_ring, timer_event_t, link);
2022 APR_RING_INIT(&timer_ring, timer_event_t, link);
2023 ap_run_child_init(pchild, ap_server_conf);
2025 /* done with init critical section */
2027 /* Just use the standard apr_setup_signal_thread to block all signals
2028 * from being received. The child processes no longer use signals for
2029 * any communication with the parent process.
2031 rv = apr_setup_signal_thread();
2032 if (rv != APR_SUCCESS) {
2033 ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
2034 "Couldn't initialize signal thread");
2035 clean_child_exit(APEXIT_CHILDFATAL);
2038 if (ap_max_requests_per_child) {
2039 requests_this_child = ap_max_requests_per_child;
2042 /* coding a value of zero means infinity */
2043 requests_this_child = INT_MAX;
2046 /* Setup worker threads */
2048 /* clear the storage; we may not create all our threads immediately,
2049 * and we want a 0 entry to indicate a thread which was not created
2051 threads = (apr_thread_t **) calloc(1,
2052 sizeof(apr_thread_t *) *
2054 if (threads == NULL) {
2055 ap_log_error(APLOG_MARK, APLOG_ALERT, errno, ap_server_conf,
2056 "malloc: out of memory");
2057 clean_child_exit(APEXIT_CHILDFATAL);
2060 ts = (thread_starter *) apr_palloc(pchild, sizeof(*ts));
2062 apr_threadattr_create(&thread_attr, pchild);
2063 /* 0 means PTHREAD_CREATE_JOINABLE */
2064 apr_threadattr_detach_set(thread_attr, 0);
2066 if (ap_thread_stacksize != 0) {
2067 apr_threadattr_stacksize_set(thread_attr, ap_thread_stacksize);
2070 ts->threads = threads;
2071 ts->listener = NULL;
2072 ts->child_num_arg = child_num_arg;
2073 ts->threadattr = thread_attr;
2075 rv = apr_thread_create(&start_thread_id, thread_attr, start_threads,
2077 if (rv != APR_SUCCESS) {
2078 ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
2079 "apr_thread_create: unable to create worker thread");
2080 /* let the parent decide how bad this really is */
2081 clean_child_exit(APEXIT_CHILDSICK);
2084 mpm_state = AP_MPMQ_RUNNING;
2086 /* If we are only running in one_process mode, we will want to
2087 * still handle signals. */
2089 /* Block until we get a terminating signal. */
2090 apr_signal_thread(check_signal);
2091 /* make sure the start thread has finished; signal_threads()
2092 * and join_workers() depend on that
2094 /* XXX join_start_thread() won't be awakened if one of our
2095 * threads encounters a critical error and attempts to
2096 * shutdown this child
2098 join_start_thread(start_thread_id);
2100 /* helps us terminate a little more quickly than the dispatch of the
2101 * signal thread; beats the Pipe of Death and the browsers
2103 signal_threads(ST_UNGRACEFUL);
2105 /* A terminating signal was received. Now join each of the
2106 * workers to clean them up.
2107 * If the worker already exited, then the join frees
2108 * their resources and returns.
2109 * If the worker hasn't exited, then this blocks until
2110 * they have (then cleans up).
2112 join_workers(ts->listener, threads);
2114 else { /* !one_process */
2115 /* remove SIGTERM from the set of blocked signals... if one of
2116 * the other threads in the process needs to take us down
2117 * (e.g., for MaxConnectionsPerChild) it will send us SIGTERM
2119 unblock_signal(SIGTERM);
2120 apr_signal(SIGTERM, dummy_signal_handler);
2121 /* Watch for any messages from the parent over the POD */
2123 rv = ap_event_pod_check(pod);
2124 if (rv == AP_NORESTART) {
2125 /* see if termination was triggered while we slept */
2126 switch (terminate_mode) {
2135 if (rv == AP_GRACEFUL || rv == AP_RESTART) {
2136 /* make sure the start thread has finished;
2137 * signal_threads() and join_workers depend on that
2139 join_start_thread(start_thread_id);
2140 signal_threads(rv ==
2141 AP_GRACEFUL ? ST_GRACEFUL : ST_UNGRACEFUL);
2146 /* A terminating signal was received. Now join each of the
2147 * workers to clean them up.
2148 * If the worker already exited, then the join frees
2149 * their resources and returns.
2150 * If the worker hasn't exited, then this blocks until
2151 * they have (then cleans up).
2153 join_workers(ts->listener, threads);
2158 clean_child_exit(resource_shortage ? APEXIT_CHILDSICK : 0);
2161 static int make_child(server_rec * s, int slot)
2165 if (slot + 1 > retained->max_daemons_limit) {
2166 retained->max_daemons_limit = slot + 1;
2171 event_note_child_started(slot, getpid());
2176 if ((pid = fork()) == -1) {
2177 ap_log_error(APLOG_MARK, APLOG_ERR, errno, s,
2178 "fork: Unable to fork new process");
2180 /* fork didn't succeed. There's no need to touch the scoreboard;
2181 * if we were trying to replace a failed child process, then
2182 * server_main_loop() marked its workers SERVER_DEAD, and if
2183 * we were trying to replace a child process that exited normally,
2184 * its worker_thread()s left SERVER_DEAD or SERVER_GRACEFUL behind.
2187 /* In case system resources are maxxed out, we don't want
2188 Apache running away with the CPU trying to fork over and
2189 over and over again. */
2190 apr_sleep(apr_time_from_sec(10));
2196 #ifdef HAVE_BINDPROCESSOR
2197 /* By default, AIX binds to a single processor. This bit unbinds
2198 * children which will then bind to another CPU.
2200 int status = bindprocessor(BINDPROCESS, (int) getpid(),
2201 PROCESSOR_CLASS_ANY);
2203 ap_log_error(APLOG_MARK, APLOG_DEBUG, errno,
2205 "processor unbind failed");
2207 RAISE_SIGSTOP(MAKE_CHILD);
2209 apr_signal(SIGTERM, just_die);
2214 if (ap_scoreboard_image->parent[slot].pid != 0) {
2215 /* This new child process is squatting on the scoreboard
2216 * entry owned by an exiting child process, which cannot
2217 * exit until all active requests complete.
2219 event_note_child_lost_slot(slot, pid);
2221 ap_scoreboard_image->parent[slot].quiescing = 0;
2222 ap_scoreboard_image->parent[slot].not_accepting = 0;
2223 event_note_child_started(slot, pid);
2227 /* start up a bunch of children */
2228 static void startup_children(int number_to_start)
2232 for (i = 0; number_to_start && i < ap_daemons_limit; ++i) {
2233 if (ap_scoreboard_image->parent[i].pid != 0) {
2236 if (make_child(ap_server_conf, i) < 0) {
2243 static void perform_idle_server_maintenance(void)
2246 int idle_thread_count;
2250 int totally_free_length = 0;
2251 int free_slots[MAX_SPAWN_RATE];
2254 int active_thread_count = 0;
2256 /* initialize the free_list */
2259 idle_thread_count = 0;
2263 for (i = 0; i < ap_daemons_limit; ++i) {
2264 /* Initialization to satisfy the compiler. It doesn't know
2265 * that threads_per_child is always > 0 */
2266 int status = SERVER_DEAD;
2267 int any_dying_threads = 0;
2268 int any_dead_threads = 0;
2269 int all_dead_threads = 1;
2271 if (i >= retained->max_daemons_limit
2272 && totally_free_length == retained->idle_spawn_rate)
2273 /* short cut if all active processes have been examined and
2274 * enough empty scoreboard slots have been found
2278 ps = &ap_scoreboard_image->parent[i];
2279 for (j = 0; j < threads_per_child; j++) {
2280 ws = &ap_scoreboard_image->servers[i][j];
2281 status = ws->status;
2283 /* XXX any_dying_threads is probably no longer needed GLA */
2284 any_dying_threads = any_dying_threads ||
2285 (status == SERVER_GRACEFUL);
2286 any_dead_threads = any_dead_threads || (status == SERVER_DEAD);
2287 all_dead_threads = all_dead_threads &&
2288 (status == SERVER_DEAD || status == SERVER_GRACEFUL);
2290 /* We consider a starting server as idle because we started it
2291 * at least a cycle ago, and if it still hasn't finished starting
2292 * then we're just going to swamp things worse by forking more.
2293 * So we hopefully won't need to fork more if we count it.
2294 * This depends on the ordering of SERVER_READY and SERVER_STARTING.
2296 if (ps->pid != 0) { /* XXX just set all_dead_threads in outer
2297 for loop if no pid? not much else matters */
2298 if (status <= SERVER_READY && !ps->quiescing && !ps->not_accepting
2299 && ps->generation == retained->my_generation)
2301 ++idle_thread_count;
2303 if (status >= SERVER_READY && status < SERVER_GRACEFUL) {
2304 ++active_thread_count;
2308 if (any_dead_threads
2309 && totally_free_length < retained->idle_spawn_rate
2310 && free_length < MAX_SPAWN_RATE
2311 && (!ps->pid /* no process in the slot */
2312 || ps->quiescing)) { /* or at least one is going away */
2313 if (all_dead_threads) {
2314 /* great! we prefer these, because the new process can
2315 * start more threads sooner. So prioritize this slot
2316 * by putting it ahead of any slots with active threads.
2318 * first, make room by moving a slot that's potentially still
2319 * in use to the end of the array
2321 free_slots[free_length] = free_slots[totally_free_length];
2322 free_slots[totally_free_length++] = i;
2325 /* slot is still in use - back of the bus
2327 free_slots[free_length] = i;
2331 /* XXX if (!ps->quiescing) is probably more reliable GLA */
2332 if (!any_dying_threads) {
2338 if (retained->sick_child_detected) {
2339 if (active_thread_count > 0) {
2340 /* some child processes appear to be working. don't kill the
2343 retained->sick_child_detected = 0;
2346 /* looks like a basket case. give up.
2348 shutdown_pending = 1;
2350 ap_log_error(APLOG_MARK, APLOG_ALERT, 0,
2352 "No active workers found..."
2353 " Apache is exiting!");
2354 /* the child already logged the failure details */
2359 retained->max_daemons_limit = last_non_dead + 1;
2361 if (idle_thread_count > max_spare_threads) {
2362 /* Kill off one child */
2363 ap_event_pod_signal(pod, TRUE);
2364 retained->idle_spawn_rate = 1;
2366 else if (idle_thread_count < min_spare_threads) {
2367 /* terminate the free list */
2368 if (free_length == 0) { /* scoreboard is full, can't fork */
2370 if (active_thread_count >= ap_daemons_limit * threads_per_child) {
2371 if (!retained->maxclients_reported) {
2372 /* only report this condition once */
2373 ap_log_error(APLOG_MARK, APLOG_ERR, 0,
2375 "server reached MaxClients setting, consider"
2376 " raising the MaxClients setting");
2377 retained->maxclients_reported = 1;
2381 ap_log_error(APLOG_MARK, APLOG_ERR, 0,
2383 "scoreboard is full, not at MaxClients");
2385 retained->idle_spawn_rate = 1;
2388 if (free_length > retained->idle_spawn_rate) {
2389 free_length = retained->idle_spawn_rate;
2391 if (retained->idle_spawn_rate >= 8) {
2392 ap_log_error(APLOG_MARK, APLOG_INFO, 0,
2394 "server seems busy, (you may need "
2395 "to increase StartServers, ThreadsPerChild "
2396 "or Min/MaxSpareThreads), "
2397 "spawning %d children, there are around %d idle "
2398 "threads, and %d total children", free_length,
2399 idle_thread_count, total_non_dead);
2401 for (i = 0; i < free_length; ++i) {
2402 make_child(ap_server_conf, free_slots[i]);
2404 /* the next time around we want to spawn twice as many if this
2405 * wasn't good enough, but not if we've just done a graceful
2407 if (retained->hold_off_on_exponential_spawning) {
2408 --retained->hold_off_on_exponential_spawning;
2410 else if (retained->idle_spawn_rate < MAX_SPAWN_RATE) {
2411 retained->idle_spawn_rate *= 2;
2416 retained->idle_spawn_rate = 1;
2420 static void server_main_loop(int remaining_children_to_start)
2422 ap_generation_t old_gen;
2424 apr_exit_why_e exitwhy;
2425 int status, processed_status;
2429 while (!restart_pending && !shutdown_pending) {
2430 ap_wait_or_timeout(&exitwhy, &status, &pid, pconf, ap_server_conf);
2432 if (pid.pid != -1) {
2433 processed_status = ap_process_child_status(&pid, exitwhy, status);
2434 if (processed_status == APEXIT_CHILDFATAL) {
2435 shutdown_pending = 1;
2439 else if (processed_status == APEXIT_CHILDSICK) {
2440 /* tell perform_idle_server_maintenance to check into this
2441 * on the next timer pop
2443 retained->sick_child_detected = 1;
2445 /* non-fatal death... note that it's gone in the scoreboard. */
2446 child_slot = ap_find_child_by_pid(&pid);
2447 if (child_slot >= 0) {
2448 for (i = 0; i < threads_per_child; i++)
2449 ap_update_child_status_from_indexes(child_slot, i,
2451 (request_rec *) NULL);
2453 event_note_child_killed(child_slot, 0, 0);
2454 ap_scoreboard_image->parent[child_slot].quiescing = 0;
2455 if (processed_status == APEXIT_CHILDSICK) {
2456 /* resource shortage, minimize the fork rate */
2457 retained->idle_spawn_rate = 1;
2459 else if (remaining_children_to_start
2460 && child_slot < ap_daemons_limit) {
2461 /* we're still doing a 1-for-1 replacement of dead
2462 * children with new children
2464 make_child(ap_server_conf, child_slot);
2465 --remaining_children_to_start;
2468 else if (ap_unregister_extra_mpm_process(pid.pid, &old_gen) == 1) {
2470 event_note_child_killed(-1, /* already out of the scoreboard */
2472 #if APR_HAS_OTHER_CHILD
2474 else if (apr_proc_other_child_alert(&pid, APR_OC_REASON_DEATH,
2479 else if (retained->is_graceful) {
2480 /* Great, we've probably just lost a slot in the
2481 * scoreboard. Somehow we don't know about this child.
2483 ap_log_error(APLOG_MARK, APLOG_WARNING, 0,
2485 "long lost child came home! (pid %ld)",
2488 /* Don't perform idle maintenance when a child dies,
2489 * only do it when there's a timeout. Remember only a
2490 * finite number of children can die, and it's pretty
2491 * pathological for a lot to die suddenly.
2495 else if (remaining_children_to_start) {
2496 /* we hit a 1 second timeout in which none of the previous
2497 * generation of children needed to be reaped... so assume
2498 * they're all done, and pick up the slack if any is left.
2500 startup_children(remaining_children_to_start);
2501 remaining_children_to_start = 0;
2502 /* In any event we really shouldn't do the code below because
2503 * few of the servers we just started are in the IDLE state
2504 * yet, so we'd mistakenly create an extra server.
2509 perform_idle_server_maintenance();
2513 static int event_run(apr_pool_t * _pconf, apr_pool_t * plog, server_rec * s)
2515 int remaining_children_to_start;
2517 ap_log_pid(pconf, ap_pid_fname);
2519 if (!retained->is_graceful) {
2520 if (ap_run_pre_mpm(s->process->pool, SB_SHARED) != OK) {
2521 mpm_state = AP_MPMQ_STOPPING;
2524 /* fix the generation number in the global score; we just got a new,
2525 * cleared scoreboard
2527 ap_scoreboard_image->global->running_generation = retained->my_generation;
2531 /* Don't thrash... */
2532 if (max_spare_threads < min_spare_threads + threads_per_child)
2533 max_spare_threads = min_spare_threads + threads_per_child;
2535 /* If we're doing a graceful_restart then we're going to see a lot
2536 * of children exiting immediately when we get into the main loop
2537 * below (because we just sent them AP_SIG_GRACEFUL). This happens pretty
2538 * rapidly... and for each one that exits we may start a new one, until
2539 * there are at least min_spare_threads idle threads, counting across
2540 * all children. But we may be permitted to start more children than
2541 * that, so we'll just keep track of how many we're
2542 * supposed to start up without the 1 second penalty between each fork.
2544 remaining_children_to_start = ap_daemons_to_start;
2545 if (remaining_children_to_start > ap_daemons_limit) {
2546 remaining_children_to_start = ap_daemons_limit;
2548 if (!retained->is_graceful) {
2549 startup_children(remaining_children_to_start);
2550 remaining_children_to_start = 0;
2553 /* give the system some time to recover before kicking into
2554 * exponential mode */
2555 retained->hold_off_on_exponential_spawning = 10;
2558 ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
2559 "%s configured -- resuming normal operations",
2560 ap_get_server_description());
2561 ap_log_error(APLOG_MARK, APLOG_INFO, 0, ap_server_conf,
2562 "Server built: %s", ap_get_server_built());
2563 ap_log_command_line(plog, s);
2565 restart_pending = shutdown_pending = 0;
2566 mpm_state = AP_MPMQ_RUNNING;
2568 server_main_loop(remaining_children_to_start);
2569 mpm_state = AP_MPMQ_STOPPING;
2571 if (shutdown_pending && !retained->is_graceful) {
2572 /* Time to shut down:
2573 * Kill child processes, tell them to call child_exit, etc...
2575 ap_event_pod_killpg(pod, ap_daemons_limit, FALSE);
2576 ap_reclaim_child_processes(1, /* Start with SIGTERM */
2577 event_note_child_killed);
2580 /* cleanup pid file on normal shutdown */
2581 ap_remove_pid(pconf, ap_pid_fname);
2582 ap_log_error(APLOG_MARK, APLOG_NOTICE, 0,
2583 ap_server_conf, "caught SIGTERM, shutting down");
2586 } else if (shutdown_pending) {
2587 /* Time to gracefully shut down:
2588 * Kill child processes, tell them to call child_exit, etc...
2590 int active_children;
2592 apr_time_t cutoff = 0;
2594 /* Close our listeners, and then ask our children to do same */
2595 ap_close_listeners();
2596 ap_event_pod_killpg(pod, ap_daemons_limit, TRUE);
2597 ap_relieve_child_processes(event_note_child_killed);
2600 /* cleanup pid file on normal shutdown */
2601 ap_remove_pid(pconf, ap_pid_fname);
2602 ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
2603 "caught " AP_SIG_GRACEFUL_STOP_STRING
2604 ", shutting down gracefully");
2607 if (ap_graceful_shutdown_timeout) {
2608 cutoff = apr_time_now() +
2609 apr_time_from_sec(ap_graceful_shutdown_timeout);
2612 /* Don't really exit until each child has finished */
2613 shutdown_pending = 0;
2615 /* Pause for a second */
2616 apr_sleep(apr_time_from_sec(1));
2618 /* Relieve any children which have now exited */
2619 ap_relieve_child_processes(event_note_child_killed);
2621 active_children = 0;
2622 for (index = 0; index < ap_daemons_limit; ++index) {
2623 if (ap_mpm_safe_kill(MPM_CHILD_PID(index), 0) == APR_SUCCESS) {
2624 active_children = 1;
2625 /* Having just one child is enough to stay around */
2629 } while (!shutdown_pending && active_children &&
2630 (!ap_graceful_shutdown_timeout || apr_time_now() < cutoff));
2632 /* We might be here because we received SIGTERM, either
2633 * way, try and make sure that all of our processes are
2636 ap_event_pod_killpg(pod, ap_daemons_limit, FALSE);
2637 ap_reclaim_child_processes(1, event_note_child_killed);
2642 /* we've been told to restart */
2643 apr_signal(SIGHUP, SIG_IGN);
2646 /* not worth thinking about */
2650 /* advance to the next generation */
2651 /* XXX: we really need to make sure this new generation number isn't in
2652 * use by any of the children.
2654 ++retained->my_generation;
2655 ap_scoreboard_image->global->running_generation = retained->my_generation;
2657 if (retained->is_graceful) {
2658 ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
2659 AP_SIG_GRACEFUL_STRING
2660 " received. Doing graceful restart");
2661 /* wake up the children...time to die. But we'll have more soon */
2662 ap_event_pod_killpg(pod, ap_daemons_limit, TRUE);
2665 /* This is mostly for debugging... so that we know what is still
2666 * gracefully dealing with existing request.
2671 /* Kill 'em all. Since the child acts the same on the parents SIGTERM
2672 * and a SIGHUP, we may as well use the same signal, because some user
2673 * pthreads are stealing signals from us left and right.
2675 ap_event_pod_killpg(pod, ap_daemons_limit, FALSE);
2677 ap_reclaim_child_processes(1, /* Start with SIGTERM */
2678 event_note_child_killed);
2679 ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
2680 "SIGHUP received. Attempting to restart");
2686 /* This really should be a post_config hook, but the error log is already
2687 * redirected by that point, so we need to do this in the open_logs phase.
2689 static int event_open_logs(apr_pool_t * p, apr_pool_t * plog,
2690 apr_pool_t * ptemp, server_rec * s)
2693 int level_flags = 0;
2698 /* the reverse of pre_config, we want this only the first time around */
2699 if (retained->module_loads == 1) {
2701 level_flags |= APLOG_STARTUP;
2704 if ((num_listensocks = ap_setup_listeners(ap_server_conf)) < 1) {
2705 ap_log_error(APLOG_MARK, APLOG_ALERT | level_flags, 0,
2706 (startup ? NULL : s),
2707 "no listening sockets available, shutting down");
2712 if ((rv = ap_event_pod_open(pconf, &pod))) {
2713 ap_log_error(APLOG_MARK, APLOG_CRIT | level_flags, rv,
2714 (startup ? NULL : s),
2715 "could not open pipe-of-death");
2722 static int event_pre_config(apr_pool_t * pconf, apr_pool_t * plog,
2725 int no_detach, debug, foreground;
2727 const char *userdata_key = "mpm_event_module";
2729 mpm_state = AP_MPMQ_STARTING;
2731 debug = ap_exists_config_define("DEBUG");
2734 foreground = one_process = 1;
2738 one_process = ap_exists_config_define("ONE_PROCESS");
2739 no_detach = ap_exists_config_define("NO_DETACH");
2740 foreground = ap_exists_config_define("FOREGROUND");
2743 /* sigh, want this only the second time around */
2744 retained = ap_retained_data_get(userdata_key);
2746 retained = ap_retained_data_create(userdata_key, sizeof(*retained));
2747 retained->max_daemons_limit = -1;
2748 retained->idle_spawn_rate = 1;
2750 ++retained->module_loads;
2751 if (retained->module_loads == 2) {
2752 rv = apr_pollset_create(&event_pollset, 1, plog,
2753 APR_POLLSET_THREADSAFE | APR_POLLSET_NOCOPY);
2754 if (rv != APR_SUCCESS) {
2755 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL,
2756 "Couldn't create a Thread Safe Pollset. "
2757 "Is it supported on your platform?"
2758 "Also check system or user limits!");
2759 return HTTP_INTERNAL_SERVER_ERROR;
2761 apr_pollset_destroy(event_pollset);
2763 if (!one_process && !foreground) {
2764 rv = apr_proc_detach(no_detach ? APR_PROC_DETACH_FOREGROUND
2765 : APR_PROC_DETACH_DAEMONIZE);
2766 if (rv != APR_SUCCESS) {
2767 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL,
2768 "apr_proc_detach failed");
2769 return HTTP_INTERNAL_SERVER_ERROR;
2774 parent_pid = ap_my_pid = getpid();
2776 ap_listen_pre_config();
2777 ap_daemons_to_start = DEFAULT_START_DAEMON;
2778 min_spare_threads = DEFAULT_MIN_FREE_DAEMON * DEFAULT_THREADS_PER_CHILD;
2779 max_spare_threads = DEFAULT_MAX_FREE_DAEMON * DEFAULT_THREADS_PER_CHILD;
2780 server_limit = DEFAULT_SERVER_LIMIT;
2781 thread_limit = DEFAULT_THREAD_LIMIT;
2782 ap_daemons_limit = server_limit;
2783 threads_per_child = DEFAULT_THREADS_PER_CHILD;
2784 max_clients = ap_daemons_limit * threads_per_child;
2785 ap_extended_status = 0;
2790 static int event_check_config(apr_pool_t *p, apr_pool_t *plog,
2791 apr_pool_t *ptemp, server_rec *s)
2795 /* the reverse of pre_config, we want this only the first time around */
2796 if (retained->module_loads == 1) {
2800 if (server_limit > MAX_SERVER_LIMIT) {
2802 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2803 "WARNING: ServerLimit of %d exceeds compile-time "
2804 "limit of", server_limit);
2805 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2806 " %d servers, decreasing to %d.",
2807 MAX_SERVER_LIMIT, MAX_SERVER_LIMIT);
2809 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
2810 "ServerLimit of %d exceeds compile-time limit "
2811 "of %d, decreasing to match",
2812 server_limit, MAX_SERVER_LIMIT);
2814 server_limit = MAX_SERVER_LIMIT;
2816 else if (server_limit < 1) {
2818 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2819 "WARNING: ServerLimit of %d not allowed, "
2820 "increasing to 1.", server_limit);
2822 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
2823 "ServerLimit of %d not allowed, increasing to 1",
2829 /* you cannot change ServerLimit across a restart; ignore
2832 if (!retained->first_server_limit) {
2833 retained->first_server_limit = server_limit;
2835 else if (server_limit != retained->first_server_limit) {
2836 /* don't need a startup console version here */
2837 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
2838 "changing ServerLimit to %d from original value of %d "
2839 "not allowed during restart",
2840 server_limit, retained->first_server_limit);
2841 server_limit = retained->first_server_limit;
2844 if (thread_limit > MAX_THREAD_LIMIT) {
2846 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2847 "WARNING: ThreadLimit of %d exceeds compile-time "
2848 "limit of", thread_limit);
2849 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2850 " %d threads, decreasing to %d.",
2851 MAX_THREAD_LIMIT, MAX_THREAD_LIMIT);
2853 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
2854 "ThreadLimit of %d exceeds compile-time limit "
2855 "of %d, decreasing to match",
2856 thread_limit, MAX_THREAD_LIMIT);
2858 thread_limit = MAX_THREAD_LIMIT;
2860 else if (thread_limit < 1) {
2862 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2863 "WARNING: ThreadLimit of %d not allowed, "
2864 "increasing to 1.", thread_limit);
2866 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
2867 "ThreadLimit of %d not allowed, increasing to 1",
2873 /* you cannot change ThreadLimit across a restart; ignore
2876 if (!retained->first_thread_limit) {
2877 retained->first_thread_limit = thread_limit;
2879 else if (thread_limit != retained->first_thread_limit) {
2880 /* don't need a startup console version here */
2881 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
2882 "changing ThreadLimit to %d from original value of %d "
2883 "not allowed during restart",
2884 thread_limit, retained->first_thread_limit);
2885 thread_limit = retained->first_thread_limit;
2888 if (threads_per_child > thread_limit) {
2890 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2891 "WARNING: ThreadsPerChild of %d exceeds ThreadLimit "
2892 "of", threads_per_child);
2893 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2894 " %d threads, decreasing to %d.",
2895 thread_limit, thread_limit);
2896 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2897 " To increase, please see the ThreadLimit "
2900 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
2901 "ThreadsPerChild of %d exceeds ThreadLimit "
2902 "of %d, decreasing to match",
2903 threads_per_child, thread_limit);
2905 threads_per_child = thread_limit;
2907 else if (threads_per_child < 1) {
2909 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2910 "WARNING: ThreadsPerChild of %d not allowed, "
2911 "increasing to 1.", threads_per_child);
2913 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
2914 "ThreadsPerChild of %d not allowed, increasing to 1",
2917 threads_per_child = 1;
2920 if (max_clients < threads_per_child) {
2922 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2923 "WARNING: MaxClients of %d is less than "
2924 "ThreadsPerChild of", max_clients);
2925 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2926 " %d, increasing to %d. MaxClients must be at "
2928 threads_per_child, threads_per_child);
2929 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2930 " as the number of threads in a single server.");
2932 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
2933 "MaxClients of %d is less than ThreadsPerChild "
2934 "of %d, increasing to match",
2935 max_clients, threads_per_child);
2937 max_clients = threads_per_child;
2940 ap_daemons_limit = max_clients / threads_per_child;
2942 if (max_clients % threads_per_child) {
2943 int tmp_max_clients = ap_daemons_limit * threads_per_child;
2946 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2947 "WARNING: MaxClients of %d is not an integer "
2948 "multiple of", max_clients);
2949 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2950 " ThreadsPerChild of %d, decreasing to nearest "
2951 "multiple %d,", threads_per_child,
2953 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2954 " for a maximum of %d servers.",
2957 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
2958 "MaxClients of %d is not an integer multiple of "
2959 "ThreadsPerChild of %d, decreasing to nearest "
2960 "multiple %d", max_clients, threads_per_child,
2963 max_clients = tmp_max_clients;
2966 if (ap_daemons_limit > server_limit) {
2968 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2969 "WARNING: MaxClients of %d would require %d "
2970 "servers and ", max_clients, ap_daemons_limit);
2971 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2972 " would exceed ServerLimit of %d, decreasing to %d.",
2973 server_limit, server_limit * threads_per_child);
2974 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2975 " To increase, please see the ServerLimit "
2978 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
2979 "MaxClients of %d would require %d servers and "
2980 "exceed ServerLimit of %d, decreasing to %d",
2981 max_clients, ap_daemons_limit, server_limit,
2982 server_limit * threads_per_child);
2984 ap_daemons_limit = server_limit;
2987 /* ap_daemons_to_start > ap_daemons_limit checked in ap_mpm_run() */
2988 if (ap_daemons_to_start < 0) {
2990 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2991 "WARNING: StartServers of %d not allowed, "
2992 "increasing to 1.", ap_daemons_to_start);
2994 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
2995 "StartServers of %d not allowed, increasing to 1",
2996 ap_daemons_to_start);
2998 ap_daemons_to_start = 1;
3001 if (min_spare_threads < 1) {
3003 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
3004 "WARNING: MinSpareThreads of %d not allowed, "
3005 "increasing to 1", min_spare_threads);
3006 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
3007 " to avoid almost certain server failure.");
3008 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
3009 " Please read the documentation.");
3011 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
3012 "MinSpareThreads of %d not allowed, increasing to 1",
3015 min_spare_threads = 1;
3018 /* max_spare_threads < min_spare_threads + threads_per_child
3019 * checked in ap_mpm_run()
3025 static void event_hooks(apr_pool_t * p)
3027 /* Our open_logs hook function must run before the core's, or stderr
3028 * will be redirected to a file, and the messages won't print to the
3031 static const char *const aszSucc[] = { "core.c", NULL };
3034 ap_hook_open_logs(event_open_logs, NULL, aszSucc, APR_HOOK_REALLY_FIRST);
3035 /* we need to set the MPM state before other pre-config hooks use MPM query
3036 * to retrieve it, so register as REALLY_FIRST
3038 ap_hook_pre_config(event_pre_config, NULL, NULL, APR_HOOK_REALLY_FIRST);
3039 ap_hook_check_config(event_check_config, NULL, NULL, APR_HOOK_MIDDLE);
3040 ap_hook_mpm(event_run, NULL, NULL, APR_HOOK_MIDDLE);
3041 ap_hook_mpm_query(event_query, NULL, NULL, APR_HOOK_MIDDLE);
3042 ap_hook_mpm_register_timed_callback(event_register_timed_callback, NULL, NULL,
3044 ap_hook_mpm_get_name(event_get_name, NULL, NULL, APR_HOOK_MIDDLE);
3047 static const char *set_daemons_to_start(cmd_parms *cmd, void *dummy,
3050 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3055 ap_daemons_to_start = atoi(arg);
3059 static const char *set_min_spare_threads(cmd_parms * cmd, void *dummy,
3062 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3067 min_spare_threads = atoi(arg);
3071 static const char *set_max_spare_threads(cmd_parms * cmd, void *dummy,
3074 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3079 max_spare_threads = atoi(arg);
3083 static const char *set_max_clients(cmd_parms * cmd, void *dummy,
3086 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3091 max_clients = atoi(arg);
3095 static const char *set_threads_per_child(cmd_parms * cmd, void *dummy,
3098 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3103 threads_per_child = atoi(arg);
3106 static const char *set_server_limit (cmd_parms *cmd, void *dummy, const char *arg)
3108 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3113 server_limit = atoi(arg);
3117 static const char *set_thread_limit(cmd_parms * cmd, void *dummy,
3120 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3125 thread_limit = atoi(arg);
3129 static const command_rec event_cmds[] = {
3131 AP_INIT_TAKE1("StartServers", set_daemons_to_start, NULL, RSRC_CONF,
3132 "Number of child processes launched at server startup"),
3133 AP_INIT_TAKE1("ServerLimit", set_server_limit, NULL, RSRC_CONF,
3134 "Maximum number of child processes for this run of Apache"),
3135 AP_INIT_TAKE1("MinSpareThreads", set_min_spare_threads, NULL, RSRC_CONF,
3136 "Minimum number of idle threads, to handle request spikes"),
3137 AP_INIT_TAKE1("MaxSpareThreads", set_max_spare_threads, NULL, RSRC_CONF,
3138 "Maximum number of idle threads"),
3139 AP_INIT_TAKE1("MaxClients", set_max_clients, NULL, RSRC_CONF,
3140 "Maximum number of threads alive at the same time"),
3141 AP_INIT_TAKE1("ThreadsPerChild", set_threads_per_child, NULL, RSRC_CONF,
3142 "Number of threads each child creates"),
3143 AP_INIT_TAKE1("ThreadLimit", set_thread_limit, NULL, RSRC_CONF,
3144 "Maximum number of worker threads per child process for this "
3145 "run of Apache - Upper limit for ThreadsPerChild"),
3146 AP_GRACEFUL_SHUTDOWN_TIMEOUT_COMMAND,
3150 AP_DECLARE_MODULE(mpm_event) = {
3152 NULL, /* hook to run before apache parses args */
3153 NULL, /* create per-directory config structure */
3154 NULL, /* merge per-directory config structures */
3155 NULL, /* create per-server config structure */
3156 NULL, /* merge per-server config structures */
3157 event_cmds, /* command apr_table_t */
3158 event_hooks /* register_hooks */