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.
17 /* The purpose of this MPM is to fix the design flaws in the threaded
18 * model. Because of the way that pthreads and mutex locks interact,
19 * it is basically impossible to cleanly gracefully shutdown a child
20 * process if multiple threads are all blocked in accept. This model
21 * fixes those problems.
25 #include "apr_portable.h"
26 #include "apr_strings.h"
27 #include "apr_file_io.h"
28 #include "apr_thread_proc.h"
29 #include "apr_signal.h"
30 #include "apr_thread_mutex.h"
31 #include "apr_proc_mutex.h"
33 #define APR_WANT_STRFUNC
39 #if APR_HAVE_SYS_SOCKET_H
40 #include <sys/socket.h>
42 #if APR_HAVE_SYS_WAIT_H
45 #ifdef HAVE_SYS_PROCESSOR_H
46 #include <sys/processor.h> /* for bindprocessor() */
50 #error The Worker MPM requires APR threads, but they are unavailable.
55 #include "ap_config.h"
57 #include "http_main.h"
59 #include "http_config.h" /* for read_config */
60 #include "http_core.h" /* for get_remote_host */
61 #include "http_connection.h"
64 #include "mpm_common.h"
65 #include "ap_listen.h"
66 #include "scoreboard.h"
68 #include "mpm_default.h"
71 #include <limits.h> /* for INT_MAX */
73 /* Limit on the total --- clients will be locked out if more servers than
74 * this are needed. It is intended solely to keep the server from crashing
75 * when things get out of hand.
77 * We keep a hard maximum number of servers, for two reasons --- first off,
78 * in case something goes seriously wrong, we want to stop the fork bomb
79 * short of actually crashing the machine we're running on by filling some
80 * kernel table. Secondly, it keeps the size of the scoreboard file small
81 * enough that we can read the whole thing without worrying too much about
84 #ifndef DEFAULT_SERVER_LIMIT
85 #define DEFAULT_SERVER_LIMIT 16
88 /* Admin can't tune ServerLimit beyond MAX_SERVER_LIMIT. We want
89 * some sort of compile-time limit to help catch typos.
91 #ifndef MAX_SERVER_LIMIT
92 #define MAX_SERVER_LIMIT 20000
95 /* Limit on the threads per process. Clients will be locked out if more than
96 * this * server_limit are needed.
98 * We keep this for one reason it keeps the size of the scoreboard file small
99 * enough that we can read the whole thing without worrying too much about
102 #ifndef DEFAULT_THREAD_LIMIT
103 #define DEFAULT_THREAD_LIMIT 64
106 /* Admin can't tune ThreadLimit beyond MAX_THREAD_LIMIT. We want
107 * some sort of compile-time limit to help catch typos.
109 #ifndef MAX_THREAD_LIMIT
110 #define MAX_THREAD_LIMIT 20000
114 * Actual definitions of config globals
117 int ap_threads_per_child = 0; /* Worker threads per child */
118 static int ap_daemons_to_start = 0;
119 static int min_spare_threads = 0;
120 static int max_spare_threads = 0;
121 static int ap_daemons_limit = 0;
122 static int max_clients = 0;
123 static int server_limit = 0;
124 static int first_server_limit = 0;
125 static int thread_limit = 0;
126 static int first_thread_limit = 0;
127 static int dying = 0;
128 static int workers_may_exit = 0;
129 static int start_thread_may_exit = 0;
130 static int listener_may_exit = 0;
131 static int requests_this_child;
132 static int num_listensocks = 0;
133 static int resource_shortage = 0;
134 static fd_queue_t *worker_queue;
135 static fd_queue_info_t *worker_queue_info;
136 static int mpm_state = AP_MPMQ_STARTING;
137 static int sick_child_detected;
139 /* The structure used to pass unique initialization info to each thread */
146 /* Structure used to pass information to the thread responsible for
147 * creating the rest of the threads.
150 apr_thread_t **threads;
151 apr_thread_t *listener;
153 apr_threadattr_t *threadattr;
156 #define ID_FROM_CHILD_THREAD(c, t) ((c * thread_limit) + t)
159 * The max child slot ever assigned, preserved across restarts. Necessary
160 * to deal with MaxClients changes across AP_SIG_GRACEFUL restarts. We
161 * use this value to optimize routines that have to scan the entire
164 int ap_max_daemons_limit = -1;
166 static ap_pod_t *pod;
168 /* *Non*-shared http_main globals... */
170 server_rec *ap_server_conf;
172 /* The worker MPM respects a couple of runtime flags that can aid
173 * in debugging. Setting the -DNO_DETACH flag will prevent the root process
174 * from detaching from its controlling terminal. Additionally, setting
175 * the -DONE_PROCESS flag (which implies -DNO_DETACH) will get you the
176 * child_main loop running in the process which originally started up.
177 * This gives you a pretty nice debugging environment. (You'll get a SIGHUP
178 * early in standalone_main; just continue through. This is the server
179 * trying to kill off any child processes which it might have lying
180 * around --- Apache doesn't keep track of their pids, it just sends
181 * SIGHUP to the process group, ignoring it in the root process.
182 * Continue through and you'll be fine.).
185 static int one_process = 0;
188 int raise_sigstop_flags;
191 static apr_pool_t *pconf; /* Pool for config stuff */
192 static apr_pool_t *pchild; /* Pool for httpd child stuff */
194 static pid_t ap_my_pid; /* Linux getpid() doesn't work except in main
195 thread. Use this instead */
196 static pid_t parent_pid;
197 static apr_os_thread_t *listener_os_thread;
199 /* Locks for accept serialization */
200 static apr_proc_mutex_t *accept_mutex;
202 #ifdef SINGLE_LISTEN_UNSERIALIZED_ACCEPT
203 #define SAFE_ACCEPT(stmt) (ap_listeners->next ? (stmt) : APR_SUCCESS)
205 #define SAFE_ACCEPT(stmt) (stmt)
208 /* The LISTENER_SIGNAL signal will be sent from the main thread to the
209 * listener thread to wake it up for graceful termination (what a child
210 * process from an old generation does when the admin does "apachectl
211 * graceful"). This signal will be blocked in all threads of a child
212 * process except for the listener thread.
214 #define LISTENER_SIGNAL SIGHUP
216 /* The WORKER_SIGNAL signal will be sent from the main thread to the
217 * worker threads during an ungraceful restart or shutdown.
218 * This ensures that on systems (i.e., Linux) where closing the worker
219 * socket doesn't awake the worker thread when it is polling on the socket
220 * (especially in apr_wait_for_io_or_timeout() when handling
221 * Keep-Alive connections), close_worker_sockets() and join_workers()
222 * still function in timely manner and allow ungraceful shutdowns to
223 * proceed to completion. Otherwise join_workers() doesn't return
224 * before the main process decides the child process is non-responsive
225 * and sends a SIGKILL.
227 #define WORKER_SIGNAL AP_SIG_GRACEFUL
229 /* An array of socket descriptors in use by each thread used to
230 * perform a non-graceful (forced) shutdown of the server. */
231 static apr_socket_t **worker_sockets;
233 static void close_worker_sockets(void)
236 for (i = 0; i < ap_threads_per_child; i++) {
237 if (worker_sockets[i]) {
238 apr_socket_close(worker_sockets[i]);
239 worker_sockets[i] = NULL;
244 static void wakeup_listener(void)
246 listener_may_exit = 1;
247 if (!listener_os_thread) {
248 /* XXX there is an obscure path that this doesn't handle perfectly:
249 * right after listener thread is created but before
250 * listener_os_thread is set, the first worker thread hits an
251 * error and starts graceful termination
256 * we should just be able to "kill(ap_my_pid, LISTENER_SIGNAL)" on all
257 * platforms and wake up the listener thread since it is the only thread
258 * with SIGHUP unblocked, but that doesn't work on Linux
260 #ifdef HAVE_PTHREAD_KILL
261 pthread_kill(*listener_os_thread, LISTENER_SIGNAL);
263 kill(ap_my_pid, LISTENER_SIGNAL);
268 #define ST_GRACEFUL 1
269 #define ST_UNGRACEFUL 2
271 static int terminate_mode = ST_INIT;
273 static void signal_threads(int mode)
275 if (terminate_mode == mode) {
278 terminate_mode = mode;
279 mpm_state = AP_MPMQ_STOPPING;
281 /* in case we weren't called from the listener thread, wake up the
286 /* for ungraceful termination, let the workers exit now;
287 * for graceful termination, the listener thread will notify the
288 * workers to exit once it has stopped accepting new connections
290 if (mode == ST_UNGRACEFUL) {
291 workers_may_exit = 1;
292 ap_queue_interrupt_all(worker_queue);
293 ap_queue_info_term(worker_queue_info);
294 close_worker_sockets(); /* forcefully kill all current connections */
298 AP_DECLARE(apr_status_t) ap_mpm_query(int query_code, int *result)
301 case AP_MPMQ_MAX_DAEMON_USED:
302 *result = ap_max_daemons_limit;
304 case AP_MPMQ_IS_THREADED:
305 *result = AP_MPMQ_STATIC;
307 case AP_MPMQ_IS_FORKED:
308 *result = AP_MPMQ_DYNAMIC;
310 case AP_MPMQ_HARD_LIMIT_DAEMONS:
311 *result = server_limit;
313 case AP_MPMQ_HARD_LIMIT_THREADS:
314 *result = thread_limit;
316 case AP_MPMQ_MAX_THREADS:
317 *result = ap_threads_per_child;
319 case AP_MPMQ_MIN_SPARE_DAEMONS:
322 case AP_MPMQ_MIN_SPARE_THREADS:
323 *result = min_spare_threads;
325 case AP_MPMQ_MAX_SPARE_DAEMONS:
328 case AP_MPMQ_MAX_SPARE_THREADS:
329 *result = max_spare_threads;
331 case AP_MPMQ_MAX_REQUESTS_DAEMON:
332 *result = ap_max_requests_per_child;
334 case AP_MPMQ_MAX_DAEMONS:
335 *result = ap_daemons_limit;
337 case AP_MPMQ_MPM_STATE:
344 /* a clean exit from a child with proper cleanup */
345 static void clean_child_exit(int code) __attribute__ ((noreturn));
346 static void clean_child_exit(int code)
348 mpm_state = AP_MPMQ_STOPPING;
350 apr_pool_destroy(pchild);
355 static void just_die(int sig)
360 /*****************************************************************
361 * Connection structures and accounting...
364 /* volatile just in case */
365 static int volatile shutdown_pending;
366 static int volatile restart_pending;
367 static int volatile is_graceful;
368 static volatile int child_fatal;
369 ap_generation_t volatile ap_my_generation = 0;
372 * ap_start_shutdown() and ap_start_restart(), below, are a first stab at
373 * functions to initiate shutdown or restart without relying on signals.
374 * Previously this was initiated in sig_term() and restart() signal handlers,
375 * but we want to be able to start a shutdown/restart from other sources --
376 * e.g. on Win32, from the service manager. Now the service manager can
377 * call ap_start_shutdown() or ap_start_restart() as appropiate. Note that
378 * these functions can also be called by the child processes, since global
379 * variables are no longer used to pass on the required action to the parent.
381 * These should only be called from the parent process itself, since the
382 * parent process will use the shutdown_pending and restart_pending variables
383 * to determine whether to shutdown or restart. The child process should
384 * call signal_parent() directly to tell the parent to die -- this will
385 * cause neither of those variable to be set, which the parent will
386 * assume means something serious is wrong (which it will be, for the
387 * child to force an exit) and so do an exit anyway.
390 static void ap_start_shutdown(int graceful)
392 mpm_state = AP_MPMQ_STOPPING;
393 if (shutdown_pending == 1) {
394 /* Um, is this _probably_ not an error, if the user has
395 * tried to do a shutdown twice quickly, so we won't
396 * worry about reporting it.
400 shutdown_pending = 1;
401 is_graceful = graceful;
404 /* do a graceful restart if graceful == 1 */
405 static void ap_start_restart(int graceful)
407 mpm_state = AP_MPMQ_STOPPING;
408 if (restart_pending == 1) {
409 /* Probably not an error - don't bother reporting it */
413 is_graceful = graceful;
416 static void sig_term(int sig)
418 ap_start_shutdown(sig == AP_SIG_GRACEFUL_STOP);
421 static void restart(int sig)
423 ap_start_restart(sig == AP_SIG_GRACEFUL);
426 static void set_signals(void)
428 #ifndef NO_USE_SIGACTION
433 ap_fatal_signal_setup(ap_server_conf, pconf);
436 #ifndef NO_USE_SIGACTION
437 sigemptyset(&sa.sa_mask);
440 sa.sa_handler = sig_term;
441 if (sigaction(SIGTERM, &sa, NULL) < 0)
442 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
443 "sigaction(SIGTERM)");
444 #ifdef AP_SIG_GRACEFUL_STOP
445 if (sigaction(AP_SIG_GRACEFUL_STOP, &sa, NULL) < 0)
446 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
447 "sigaction(" AP_SIG_GRACEFUL_STOP_STRING ")");
450 if (sigaction(SIGINT, &sa, NULL) < 0)
451 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
452 "sigaction(SIGINT)");
455 sa.sa_handler = SIG_DFL;
456 if (sigaction(SIGXCPU, &sa, NULL) < 0)
457 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
458 "sigaction(SIGXCPU)");
461 sa.sa_handler = SIG_DFL;
462 if (sigaction(SIGXFSZ, &sa, NULL) < 0)
463 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
464 "sigaction(SIGXFSZ)");
467 sa.sa_handler = SIG_IGN;
468 if (sigaction(SIGPIPE, &sa, NULL) < 0)
469 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
470 "sigaction(SIGPIPE)");
473 /* we want to ignore HUPs and AP_SIG_GRACEFUL while we're busy
475 sigaddset(&sa.sa_mask, SIGHUP);
476 sigaddset(&sa.sa_mask, AP_SIG_GRACEFUL);
477 sa.sa_handler = restart;
478 if (sigaction(SIGHUP, &sa, NULL) < 0)
479 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
480 "sigaction(SIGHUP)");
481 if (sigaction(AP_SIG_GRACEFUL, &sa, NULL) < 0)
482 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
483 "sigaction(" AP_SIG_GRACEFUL_STRING ")");
487 apr_signal(SIGXCPU, SIG_DFL);
490 apr_signal(SIGXFSZ, SIG_DFL);
494 apr_signal(SIGTERM, sig_term);
496 apr_signal(SIGHUP, restart);
498 #ifdef AP_SIG_GRACEFUL
499 apr_signal(AP_SIG_GRACEFUL, restart);
500 #endif /* AP_SIG_GRACEFUL */
501 #ifdef AP_SIG_GRACEFUL_STOP
502 apr_signal(AP_SIG_GRACEFUL_STOP, sig_term);
503 #endif /* AP_SIG_GRACEFUL_STOP */
505 apr_signal(SIGPIPE, SIG_IGN);
511 /*****************************************************************
512 * Here follows a long bunch of generic server bookkeeping stuff...
515 int ap_graceful_stop_signalled(void)
516 /* XXX this is really a bad confusing obsolete name
517 * maybe it should be ap_mpm_process_exiting?
520 /* note: for a graceful termination, listener_may_exit will be set before
521 * workers_may_exit, so check listener_may_exit
523 return listener_may_exit;
526 /*****************************************************************
527 * Child process main loop.
530 static void process_socket(apr_pool_t *p, apr_socket_t *sock, int my_child_num,
531 int my_thread_num, apr_bucket_alloc_t *bucket_alloc)
533 conn_rec *current_conn;
534 long conn_id = ID_FROM_CHILD_THREAD(my_child_num, my_thread_num);
537 ap_create_sb_handle(&sbh, p, my_child_num, my_thread_num);
539 current_conn = ap_run_create_connection(p, ap_server_conf, sock,
540 conn_id, sbh, bucket_alloc);
542 ap_process_connection(current_conn, sock);
543 ap_lingering_close(current_conn);
547 /* requests_this_child has gone to zero or below. See if the admin coded
548 "MaxRequestsPerChild 0", and keep going in that case. Doing it this way
549 simplifies the hot path in worker_thread */
550 static void check_infinite_requests(void)
552 if (ap_max_requests_per_child) {
553 signal_threads(ST_GRACEFUL);
556 /* wow! if you're executing this code, you may have set a record.
557 * either this child process has served over 2 billion requests, or
558 * you're running a threaded 2.0 on a 16 bit machine.
560 * I'll buy pizza and beers at Apachecon for the first person to do
561 * the former without cheating (dorking with INT_MAX, or running with
562 * uncommitted performance patches, for example).
564 * for the latter case, you probably deserve a beer too. Greg Ames
567 requests_this_child = INT_MAX; /* keep going */
571 static void unblock_signal(int sig)
575 sigemptyset(&sig_mask);
576 sigaddset(&sig_mask, sig);
577 #if defined(SIGPROCMASK_SETS_THREAD_MASK)
578 sigprocmask(SIG_UNBLOCK, &sig_mask, NULL);
580 pthread_sigmask(SIG_UNBLOCK, &sig_mask, NULL);
584 static void dummy_signal_handler(int sig)
586 /* XXX If specifying SIG_IGN is guaranteed to unblock a syscall,
587 * then we don't need this goofy function.
591 static void * APR_THREAD_FUNC listener_thread(apr_thread_t *thd, void * dummy)
593 proc_info * ti = dummy;
594 int process_slot = ti->pid;
595 apr_pool_t *tpool = apr_thread_pool_get(thd);
597 apr_pool_t *ptrans = NULL; /* Pool for per-transaction stuff */
598 apr_pollset_t *pollset;
601 int have_idle_worker = 0;
602 int last_poll_idx = 0;
606 /* ### check the status */
607 (void) apr_pollset_create(&pollset, num_listensocks, tpool, 0);
609 for (lr = ap_listeners; lr != NULL; lr = lr->next) {
610 apr_pollfd_t pfd = { 0 };
612 pfd.desc_type = APR_POLL_SOCKET;
614 pfd.reqevents = APR_POLLIN;
615 pfd.client_data = lr;
617 /* ### check the status */
618 (void) apr_pollset_add(pollset, &pfd);
621 /* Unblock the signal used to wake this thread up, and set a handler for
624 unblock_signal(LISTENER_SIGNAL);
625 apr_signal(LISTENER_SIGNAL, dummy_signal_handler);
627 /* TODO: Switch to a system where threads reuse the results from earlier
628 poll calls - manoj */
630 /* TODO: requests_this_child should be synchronized - aaron */
631 if (requests_this_child <= 0) {
632 check_infinite_requests();
634 if (listener_may_exit) break;
636 if (!have_idle_worker) {
637 /* the following pops a recycled ptrans pool off a stack
638 * if there is one, in addition to reserving a worker thread
640 rv = ap_queue_info_wait_for_idler(worker_queue_info,
642 if (APR_STATUS_IS_EOF(rv)) {
643 break; /* we've been signaled to die now */
645 else if (rv != APR_SUCCESS) {
646 ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
647 "apr_queue_info_wait failed. Attempting to "
648 " shutdown process gracefully.");
649 signal_threads(ST_GRACEFUL);
652 have_idle_worker = 1;
655 /* We've already decremented the idle worker count inside
656 * ap_queue_info_wait_for_idler. */
658 if ((rv = SAFE_ACCEPT(apr_proc_mutex_lock(accept_mutex)))
660 int level = APLOG_EMERG;
662 if (listener_may_exit) {
665 if (ap_scoreboard_image->parent[process_slot].generation !=
666 ap_scoreboard_image->global->running_generation) {
667 level = APLOG_DEBUG; /* common to get these at restart time */
669 ap_log_error(APLOG_MARK, level, rv, ap_server_conf,
670 "apr_proc_mutex_lock failed. Attempting to shutdown "
671 "process gracefully.");
672 signal_threads(ST_GRACEFUL);
673 break; /* skip the lock release */
676 if (!ap_listeners->next) {
677 /* Only one listener, so skip the poll */
681 while (!listener_may_exit) {
683 const apr_pollfd_t *pdesc;
685 rv = apr_pollset_poll(pollset, -1, &numdesc, &pdesc);
686 if (rv != APR_SUCCESS) {
687 if (APR_STATUS_IS_EINTR(rv)) {
691 /* apr_pollset_poll() will only return errors in catastrophic
692 * circumstances. Let's try exiting gracefully, for now. */
693 ap_log_error(APLOG_MARK, APLOG_ERR, rv,
694 (const server_rec *) ap_server_conf,
695 "apr_pollset_poll: (listen)");
696 signal_threads(ST_GRACEFUL);
699 if (listener_may_exit) break;
701 /* We can always use pdesc[0], but sockets at position N
702 * could end up completely starved of attention in a very
703 * busy server. Therefore, we round-robin across the
704 * returned set of descriptors. While it is possible that
705 * the returned set of descriptors might flip around and
706 * continue to starve some sockets, we happen to know the
707 * internal pollset implementation retains ordering
708 * stability of the sockets. Thus, the round-robin should
709 * ensure that a socket will eventually be serviced.
711 if (last_poll_idx >= numdesc)
714 /* Grab a listener record from the client_data of the poll
715 * descriptor, and advance our saved index to round-robin
718 * ### hmm... this descriptor might have POLLERR rather
721 lr = pdesc[last_poll_idx++].client_data;
728 if (!listener_may_exit) {
729 if (ptrans == NULL) {
730 /* we can't use a recycled transaction pool this time.
731 * create a new transaction pool */
732 apr_allocator_t *allocator;
734 apr_allocator_create(&allocator);
735 apr_allocator_max_free_set(allocator, ap_max_mem_free);
736 apr_pool_create_ex(&ptrans, pconf, NULL, allocator);
737 apr_allocator_owner_set(allocator, ptrans);
739 apr_pool_tag(ptrans, "transaction");
740 rv = lr->accept_func(&csd, lr, ptrans);
741 /* later we trash rv and rely on csd to indicate success/failure */
742 AP_DEBUG_ASSERT(rv == APR_SUCCESS || !csd);
744 if (rv == APR_EGENERAL) {
745 /* E[NM]FILE, ENOMEM, etc */
746 resource_shortage = 1;
747 signal_threads(ST_GRACEFUL);
749 if ((rv = SAFE_ACCEPT(apr_proc_mutex_unlock(accept_mutex)))
751 int level = APLOG_EMERG;
753 if (listener_may_exit) {
756 if (ap_scoreboard_image->parent[process_slot].generation !=
757 ap_scoreboard_image->global->running_generation) {
758 level = APLOG_DEBUG; /* common to get these at restart time */
760 ap_log_error(APLOG_MARK, level, rv, ap_server_conf,
761 "apr_proc_mutex_unlock failed. Attempting to "
762 "shutdown process gracefully.");
763 signal_threads(ST_GRACEFUL);
766 rv = ap_queue_push(worker_queue, csd, ptrans);
768 /* trash the connection; we couldn't queue the connected
771 apr_socket_close(csd);
772 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
773 "ap_queue_push failed");
776 have_idle_worker = 0;
781 if ((rv = SAFE_ACCEPT(apr_proc_mutex_unlock(accept_mutex)))
783 int level = APLOG_EMERG;
785 if (ap_scoreboard_image->parent[process_slot].generation !=
786 ap_scoreboard_image->global->running_generation) {
787 level = APLOG_DEBUG; /* common to get these at restart time */
789 ap_log_error(APLOG_MARK, level, rv, ap_server_conf,
790 "apr_proc_mutex_unlock failed. Attempting to "
791 "shutdown process gracefully.");
792 signal_threads(ST_GRACEFUL);
798 ap_close_listeners();
799 ap_queue_term(worker_queue);
801 ap_scoreboard_image->parent[process_slot].quiescing = 1;
803 /* wake up the main thread */
804 kill(ap_my_pid, SIGTERM);
806 apr_thread_exit(thd, APR_SUCCESS);
810 /* XXX For ungraceful termination/restart, we definitely don't want to
811 * wait for active connections to finish but we may want to wait
812 * for idle workers to get out of the queue code and release mutexes,
813 * since those mutexes are cleaned up pretty soon and some systems
814 * may not react favorably (i.e., segfault) if operations are attempted
815 * on cleaned-up mutexes.
817 static void * APR_THREAD_FUNC worker_thread(apr_thread_t *thd, void * dummy)
819 proc_info * ti = dummy;
820 int process_slot = ti->pid;
821 int thread_slot = ti->tid;
822 apr_socket_t *csd = NULL;
823 apr_bucket_alloc_t *bucket_alloc;
824 apr_pool_t *last_ptrans = NULL;
825 apr_pool_t *ptrans; /* Pool for per-transaction stuff */
831 ap_scoreboard_image->servers[process_slot][thread_slot].pid = ap_my_pid;
832 ap_scoreboard_image->servers[process_slot][thread_slot].tid = apr_os_thread_current();
833 ap_scoreboard_image->servers[process_slot][thread_slot].generation = ap_my_generation;
834 ap_update_child_status_from_indexes(process_slot, thread_slot, SERVER_STARTING, NULL);
836 #ifdef HAVE_PTHREAD_KILL
837 unblock_signal(WORKER_SIGNAL);
838 apr_signal(WORKER_SIGNAL, dummy_signal_handler);
841 while (!workers_may_exit) {
843 rv = ap_queue_info_set_idle(worker_queue_info, last_ptrans);
845 if (rv != APR_SUCCESS) {
846 ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
847 "ap_queue_info_set_idle failed. Attempting to "
848 "shutdown process gracefully.");
849 signal_threads(ST_GRACEFUL);
855 ap_update_child_status_from_indexes(process_slot, thread_slot, SERVER_READY, NULL);
857 if (workers_may_exit) {
860 rv = ap_queue_pop(worker_queue, &csd, &ptrans);
862 if (rv != APR_SUCCESS) {
863 /* We get APR_EOF during a graceful shutdown once all the connections
864 * accepted by this server process have been handled.
866 if (APR_STATUS_IS_EOF(rv)) {
869 /* We get APR_EINTR whenever ap_queue_pop() has been interrupted
870 * from an explicit call to ap_queue_interrupt_all(). This allows
871 * us to unblock threads stuck in ap_queue_pop() when a shutdown
874 * If workers_may_exit is set and this is ungraceful termination/
875 * restart, we are bound to get an error on some systems (e.g.,
876 * AIX, which sanity-checks mutex operations) since the queue
877 * may have already been cleaned up. Don't log the "error" if
878 * workers_may_exit is set.
880 else if (APR_STATUS_IS_EINTR(rv)) {
883 /* We got some other error. */
884 else if (!workers_may_exit) {
885 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
886 "ap_queue_pop failed");
891 worker_sockets[thread_slot] = csd;
892 bucket_alloc = apr_bucket_alloc_create(ptrans);
893 process_socket(ptrans, csd, process_slot, thread_slot, bucket_alloc);
894 worker_sockets[thread_slot] = NULL;
895 requests_this_child--;
896 apr_pool_clear(ptrans);
897 last_ptrans = ptrans;
900 ap_update_child_status_from_indexes(process_slot, thread_slot,
901 (dying) ? SERVER_DEAD : SERVER_GRACEFUL, (request_rec *) NULL);
903 apr_thread_exit(thd, APR_SUCCESS);
907 static int check_signal(int signum)
917 static void create_listener_thread(thread_starter *ts)
919 int my_child_num = ts->child_num_arg;
920 apr_threadattr_t *thread_attr = ts->threadattr;
924 my_info = (proc_info *)malloc(sizeof(proc_info));
925 my_info->pid = my_child_num;
926 my_info->tid = -1; /* listener thread doesn't have a thread slot */
928 rv = apr_thread_create(&ts->listener, thread_attr, listener_thread,
930 if (rv != APR_SUCCESS) {
931 ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
932 "apr_thread_create: unable to create listener thread");
933 /* let the parent decide how bad this really is */
934 clean_child_exit(APEXIT_CHILDSICK);
936 apr_os_thread_get(&listener_os_thread, ts->listener);
939 /* XXX under some circumstances not understood, children can get stuck
940 * in start_threads forever trying to take over slots which will
941 * never be cleaned up; for now there is an APLOG_DEBUG message issued
942 * every so often when this condition occurs
944 static void * APR_THREAD_FUNC start_threads(apr_thread_t *thd, void *dummy)
946 thread_starter *ts = dummy;
947 apr_thread_t **threads = ts->threads;
948 apr_threadattr_t *thread_attr = ts->threadattr;
949 int child_num_arg = ts->child_num_arg;
950 int my_child_num = child_num_arg;
954 int threads_created = 0;
955 int listener_started = 0;
957 int prev_threads_created;
959 /* We must create the fd queues before we start up the listener
960 * and worker threads. */
961 worker_queue = apr_pcalloc(pchild, sizeof(*worker_queue));
962 rv = ap_queue_init(worker_queue, ap_threads_per_child, pchild);
963 if (rv != APR_SUCCESS) {
964 ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
965 "ap_queue_init() failed");
966 clean_child_exit(APEXIT_CHILDFATAL);
969 rv = ap_queue_info_create(&worker_queue_info, pchild,
970 ap_threads_per_child);
971 if (rv != APR_SUCCESS) {
972 ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
973 "ap_queue_info_create() failed");
974 clean_child_exit(APEXIT_CHILDFATAL);
977 worker_sockets = apr_pcalloc(pchild, ap_threads_per_child
978 * sizeof(apr_socket_t *));
980 loops = prev_threads_created = 0;
982 /* ap_threads_per_child does not include the listener thread */
983 for (i = 0; i < ap_threads_per_child; i++) {
984 int status = ap_scoreboard_image->servers[child_num_arg][i].status;
986 if (status != SERVER_GRACEFUL && status != SERVER_DEAD) {
990 my_info = (proc_info *)malloc(sizeof(proc_info));
991 if (my_info == NULL) {
992 ap_log_error(APLOG_MARK, APLOG_ALERT, errno, ap_server_conf,
993 "malloc: out of memory");
994 clean_child_exit(APEXIT_CHILDFATAL);
996 my_info->pid = my_child_num;
1000 /* We are creating threads right now */
1001 ap_update_child_status_from_indexes(my_child_num, i,
1002 SERVER_STARTING, NULL);
1003 /* We let each thread update its own scoreboard entry. This is
1004 * done because it lets us deal with tid better.
1006 rv = apr_thread_create(&threads[i], thread_attr,
1007 worker_thread, my_info, pchild);
1008 if (rv != APR_SUCCESS) {
1009 ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
1010 "apr_thread_create: unable to create worker thread");
1011 /* let the parent decide how bad this really is */
1012 clean_child_exit(APEXIT_CHILDSICK);
1016 /* Start the listener only when there are workers available */
1017 if (!listener_started && threads_created) {
1018 create_listener_thread(ts);
1019 listener_started = 1;
1021 if (start_thread_may_exit || threads_created == ap_threads_per_child) {
1024 /* wait for previous generation to clean up an entry */
1025 apr_sleep(apr_time_from_sec(1));
1027 if (loops % 120 == 0) { /* every couple of minutes */
1028 if (prev_threads_created == threads_created) {
1029 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
1030 "child %" APR_PID_T_FMT " isn't taking over "
1031 "slots very quickly (%d of %d)",
1032 ap_my_pid, threads_created, ap_threads_per_child);
1034 prev_threads_created = threads_created;
1038 /* What state should this child_main process be listed as in the
1040 * ap_update_child_status_from_indexes(my_child_num, i, SERVER_STARTING,
1041 * (request_rec *) NULL);
1043 * This state should be listed separately in the scoreboard, in some kind
1044 * of process_status, not mixed in with the worker threads' status.
1045 * "life_status" is almost right, but it's in the worker's structure, and
1046 * the name could be clearer. gla
1048 apr_thread_exit(thd, APR_SUCCESS);
1052 static void join_workers(apr_thread_t *listener, apr_thread_t **threads)
1055 apr_status_t rv, thread_rv;
1060 /* deal with a rare timing window which affects waking up the
1061 * listener thread... if the signal sent to the listener thread
1062 * is delivered between the time it verifies that the
1063 * listener_may_exit flag is clear and the time it enters a
1064 * blocking syscall, the signal didn't do any good... work around
1065 * that by sleeping briefly and sending it again
1070 #ifdef HAVE_PTHREAD_KILL
1071 pthread_kill(*listener_os_thread, 0)
1076 /* listener not dead yet */
1077 apr_sleep(apr_time_make(0, 500000));
1082 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
1083 "the listener thread didn't exit");
1086 rv = apr_thread_join(&thread_rv, listener);
1087 if (rv != APR_SUCCESS) {
1088 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
1089 "apr_thread_join: unable to join listener thread");
1094 for (i = 0; i < ap_threads_per_child; i++) {
1095 if (threads[i]) { /* if we ever created this thread */
1096 #ifdef HAVE_PTHREAD_KILL
1097 apr_os_thread_t *worker_os_thread;
1099 apr_os_thread_get(&worker_os_thread, threads[i]);
1100 pthread_kill(*worker_os_thread, WORKER_SIGNAL);
1103 rv = apr_thread_join(&thread_rv, threads[i]);
1104 if (rv != APR_SUCCESS) {
1105 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
1106 "apr_thread_join: unable to join worker "
1114 static void join_start_thread(apr_thread_t *start_thread_id)
1116 apr_status_t rv, thread_rv;
1118 start_thread_may_exit = 1; /* tell it to give up in case it is still
1119 * trying to take over slots from a
1120 * previous generation
1122 rv = apr_thread_join(&thread_rv, start_thread_id);
1123 if (rv != APR_SUCCESS) {
1124 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
1125 "apr_thread_join: unable to join the start "
1130 static void child_main(int child_num_arg)
1132 apr_thread_t **threads;
1135 apr_threadattr_t *thread_attr;
1136 apr_thread_t *start_thread_id;
1138 mpm_state = AP_MPMQ_STARTING; /* for benefit of any hooks that run as this
1141 ap_my_pid = getpid();
1142 ap_fatal_signal_child_setup(ap_server_conf);
1143 apr_pool_create(&pchild, pconf);
1145 /*stuff to do before we switch id's, so we have permissions.*/
1146 ap_reopen_scoreboard(pchild, NULL, 0);
1148 rv = SAFE_ACCEPT(apr_proc_mutex_child_init(&accept_mutex, ap_lock_fname,
1150 if (rv != APR_SUCCESS) {
1151 ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
1152 "Couldn't initialize cross-process lock in child");
1153 clean_child_exit(APEXIT_CHILDFATAL);
1156 if (unixd_setup_child()) {
1157 clean_child_exit(APEXIT_CHILDFATAL);
1160 ap_run_child_init(pchild, ap_server_conf);
1162 /* done with init critical section */
1164 /* Just use the standard apr_setup_signal_thread to block all signals
1165 * from being received. The child processes no longer use signals for
1166 * any communication with the parent process.
1168 rv = apr_setup_signal_thread();
1169 if (rv != APR_SUCCESS) {
1170 ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
1171 "Couldn't initialize signal thread");
1172 clean_child_exit(APEXIT_CHILDFATAL);
1175 if (ap_max_requests_per_child) {
1176 requests_this_child = ap_max_requests_per_child;
1179 /* coding a value of zero means infinity */
1180 requests_this_child = INT_MAX;
1183 /* Setup worker threads */
1185 /* clear the storage; we may not create all our threads immediately,
1186 * and we want a 0 entry to indicate a thread which was not created
1188 threads = (apr_thread_t **)calloc(1,
1189 sizeof(apr_thread_t *) * ap_threads_per_child);
1190 if (threads == NULL) {
1191 ap_log_error(APLOG_MARK, APLOG_ALERT, errno, ap_server_conf,
1192 "malloc: out of memory");
1193 clean_child_exit(APEXIT_CHILDFATAL);
1196 ts = (thread_starter *)apr_palloc(pchild, sizeof(*ts));
1198 apr_threadattr_create(&thread_attr, pchild);
1199 /* 0 means PTHREAD_CREATE_JOINABLE */
1200 apr_threadattr_detach_set(thread_attr, 0);
1202 if (ap_thread_stacksize != 0) {
1203 apr_threadattr_stacksize_set(thread_attr, ap_thread_stacksize);
1206 ts->threads = threads;
1207 ts->listener = NULL;
1208 ts->child_num_arg = child_num_arg;
1209 ts->threadattr = thread_attr;
1211 rv = apr_thread_create(&start_thread_id, thread_attr, start_threads,
1213 if (rv != APR_SUCCESS) {
1214 ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
1215 "apr_thread_create: unable to create worker thread");
1216 /* let the parent decide how bad this really is */
1217 clean_child_exit(APEXIT_CHILDSICK);
1220 mpm_state = AP_MPMQ_RUNNING;
1222 /* If we are only running in one_process mode, we will want to
1223 * still handle signals. */
1225 /* Block until we get a terminating signal. */
1226 apr_signal_thread(check_signal);
1227 /* make sure the start thread has finished; signal_threads()
1228 * and join_workers() depend on that
1230 /* XXX join_start_thread() won't be awakened if one of our
1231 * threads encounters a critical error and attempts to
1232 * shutdown this child
1234 join_start_thread(start_thread_id);
1235 signal_threads(ST_UNGRACEFUL); /* helps us terminate a little more
1236 * quickly than the dispatch of the signal thread
1237 * beats the Pipe of Death and the browsers
1239 /* A terminating signal was received. Now join each of the
1240 * workers to clean them up.
1241 * If the worker already exited, then the join frees
1242 * their resources and returns.
1243 * If the worker hasn't exited, then this blocks until
1244 * they have (then cleans up).
1246 join_workers(ts->listener, threads);
1248 else { /* !one_process */
1249 /* remove SIGTERM from the set of blocked signals... if one of
1250 * the other threads in the process needs to take us down
1251 * (e.g., for MaxRequestsPerChild) it will send us SIGTERM
1253 unblock_signal(SIGTERM);
1254 apr_signal(SIGTERM, dummy_signal_handler);
1255 /* Watch for any messages from the parent over the POD */
1257 rv = ap_mpm_pod_check(pod);
1258 if (rv == AP_NORESTART) {
1259 /* see if termination was triggered while we slept */
1260 switch(terminate_mode) {
1269 if (rv == AP_GRACEFUL || rv == AP_RESTART) {
1270 /* make sure the start thread has finished;
1271 * signal_threads() and join_workers depend on that
1273 join_start_thread(start_thread_id);
1274 signal_threads(rv == AP_GRACEFUL ? ST_GRACEFUL : ST_UNGRACEFUL);
1279 /* A terminating signal was received. Now join each of the
1280 * workers to clean them up.
1281 * If the worker already exited, then the join frees
1282 * their resources and returns.
1283 * If the worker hasn't exited, then this blocks until
1284 * they have (then cleans up).
1286 join_workers(ts->listener, threads);
1291 clean_child_exit(resource_shortage ? APEXIT_CHILDSICK : 0);
1294 static int make_child(server_rec *s, int slot)
1298 if (slot + 1 > ap_max_daemons_limit) {
1299 ap_max_daemons_limit = slot + 1;
1304 ap_scoreboard_image->parent[slot].pid = getpid();
1308 if ((pid = fork()) == -1) {
1309 ap_log_error(APLOG_MARK, APLOG_ERR, errno, s,
1310 "fork: Unable to fork new process");
1311 /* fork didn't succeed. There's no need to touch the scoreboard;
1312 * if we were trying to replace a failed child process, then
1313 * server_main_loop() marked its workers SERVER_DEAD, and if
1314 * we were trying to replace a child process that exited normally,
1315 * its worker_thread()s left SERVER_DEAD or SERVER_GRACEFUL behind.
1318 /* In case system resources are maxxed out, we don't want
1319 Apache running away with the CPU trying to fork over and
1320 over and over again. */
1321 apr_sleep(apr_time_from_sec(10));
1327 #ifdef HAVE_BINDPROCESSOR
1328 /* By default, AIX binds to a single processor. This bit unbinds
1329 * children which will then bind to another CPU.
1331 int status = bindprocessor(BINDPROCESS, (int)getpid(),
1332 PROCESSOR_CLASS_ANY);
1334 ap_log_error(APLOG_MARK, APLOG_WARNING, errno,
1336 "processor unbind failed %d", status);
1338 RAISE_SIGSTOP(MAKE_CHILD);
1340 apr_signal(SIGTERM, just_die);
1343 clean_child_exit(0);
1346 if (ap_scoreboard_image->parent[slot].pid != 0) {
1347 /* This new child process is squatting on the scoreboard
1348 * entry owned by an exiting child process, which cannot
1349 * exit until all active requests complete.
1350 * Don't forget about this exiting child process, or we
1351 * won't be able to kill it if it doesn't exit by the
1352 * time the server is shut down.
1354 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
1355 "taking over scoreboard slot from %" APR_PID_T_FMT "%s",
1356 ap_scoreboard_image->parent[slot].pid,
1357 ap_scoreboard_image->parent[slot].quiescing ?
1358 " (quiescing)" : "");
1359 ap_register_extra_mpm_process(ap_scoreboard_image->parent[slot].pid);
1361 ap_scoreboard_image->parent[slot].quiescing = 0;
1362 ap_scoreboard_image->parent[slot].pid = pid;
1366 /* start up a bunch of children */
1367 static void startup_children(int number_to_start)
1371 for (i = 0; number_to_start && i < ap_daemons_limit; ++i) {
1372 if (ap_scoreboard_image->parent[i].pid != 0) {
1375 if (make_child(ap_server_conf, i) < 0) {
1384 * idle_spawn_rate is the number of children that will be spawned on the
1385 * next maintenance cycle if there aren't enough idle servers. It is
1386 * doubled up to MAX_SPAWN_RATE, and reset only when a cycle goes by
1387 * without the need to spawn.
1389 static int idle_spawn_rate = 1;
1390 #ifndef MAX_SPAWN_RATE
1391 #define MAX_SPAWN_RATE (32)
1393 static int hold_off_on_exponential_spawning;
1395 static void perform_idle_server_maintenance(void)
1398 int idle_thread_count;
1402 int totally_free_length = 0;
1403 int free_slots[MAX_SPAWN_RATE];
1406 int active_thread_count = 0;
1408 /* initialize the free_list */
1411 idle_thread_count = 0;
1415 for (i = 0; i < ap_daemons_limit; ++i) {
1416 /* Initialization to satisfy the compiler. It doesn't know
1417 * that ap_threads_per_child is always > 0 */
1418 int status = SERVER_DEAD;
1419 int any_dying_threads = 0;
1420 int any_dead_threads = 0;
1421 int all_dead_threads = 1;
1423 if (i >= ap_max_daemons_limit && totally_free_length == idle_spawn_rate)
1424 /* short cut if all active processes have been examined and
1425 * enough empty scoreboard slots have been found
1428 ps = &ap_scoreboard_image->parent[i];
1429 for (j = 0; j < ap_threads_per_child; j++) {
1430 ws = &ap_scoreboard_image->servers[i][j];
1431 status = ws->status;
1433 /* XXX any_dying_threads is probably no longer needed GLA */
1434 any_dying_threads = any_dying_threads ||
1435 (status == SERVER_GRACEFUL);
1436 any_dead_threads = any_dead_threads || (status == SERVER_DEAD);
1437 all_dead_threads = all_dead_threads &&
1438 (status == SERVER_DEAD ||
1439 status == SERVER_GRACEFUL);
1441 /* We consider a starting server as idle because we started it
1442 * at least a cycle ago, and if it still hasn't finished starting
1443 * then we're just going to swamp things worse by forking more.
1444 * So we hopefully won't need to fork more if we count it.
1445 * This depends on the ordering of SERVER_READY and SERVER_STARTING.
1447 if (ps->pid != 0) { /* XXX just set all_dead_threads in outer for
1448 loop if no pid? not much else matters */
1449 if (status <= SERVER_READY &&
1451 ps->generation == ap_my_generation) {
1452 ++idle_thread_count;
1454 if (status >= SERVER_READY && status < SERVER_GRACEFUL) {
1455 ++active_thread_count;
1459 if (any_dead_threads && totally_free_length < idle_spawn_rate
1460 && free_length < MAX_SPAWN_RATE
1461 && (!ps->pid /* no process in the slot */
1462 || ps->quiescing)) { /* or at least one is going away */
1463 if (all_dead_threads) {
1464 /* great! we prefer these, because the new process can
1465 * start more threads sooner. So prioritize this slot
1466 * by putting it ahead of any slots with active threads.
1468 * first, make room by moving a slot that's potentially still
1469 * in use to the end of the array
1471 free_slots[free_length] = free_slots[totally_free_length];
1472 free_slots[totally_free_length++] = i;
1475 /* slot is still in use - back of the bus
1477 free_slots[free_length] = i;
1481 /* XXX if (!ps->quiescing) is probably more reliable GLA */
1482 if (!any_dying_threads) {
1488 if (sick_child_detected) {
1489 if (active_thread_count > 0) {
1490 /* some child processes appear to be working. don't kill the
1493 sick_child_detected = 0;
1496 /* looks like a basket case. give up.
1498 shutdown_pending = 1;
1500 ap_log_error(APLOG_MARK, APLOG_ALERT, 0,
1502 "No active workers found..."
1503 " Apache is exiting!");
1504 /* the child already logged the failure details */
1509 ap_max_daemons_limit = last_non_dead + 1;
1511 if (idle_thread_count > max_spare_threads) {
1512 /* Kill off one child */
1513 ap_mpm_pod_signal(pod, TRUE);
1514 idle_spawn_rate = 1;
1516 else if (idle_thread_count < min_spare_threads) {
1517 /* terminate the free list */
1518 if (free_length == 0) { /* scoreboard is full, can't fork */
1520 if (active_thread_count >= ap_daemons_limit * ap_threads_per_child) {
1521 static int reported = 0;
1523 /* only report this condition once */
1524 ap_log_error(APLOG_MARK, APLOG_ERR, 0,
1526 "server reached MaxClients setting, consider"
1527 " raising the MaxClients setting");
1532 ap_log_error(APLOG_MARK, APLOG_ERR, 0,
1534 "scoreboard is full, not at MaxClients");
1536 idle_spawn_rate = 1;
1539 if (free_length > idle_spawn_rate) {
1540 free_length = idle_spawn_rate;
1542 if (idle_spawn_rate >= 8) {
1543 ap_log_error(APLOG_MARK, APLOG_INFO, 0,
1545 "server seems busy, (you may need "
1546 "to increase StartServers, ThreadsPerChild "
1547 "or Min/MaxSpareThreads), "
1548 "spawning %d children, there are around %d idle "
1549 "threads, and %d total children", free_length,
1550 idle_thread_count, total_non_dead);
1552 for (i = 0; i < free_length; ++i) {
1553 make_child(ap_server_conf, free_slots[i]);
1555 /* the next time around we want to spawn twice as many if this
1556 * wasn't good enough, but not if we've just done a graceful
1558 if (hold_off_on_exponential_spawning) {
1559 --hold_off_on_exponential_spawning;
1561 else if (idle_spawn_rate < MAX_SPAWN_RATE) {
1562 idle_spawn_rate *= 2;
1567 idle_spawn_rate = 1;
1571 static void server_main_loop(int remaining_children_to_start)
1574 apr_exit_why_e exitwhy;
1575 int status, processed_status;
1579 while (!restart_pending && !shutdown_pending) {
1580 ap_wait_or_timeout(&exitwhy, &status, &pid, pconf);
1582 if (pid.pid != -1) {
1583 processed_status = ap_process_child_status(&pid, exitwhy, status);
1584 if (processed_status == APEXIT_CHILDFATAL) {
1585 shutdown_pending = 1;
1589 else if (processed_status == APEXIT_CHILDSICK) {
1590 /* tell perform_idle_server_maintenance to check into this
1591 * on the next timer pop
1593 sick_child_detected = 1;
1595 /* non-fatal death... note that it's gone in the scoreboard. */
1596 child_slot = find_child_by_pid(&pid);
1597 if (child_slot >= 0) {
1598 for (i = 0; i < ap_threads_per_child; i++)
1599 ap_update_child_status_from_indexes(child_slot, i, SERVER_DEAD,
1600 (request_rec *) NULL);
1602 ap_scoreboard_image->parent[child_slot].pid = 0;
1603 ap_scoreboard_image->parent[child_slot].quiescing = 0;
1604 if (processed_status == APEXIT_CHILDSICK) {
1605 /* resource shortage, minimize the fork rate */
1606 idle_spawn_rate = 1;
1608 else if (remaining_children_to_start
1609 && child_slot < ap_daemons_limit) {
1610 /* we're still doing a 1-for-1 replacement of dead
1611 * children with new children
1613 make_child(ap_server_conf, child_slot);
1614 --remaining_children_to_start;
1617 else if (ap_unregister_extra_mpm_process(pid.pid) == 1) {
1619 #if APR_HAS_OTHER_CHILD
1621 else if (apr_proc_other_child_alert(&pid, APR_OC_REASON_DEATH,
1626 else if (is_graceful) {
1627 /* Great, we've probably just lost a slot in the
1628 * scoreboard. Somehow we don't know about this child.
1630 ap_log_error(APLOG_MARK, APLOG_WARNING, 0,
1632 "long lost child came home! (pid %ld)",
1635 /* Don't perform idle maintenance when a child dies,
1636 * only do it when there's a timeout. Remember only a
1637 * finite number of children can die, and it's pretty
1638 * pathological for a lot to die suddenly.
1642 else if (remaining_children_to_start) {
1643 /* we hit a 1 second timeout in which none of the previous
1644 * generation of children needed to be reaped... so assume
1645 * they're all done, and pick up the slack if any is left.
1647 startup_children(remaining_children_to_start);
1648 remaining_children_to_start = 0;
1649 /* In any event we really shouldn't do the code below because
1650 * few of the servers we just started are in the IDLE state
1651 * yet, so we'd mistakenly create an extra server.
1656 perform_idle_server_maintenance();
1660 int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
1662 int remaining_children_to_start;
1665 ap_log_pid(pconf, ap_pid_fname);
1667 /* Initialize cross-process accept lock */
1668 ap_lock_fname = apr_psprintf(_pconf, "%s.%" APR_PID_T_FMT,
1669 ap_server_root_relative(_pconf, ap_lock_fname),
1672 rv = apr_proc_mutex_create(&accept_mutex, ap_lock_fname,
1673 ap_accept_lock_mech, _pconf);
1674 if (rv != APR_SUCCESS) {
1675 ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s,
1676 "Couldn't create accept lock");
1677 mpm_state = AP_MPMQ_STOPPING;
1681 #if APR_USE_SYSVSEM_SERIALIZE
1682 if (ap_accept_lock_mech == APR_LOCK_DEFAULT ||
1683 ap_accept_lock_mech == APR_LOCK_SYSVSEM) {
1685 if (ap_accept_lock_mech == APR_LOCK_SYSVSEM) {
1687 rv = unixd_set_proc_mutex_perms(accept_mutex);
1688 if (rv != APR_SUCCESS) {
1689 ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s,
1690 "Couldn't set permissions on cross-process lock; "
1691 "check User and Group directives");
1692 mpm_state = AP_MPMQ_STOPPING;
1698 if (ap_run_pre_mpm(s->process->pool, SB_SHARED) != OK) {
1699 mpm_state = AP_MPMQ_STOPPING;
1702 /* fix the generation number in the global score; we just got a new,
1703 * cleared scoreboard
1705 ap_scoreboard_image->global->running_generation = ap_my_generation;
1709 /* Don't thrash... */
1710 if (max_spare_threads < min_spare_threads + ap_threads_per_child)
1711 max_spare_threads = min_spare_threads + ap_threads_per_child;
1713 /* If we're doing a graceful_restart then we're going to see a lot
1714 * of children exiting immediately when we get into the main loop
1715 * below (because we just sent them AP_SIG_GRACEFUL). This happens pretty
1716 * rapidly... and for each one that exits we may start a new one, until
1717 * there are at least min_spare_threads idle threads, counting across
1718 * all children. But we may be permitted to start more children than
1719 * that, so we'll just keep track of how many we're
1720 * supposed to start up without the 1 second penalty between each fork.
1722 remaining_children_to_start = ap_daemons_to_start;
1723 if (remaining_children_to_start > ap_daemons_limit) {
1724 remaining_children_to_start = ap_daemons_limit;
1727 startup_children(remaining_children_to_start);
1728 remaining_children_to_start = 0;
1731 /* give the system some time to recover before kicking into
1732 * exponential mode */
1733 hold_off_on_exponential_spawning = 10;
1736 ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
1737 "%s configured -- resuming normal operations",
1738 ap_get_server_description());
1739 ap_log_error(APLOG_MARK, APLOG_INFO, 0, ap_server_conf,
1740 "Server built: %s", ap_get_server_built());
1741 #ifdef AP_MPM_WANT_SET_ACCEPT_LOCK_MECH
1742 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
1743 "AcceptMutex: %s (default: %s)",
1744 apr_proc_mutex_name(accept_mutex),
1745 apr_proc_mutex_defname());
1747 restart_pending = shutdown_pending = 0;
1748 mpm_state = AP_MPMQ_RUNNING;
1750 server_main_loop(remaining_children_to_start);
1751 mpm_state = AP_MPMQ_STOPPING;
1753 if (shutdown_pending && !is_graceful) {
1754 /* Time to shut down:
1755 * Kill child processes, tell them to call child_exit, etc...
1757 ap_mpm_pod_killpg(pod, ap_daemons_limit, FALSE);
1758 ap_reclaim_child_processes(1); /* Start with SIGTERM */
1761 /* cleanup pid file on normal shutdown */
1762 const char *pidfile = NULL;
1763 pidfile = ap_server_root_relative (pconf, ap_pid_fname);
1764 if ( pidfile != NULL && unlink(pidfile) == 0)
1765 ap_log_error(APLOG_MARK, APLOG_INFO, 0,
1767 "removed PID file %s (pid=%" APR_PID_T_FMT ")",
1770 ap_log_error(APLOG_MARK, APLOG_NOTICE, 0,
1771 ap_server_conf, "caught SIGTERM, shutting down");
1774 } else if (shutdown_pending) {
1775 /* Time to gracefully shut down:
1776 * Kill child processes, tell them to call child_exit, etc...
1778 int active_children;
1780 apr_time_t cutoff = 0;
1782 /* Close our listeners, and then ask our children to do same */
1783 ap_close_listeners();
1784 ap_mpm_pod_killpg(pod, ap_daemons_limit, TRUE);
1785 ap_relieve_child_processes();
1788 /* cleanup pid file on normal shutdown */
1789 const char *pidfile = NULL;
1790 pidfile = ap_server_root_relative (pconf, ap_pid_fname);
1791 if ( pidfile != NULL && unlink(pidfile) == 0)
1792 ap_log_error(APLOG_MARK, APLOG_INFO, 0,
1794 "removed PID file %s (pid=%" APR_PID_T_FMT ")",
1797 ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
1798 "caught " AP_SIG_GRACEFUL_STOP_STRING
1799 ", shutting down gracefully");
1802 if (ap_graceful_shutdown_timeout) {
1803 cutoff = apr_time_now() +
1804 apr_time_from_sec(ap_graceful_shutdown_timeout);
1807 /* Don't really exit until each child has finished */
1808 shutdown_pending = 0;
1810 /* Pause for a second */
1811 apr_sleep(apr_time_from_sec(1));
1813 /* Relieve any children which have now exited */
1814 ap_relieve_child_processes();
1816 active_children = 0;
1817 for (index = 0; index < ap_daemons_limit; ++index) {
1818 if (ap_mpm_safe_kill(MPM_CHILD_PID(index), 0) == APR_SUCCESS) {
1819 active_children = 1;
1820 /* Having just one child is enough to stay around */
1824 } while (!shutdown_pending && active_children &&
1825 (!ap_graceful_shutdown_timeout || apr_time_now() < cutoff));
1827 /* We might be here because we received SIGTERM, either
1828 * way, try and make sure that all of our processes are
1831 ap_mpm_pod_killpg(pod, ap_daemons_limit, FALSE);
1832 ap_reclaim_child_processes(1);
1837 /* we've been told to restart */
1838 apr_signal(SIGHUP, SIG_IGN);
1841 /* not worth thinking about */
1845 /* advance to the next generation */
1846 /* XXX: we really need to make sure this new generation number isn't in
1847 * use by any of the children.
1850 ap_scoreboard_image->global->running_generation = ap_my_generation;
1853 ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
1854 AP_SIG_GRACEFUL_STRING " received. Doing graceful restart");
1855 /* wake up the children...time to die. But we'll have more soon */
1856 ap_mpm_pod_killpg(pod, ap_daemons_limit, TRUE);
1859 /* This is mostly for debugging... so that we know what is still
1860 * gracefully dealing with existing request.
1865 /* Kill 'em all. Since the child acts the same on the parents SIGTERM
1866 * and a SIGHUP, we may as well use the same signal, because some user
1867 * pthreads are stealing signals from us left and right.
1869 ap_mpm_pod_killpg(pod, ap_daemons_limit, FALSE);
1871 ap_reclaim_child_processes(1); /* Start with SIGTERM */
1872 ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
1873 "SIGHUP received. Attempting to restart");
1879 /* This really should be a post_config hook, but the error log is already
1880 * redirected by that point, so we need to do this in the open_logs phase.
1882 static int worker_open_logs(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
1884 static int restart_num = 0;
1886 int level_flags = 0;
1892 /* the reverse of pre_config, we want this only the first time around */
1893 if (restart_num++ == 0) {
1895 level_flags |= APLOG_STARTUP;
1898 if ((num_listensocks = ap_setup_listeners(ap_server_conf)) < 1) {
1899 ap_log_error(APLOG_MARK, APLOG_ALERT | level_flags, 0,
1900 (startup ? NULL : s),
1901 "no listening sockets available, shutting down");
1906 if ((rv = ap_mpm_pod_open(pconf, &pod))) {
1907 ap_log_error(APLOG_MARK, APLOG_CRIT | level_flags, rv,
1908 (startup ? NULL : s),
1909 "could not open pipe-of-death");
1916 static int worker_pre_config(apr_pool_t *pconf, apr_pool_t *plog,
1919 static int restart_num = 0;
1920 int no_detach, debug, foreground;
1923 mpm_state = AP_MPMQ_STARTING;
1925 debug = ap_exists_config_define("DEBUG");
1928 foreground = one_process = 1;
1932 one_process = ap_exists_config_define("ONE_PROCESS");
1933 no_detach = ap_exists_config_define("NO_DETACH");
1934 foreground = ap_exists_config_define("FOREGROUND");
1937 /* sigh, want this only the second time around */
1938 if (restart_num++ == 1) {
1941 if (!one_process && !foreground) {
1942 rv = apr_proc_detach(no_detach ? APR_PROC_DETACH_FOREGROUND
1943 : APR_PROC_DETACH_DAEMONIZE);
1944 if (rv != APR_SUCCESS) {
1945 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL,
1946 "apr_proc_detach failed");
1947 return HTTP_INTERNAL_SERVER_ERROR;
1950 parent_pid = ap_my_pid = getpid();
1953 unixd_pre_config(ptemp);
1954 ap_listen_pre_config();
1955 ap_daemons_to_start = DEFAULT_START_DAEMON;
1956 min_spare_threads = DEFAULT_MIN_FREE_DAEMON * DEFAULT_THREADS_PER_CHILD;
1957 max_spare_threads = DEFAULT_MAX_FREE_DAEMON * DEFAULT_THREADS_PER_CHILD;
1958 server_limit = DEFAULT_SERVER_LIMIT;
1959 thread_limit = DEFAULT_THREAD_LIMIT;
1960 ap_daemons_limit = server_limit;
1961 ap_threads_per_child = DEFAULT_THREADS_PER_CHILD;
1962 max_clients = ap_daemons_limit * ap_threads_per_child;
1963 ap_pid_fname = DEFAULT_PIDLOG;
1964 ap_lock_fname = DEFAULT_LOCKFILE;
1965 ap_max_requests_per_child = DEFAULT_MAX_REQUESTS_PER_CHILD;
1966 ap_extended_status = 0;
1967 #ifdef AP_MPM_WANT_SET_MAX_MEM_FREE
1968 ap_max_mem_free = APR_ALLOCATOR_MAX_FREE_UNLIMITED;
1971 apr_cpystrn(ap_coredump_dir, ap_server_root, sizeof(ap_coredump_dir));
1976 static int worker_check_config(apr_pool_t *p, apr_pool_t *plog,
1977 apr_pool_t *ptemp, server_rec *s)
1979 static int restart_num = 0;
1982 /* the reverse of pre_config, we want this only the first time around */
1983 if (restart_num++ == 0) {
1987 if (server_limit > MAX_SERVER_LIMIT) {
1989 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
1990 "WARNING: ServerLimit of %d exceeds compile-time "
1991 "limit of", server_limit);
1992 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
1993 " %d servers, decreasing to %d.",
1994 MAX_SERVER_LIMIT, MAX_SERVER_LIMIT);
1996 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
1997 "ServerLimit of %d exceeds compile-time limit "
1998 "of %d, decreasing to match",
1999 server_limit, MAX_SERVER_LIMIT);
2001 server_limit = MAX_SERVER_LIMIT;
2003 else if (server_limit < 1) {
2005 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2006 "WARNING: ServerLimit of %d not allowed, "
2007 "increasing to 1.", server_limit);
2009 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
2010 "ServerLimit of %d not allowed, increasing to 1",
2016 /* you cannot change ServerLimit across a restart; ignore
2019 if (!first_server_limit) {
2020 first_server_limit = server_limit;
2022 else if (server_limit != first_server_limit) {
2023 /* don't need a startup console version here */
2024 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
2025 "changing ServerLimit to %d from original value of %d "
2026 "not allowed during restart",
2027 server_limit, first_server_limit);
2028 server_limit = first_server_limit;
2031 if (thread_limit > MAX_THREAD_LIMIT) {
2033 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2034 "WARNING: ThreadLimit of %d exceeds compile-time "
2035 "limit of", thread_limit);
2036 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2037 " %d threads, decreasing to %d.",
2038 MAX_THREAD_LIMIT, MAX_THREAD_LIMIT);
2040 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
2041 "ThreadLimit of %d exceeds compile-time limit "
2042 "of %d, decreasing to match",
2043 thread_limit, MAX_THREAD_LIMIT);
2045 thread_limit = MAX_THREAD_LIMIT;
2047 else if (thread_limit < 1) {
2049 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2050 "WARNING: ThreadLimit of %d not allowed, "
2051 "increasing to 1.", thread_limit);
2053 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
2054 "ThreadLimit of %d not allowed, increasing to 1",
2060 /* you cannot change ThreadLimit across a restart; ignore
2063 if (!first_thread_limit) {
2064 first_thread_limit = thread_limit;
2066 else if (thread_limit != first_thread_limit) {
2067 /* don't need a startup console version here */
2068 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
2069 "changing ThreadLimit to %d from original value of %d "
2070 "not allowed during restart",
2071 thread_limit, first_thread_limit);
2072 thread_limit = first_thread_limit;
2075 if (ap_threads_per_child > thread_limit) {
2077 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2078 "WARNING: ThreadsPerChild of %d exceeds ThreadLimit "
2079 "of", ap_threads_per_child);
2080 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2081 " %d threads, decreasing to %d.",
2082 thread_limit, thread_limit);
2083 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2084 " To increase, please see the ThreadLimit "
2087 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
2088 "ThreadsPerChild of %d exceeds ThreadLimit "
2089 "of %d, decreasing to match",
2090 ap_threads_per_child, thread_limit);
2092 ap_threads_per_child = thread_limit;
2094 else if (ap_threads_per_child < 1) {
2096 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2097 "WARNING: ThreadsPerChild of %d not allowed, "
2098 "increasing to 1.", ap_threads_per_child);
2100 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
2101 "ThreadsPerChild of %d not allowed, increasing to 1",
2102 ap_threads_per_child);
2104 ap_threads_per_child = 1;
2107 if (max_clients < ap_threads_per_child) {
2109 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2110 "WARNING: MaxClients of %d is less than "
2111 "ThreadsPerChild of", max_clients);
2112 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2113 " %d, increasing to %d. MaxClients must be at "
2115 ap_threads_per_child, ap_threads_per_child);
2116 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2117 " as the number of threads in a single server.");
2119 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
2120 "MaxClients of %d is less than ThreadsPerChild "
2121 "of %d, increasing to match",
2122 max_clients, ap_threads_per_child);
2124 max_clients = ap_threads_per_child;
2127 ap_daemons_limit = max_clients / ap_threads_per_child;
2129 if (max_clients % ap_threads_per_child) {
2130 int tmp_max_clients = ap_daemons_limit * ap_threads_per_child;
2133 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2134 "WARNING: MaxClients of %d is not an integer "
2135 "multiple of", max_clients);
2136 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2137 " ThreadsPerChild of %d, decreasing to nearest "
2138 "multiple %d,", ap_threads_per_child,
2140 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2141 " for a maximum of %d servers.",
2144 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
2145 "MaxClients of %d is not an integer multiple of "
2146 "ThreadsPerChild of %d, decreasing to nearest "
2147 "multiple %d", max_clients, ap_threads_per_child,
2150 max_clients = tmp_max_clients;
2153 if (ap_daemons_limit > server_limit) {
2155 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2156 "WARNING: MaxClients of %d would require %d "
2157 "servers and ", max_clients, ap_daemons_limit);
2158 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2159 " would exceed ServerLimit of %d, decreasing to %d.",
2160 server_limit, server_limit * ap_threads_per_child);
2161 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2162 " To increase, please see the ServerLimit "
2165 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
2166 "MaxClients of %d would require %d servers and "
2167 "exceed ServerLimit of %d, decreasing to %d",
2168 max_clients, ap_daemons_limit, server_limit,
2169 server_limit * ap_threads_per_child);
2171 ap_daemons_limit = server_limit;
2174 /* ap_daemons_to_start > ap_daemons_limit checked in ap_mpm_run() */
2175 if (ap_daemons_to_start < 0) {
2177 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2178 "WARNING: StartServers of %d not allowed, "
2179 "increasing to 1.", ap_daemons_to_start);
2181 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
2182 "StartServers of %d not allowed, increasing to 1",
2183 ap_daemons_to_start);
2185 ap_daemons_to_start = 1;
2188 if (min_spare_threads < 1) {
2190 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2191 "WARNING: MinSpareThreads of %d not allowed, "
2192 "increasing to 1", min_spare_threads);
2193 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2194 " to avoid almost certain server failure.");
2195 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2196 " Please read the documentation.");
2198 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
2199 "MinSpareThreads of %d not allowed, increasing to 1",
2202 min_spare_threads = 1;
2205 /* max_spare_threads < min_spare_threads + ap_threads_per_child
2206 * checked in ap_mpm_run()
2212 static void worker_hooks(apr_pool_t *p)
2214 /* Our open_logs hook function must run before the core's, or stderr
2215 * will be redirected to a file, and the messages won't print to the
2218 static const char *const aszSucc[] = {"core.c", NULL};
2221 ap_hook_open_logs(worker_open_logs, NULL, aszSucc, APR_HOOK_REALLY_FIRST);
2222 /* we need to set the MPM state before other pre-config hooks use MPM query
2223 * to retrieve it, so register as REALLY_FIRST
2225 ap_hook_pre_config(worker_pre_config, NULL, NULL, APR_HOOK_REALLY_FIRST);
2226 ap_hook_check_config(worker_check_config, NULL, NULL, APR_HOOK_MIDDLE);
2229 static const char *set_daemons_to_start(cmd_parms *cmd, void *dummy,
2232 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
2237 ap_daemons_to_start = atoi(arg);
2241 static const char *set_min_spare_threads(cmd_parms *cmd, void *dummy,
2244 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
2249 min_spare_threads = atoi(arg);
2253 static const char *set_max_spare_threads(cmd_parms *cmd, void *dummy,
2256 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
2261 max_spare_threads = atoi(arg);
2265 static const char *set_max_clients (cmd_parms *cmd, void *dummy,
2268 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
2273 max_clients = atoi(arg);
2277 static const char *set_threads_per_child (cmd_parms *cmd, void *dummy,
2280 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
2285 ap_threads_per_child = atoi(arg);
2289 static const char *set_server_limit (cmd_parms *cmd, void *dummy, const char *arg)
2291 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
2296 server_limit = atoi(arg);
2300 static const char *set_thread_limit (cmd_parms *cmd, void *dummy, const char *arg)
2302 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
2307 thread_limit = atoi(arg);
2311 static const command_rec worker_cmds[] = {
2312 UNIX_DAEMON_COMMANDS,
2314 AP_INIT_TAKE1("StartServers", set_daemons_to_start, NULL, RSRC_CONF,
2315 "Number of child processes launched at server startup"),
2316 AP_INIT_TAKE1("MinSpareThreads", set_min_spare_threads, NULL, RSRC_CONF,
2317 "Minimum number of idle threads, to handle request spikes"),
2318 AP_INIT_TAKE1("MaxSpareThreads", set_max_spare_threads, NULL, RSRC_CONF,
2319 "Maximum number of idle threads"),
2320 AP_INIT_TAKE1("MaxClients", set_max_clients, NULL, RSRC_CONF,
2321 "Maximum number of threads alive at the same time"),
2322 AP_INIT_TAKE1("ThreadsPerChild", set_threads_per_child, NULL, RSRC_CONF,
2323 "Number of threads each child creates"),
2324 AP_INIT_TAKE1("ServerLimit", set_server_limit, NULL, RSRC_CONF,
2325 "Maximum number of child processes for this run of Apache"),
2326 AP_INIT_TAKE1("ThreadLimit", set_thread_limit, NULL, RSRC_CONF,
2327 "Maximum number of worker threads per child process for this run of Apache - Upper limit for ThreadsPerChild"),
2328 AP_GRACEFUL_SHUTDOWN_TIMEOUT_COMMAND,
2332 module AP_MODULE_DECLARE_DATA mpm_worker_module = {
2334 ap_mpm_rewrite_args, /* hook to run before apache parses args */
2335 NULL, /* create per-directory config structure */
2336 NULL, /* merge per-directory config structures */
2337 NULL, /* create per-server config structure */
2338 NULL, /* merge per-server config structures */
2339 worker_cmds, /* command apr_table_t */
2340 worker_hooks /* register_hooks */