switch to a 60 bit hash
[httpd-crcsyncproxy.git] / server / mpm / experimental / event / event.c
blobbe4969371195d58115a45782e349e45e2f90ab3d
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 /**
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 implmentation 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.
47 #include "apr.h"
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"
54 #include "apr_proc_mutex.h"
55 #include "apr_poll.h"
56 #include "apr_ring.h"
57 #include "apr_queue.h"
58 #define APR_WANT_STRFUNC
59 #include "apr_want.h"
61 #if APR_HAVE_UNISTD_H
62 #include <unistd.h>
63 #endif
64 #if APR_HAVE_SYS_SOCKET_H
65 #include <sys/socket.h>
66 #endif
67 #if APR_HAVE_SYS_WAIT_H
68 #include <sys/wait.h>
69 #endif
70 #ifdef HAVE_SYS_PROCESSOR_H
71 #include <sys/processor.h> /* for bindprocessor() */
72 #endif
74 #if !APR_HAS_THREADS
75 #error The Event MPM requires APR threads, but they are unavailable.
76 #endif
78 #include "ap_config.h"
79 #include "httpd.h"
80 #include "http_main.h"
81 #include "http_log.h"
82 #include "http_config.h" /* for read_config */
83 #include "http_core.h" /* for get_remote_host */
84 #include "http_connection.h"
85 #include "ap_mpm.h"
86 #include "pod.h"
87 #include "mpm_common.h"
88 #include "ap_listen.h"
89 #include "scoreboard.h"
90 #include "fdqueue.h"
91 #include "mpm_default.h"
92 #include "http_vhost.h"
94 #include <signal.h>
95 #include <limits.h> /* for INT_MAX */
97 /* Limit on the total --- clients will be locked out if more servers than
98 * this are needed. It is intended solely to keep the server from crashing
99 * when things get out of hand.
101 * We keep a hard maximum number of servers, for two reasons --- first off,
102 * in case something goes seriously wrong, we want to stop the fork bomb
103 * short of actually crashing the machine we're running on by filling some
104 * kernel table. Secondly, it keeps the size of the scoreboard file small
105 * enough that we can read the whole thing without worrying too much about
106 * the overhead.
108 #ifndef DEFAULT_SERVER_LIMIT
109 #define DEFAULT_SERVER_LIMIT 16
110 #endif
112 /* Admin can't tune ServerLimit beyond MAX_SERVER_LIMIT. We want
113 * some sort of compile-time limit to help catch typos.
115 #ifndef MAX_SERVER_LIMIT
116 #define MAX_SERVER_LIMIT 20000
117 #endif
119 /* Limit on the threads per process. Clients will be locked out if more than
120 * this are needed.
122 * We keep this for one reason it keeps the size of the scoreboard file small
123 * enough that we can read the whole thing without worrying too much about
124 * the overhead.
126 #ifndef DEFAULT_THREAD_LIMIT
127 #define DEFAULT_THREAD_LIMIT 64
128 #endif
130 /* Admin can't tune ThreadLimit beyond MAX_THREAD_LIMIT. We want
131 * some sort of compile-time limit to help catch typos.
133 #ifndef MAX_THREAD_LIMIT
134 #define MAX_THREAD_LIMIT 100000
135 #endif
138 * Actual definitions of config globals
141 int ap_threads_per_child = 0; /* Worker threads per child */
142 static int ap_daemons_to_start = 0;
143 static int min_spare_threads = 0;
144 static int max_spare_threads = 0;
145 static int ap_daemons_limit = 0;
146 static int max_clients = 0;
147 static int server_limit = 0;
148 static int first_server_limit = 0;
149 static int thread_limit = 0;
150 static int first_thread_limit = 0;
151 static int dying = 0;
152 static int workers_may_exit = 0;
153 static int start_thread_may_exit = 0;
154 static int listener_may_exit = 0;
155 static int requests_this_child;
156 static int num_listensocks = 0;
157 static int resource_shortage = 0;
158 static fd_queue_t *worker_queue;
159 static fd_queue_info_t *worker_queue_info;
160 static int mpm_state = AP_MPMQ_STARTING;
161 static int sick_child_detected;
163 static apr_thread_mutex_t *timeout_mutex;
164 APR_RING_HEAD(timeout_head_t, conn_state_t);
165 static struct timeout_head_t timeout_head, keepalive_timeout_head;
167 static apr_pollset_t *event_pollset;
169 /* The structure used to pass unique initialization info to each thread */
170 typedef struct
172 int pid;
173 int tid;
174 int sd;
175 } proc_info;
177 /* Structure used to pass information to the thread responsible for
178 * creating the rest of the threads.
180 typedef struct
182 apr_thread_t **threads;
183 apr_thread_t *listener;
184 int child_num_arg;
185 apr_threadattr_t *threadattr;
186 } thread_starter;
188 typedef enum
190 PT_CSD,
191 PT_ACCEPT
192 } poll_type_e;
194 typedef struct
196 poll_type_e type;
197 int bypass_push;
198 void *baton;
199 } listener_poll_type;
201 #define ID_FROM_CHILD_THREAD(c, t) ((c * thread_limit) + t)
204 * The max child slot ever assigned, preserved across restarts. Necessary
205 * to deal with MaxClients changes across AP_SIG_GRACEFUL restarts. We
206 * use this value to optimize routines that have to scan the entire
207 * scoreboard.
209 int ap_max_daemons_limit = -1;
211 static ap_pod_t *pod;
213 /* *Non*-shared http_main globals... */
215 server_rec *ap_server_conf;
217 /* The event MPM respects a couple of runtime flags that can aid
218 * in debugging. Setting the -DNO_DETACH flag will prevent the root process
219 * from detaching from its controlling terminal. Additionally, setting
220 * the -DONE_PROCESS flag (which implies -DNO_DETACH) will get you the
221 * child_main loop running in the process which originally started up.
222 * This gives you a pretty nice debugging environment. (You'll get a SIGHUP
223 * early in standalone_main; just continue through. This is the server
224 * trying to kill off any child processes which it might have lying
225 * around --- Apache doesn't keep track of their pids, it just sends
226 * SIGHUP to the process group, ignoring it in the root process.
227 * Continue through and you'll be fine.).
230 static int one_process = 0;
232 #ifdef DEBUG_SIGSTOP
233 int raise_sigstop_flags;
234 #endif
236 static apr_pool_t *pconf; /* Pool for config stuff */
237 static apr_pool_t *pchild; /* Pool for httpd child stuff */
239 static pid_t ap_my_pid; /* Linux getpid() doesn't work except in main
240 thread. Use this instead */
241 static pid_t parent_pid;
242 static apr_os_thread_t *listener_os_thread;
244 /* The LISTENER_SIGNAL signal will be sent from the main thread to the
245 * listener thread to wake it up for graceful termination (what a child
246 * process from an old generation does when the admin does "apachectl
247 * graceful"). This signal will be blocked in all threads of a child
248 * process except for the listener thread.
250 #define LISTENER_SIGNAL SIGHUP
252 /* An array of socket descriptors in use by each thread used to
253 * perform a non-graceful (forced) shutdown of the server.
255 static apr_socket_t **worker_sockets;
257 static void close_worker_sockets(void)
259 int i;
260 for (i = 0; i < ap_threads_per_child; i++) {
261 if (worker_sockets[i]) {
262 apr_socket_close(worker_sockets[i]);
263 worker_sockets[i] = NULL;
268 static void wakeup_listener(void)
270 listener_may_exit = 1;
271 if (!listener_os_thread) {
272 /* XXX there is an obscure path that this doesn't handle perfectly:
273 * right after listener thread is created but before
274 * listener_os_thread is set, the first worker thread hits an
275 * error and starts graceful termination
277 return;
280 /* unblock the listener if it's waiting for a worker */
281 ap_queue_info_term(worker_queue_info);
284 * we should just be able to "kill(ap_my_pid, LISTENER_SIGNAL)" on all
285 * platforms and wake up the listener thread since it is the only thread
286 * with SIGHUP unblocked, but that doesn't work on Linux
288 #ifdef HAVE_PTHREAD_KILL
289 pthread_kill(*listener_os_thread, LISTENER_SIGNAL);
290 #else
291 kill(ap_my_pid, LISTENER_SIGNAL);
292 #endif
295 #define ST_INIT 0
296 #define ST_GRACEFUL 1
297 #define ST_UNGRACEFUL 2
299 static int terminate_mode = ST_INIT;
301 static void signal_threads(int mode)
303 if (terminate_mode == mode) {
304 return;
306 terminate_mode = mode;
307 mpm_state = AP_MPMQ_STOPPING;
309 /* in case we weren't called from the listener thread, wake up the
310 * listener thread
312 wakeup_listener();
314 /* for ungraceful termination, let the workers exit now;
315 * for graceful termination, the listener thread will notify the
316 * workers to exit once it has stopped accepting new connections
318 if (mode == ST_UNGRACEFUL) {
319 workers_may_exit = 1;
320 ap_queue_interrupt_all(worker_queue);
321 close_worker_sockets(); /* forcefully kill all current connections */
325 AP_DECLARE(apr_status_t) ap_mpm_query(int query_code, int *result)
327 switch (query_code) {
328 case AP_MPMQ_MAX_DAEMON_USED:
329 *result = ap_max_daemons_limit;
330 return APR_SUCCESS;
331 case AP_MPMQ_IS_THREADED:
332 *result = AP_MPMQ_STATIC;
333 return APR_SUCCESS;
334 case AP_MPMQ_IS_FORKED:
335 *result = AP_MPMQ_DYNAMIC;
336 return APR_SUCCESS;
337 case AP_MPMQ_IS_ASYNC:
338 *result = 1;
339 return APR_SUCCESS;
340 case AP_MPMQ_HARD_LIMIT_DAEMONS:
341 *result = server_limit;
342 return APR_SUCCESS;
343 case AP_MPMQ_HARD_LIMIT_THREADS:
344 *result = thread_limit;
345 return APR_SUCCESS;
346 case AP_MPMQ_MAX_THREADS:
347 *result = ap_threads_per_child;
348 return APR_SUCCESS;
349 case AP_MPMQ_MIN_SPARE_DAEMONS:
350 *result = 0;
351 return APR_SUCCESS;
352 case AP_MPMQ_MIN_SPARE_THREADS:
353 *result = min_spare_threads;
354 return APR_SUCCESS;
355 case AP_MPMQ_MAX_SPARE_DAEMONS:
356 *result = 0;
357 return APR_SUCCESS;
358 case AP_MPMQ_MAX_SPARE_THREADS:
359 *result = max_spare_threads;
360 return APR_SUCCESS;
361 case AP_MPMQ_MAX_REQUESTS_DAEMON:
362 *result = ap_max_requests_per_child;
363 return APR_SUCCESS;
364 case AP_MPMQ_MAX_DAEMONS:
365 *result = ap_daemons_limit;
366 return APR_SUCCESS;
367 case AP_MPMQ_MPM_STATE:
368 *result = mpm_state;
369 return APR_SUCCESS;
371 return APR_ENOTIMPL;
374 /* a clean exit from a child with proper cleanup */
375 static void clean_child_exit(int code) __attribute__ ((noreturn));
376 static void clean_child_exit(int code)
378 mpm_state = AP_MPMQ_STOPPING;
379 if (pchild) {
380 apr_pool_destroy(pchild);
382 exit(code);
385 static void just_die(int sig)
387 clean_child_exit(0);
390 /*****************************************************************
391 * Connection structures and accounting...
394 /* volatile just in case */
395 static int volatile shutdown_pending;
396 static int volatile restart_pending;
397 static int volatile is_graceful;
398 static volatile int child_fatal;
399 ap_generation_t volatile ap_my_generation = 0;
402 * ap_start_shutdown() and ap_start_restart(), below, are a first stab at
403 * functions to initiate shutdown or restart without relying on signals.
404 * Previously this was initiated in sig_term() and restart() signal handlers,
405 * but we want to be able to start a shutdown/restart from other sources --
406 * e.g. on Win32, from the service manager. Now the service manager can
407 * call ap_start_shutdown() or ap_start_restart() as appropiate. Note that
408 * these functions can also be called by the child processes, since global
409 * variables are no longer used to pass on the required action to the parent.
411 * These should only be called from the parent process itself, since the
412 * parent process will use the shutdown_pending and restart_pending variables
413 * to determine whether to shutdown or restart. The child process should
414 * call signal_parent() directly to tell the parent to die -- this will
415 * cause neither of those variable to be set, which the parent will
416 * assume means something serious is wrong (which it will be, for the
417 * child to force an exit) and so do an exit anyway.
420 static void ap_start_shutdown(int graceful)
422 mpm_state = AP_MPMQ_STOPPING;
423 if (shutdown_pending == 1) {
424 /* Um, is this _probably_ not an error, if the user has
425 * tried to do a shutdown twice quickly, so we won't
426 * worry about reporting it.
428 return;
430 shutdown_pending = 1;
431 is_graceful = graceful;
434 /* do a graceful restart if graceful == 1 */
435 static void ap_start_restart(int graceful)
437 mpm_state = AP_MPMQ_STOPPING;
438 if (restart_pending == 1) {
439 /* Probably not an error - don't bother reporting it */
440 return;
442 restart_pending = 1;
443 is_graceful = graceful;
446 static void sig_term(int sig)
448 ap_start_shutdown(sig == AP_SIG_GRACEFUL_STOP);
451 static void restart(int sig)
453 ap_start_restart(sig == AP_SIG_GRACEFUL);
456 static void set_signals(void)
458 #ifndef NO_USE_SIGACTION
459 struct sigaction sa;
460 #endif
462 if (!one_process) {
463 ap_fatal_signal_setup(ap_server_conf, pconf);
466 #ifndef NO_USE_SIGACTION
467 sigemptyset(&sa.sa_mask);
468 sa.sa_flags = 0;
470 sa.sa_handler = sig_term;
471 if (sigaction(SIGTERM, &sa, NULL) < 0)
472 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
473 "sigaction(SIGTERM)");
474 #ifdef AP_SIG_GRACEFUL_STOP
475 if (sigaction(AP_SIG_GRACEFUL_STOP, &sa, NULL) < 0)
476 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
477 "sigaction(" AP_SIG_GRACEFUL_STOP_STRING ")");
478 #endif
479 #ifdef SIGINT
480 if (sigaction(SIGINT, &sa, NULL) < 0)
481 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
482 "sigaction(SIGINT)");
483 #endif
484 #ifdef SIGXCPU
485 sa.sa_handler = SIG_DFL;
486 if (sigaction(SIGXCPU, &sa, NULL) < 0)
487 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
488 "sigaction(SIGXCPU)");
489 #endif
490 #ifdef SIGXFSZ
491 sa.sa_handler = SIG_DFL;
492 if (sigaction(SIGXFSZ, &sa, NULL) < 0)
493 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
494 "sigaction(SIGXFSZ)");
495 #endif
496 #ifdef SIGPIPE
497 sa.sa_handler = SIG_IGN;
498 if (sigaction(SIGPIPE, &sa, NULL) < 0)
499 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
500 "sigaction(SIGPIPE)");
501 #endif
503 /* we want to ignore HUPs and AP_SIG_GRACEFUL while we're busy
504 * processing one */
505 sigaddset(&sa.sa_mask, SIGHUP);
506 sigaddset(&sa.sa_mask, AP_SIG_GRACEFUL);
507 sa.sa_handler = restart;
508 if (sigaction(SIGHUP, &sa, NULL) < 0)
509 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
510 "sigaction(SIGHUP)");
511 if (sigaction(AP_SIG_GRACEFUL, &sa, NULL) < 0)
512 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
513 "sigaction(" AP_SIG_GRACEFUL_STRING ")");
514 #else
515 if (!one_process) {
516 #ifdef SIGXCPU
517 apr_signal(SIGXCPU, SIG_DFL);
518 #endif /* SIGXCPU */
519 #ifdef SIGXFSZ
520 apr_signal(SIGXFSZ, SIG_DFL);
521 #endif /* SIGXFSZ */
524 apr_signal(SIGTERM, sig_term);
525 #ifdef SIGHUP
526 apr_signal(SIGHUP, restart);
527 #endif /* SIGHUP */
528 #ifdef AP_SIG_GRACEFUL
529 apr_signal(AP_SIG_GRACEFUL, restart);
530 #endif /* AP_SIG_GRACEFUL */
531 #ifdef AP_SIG_GRACEFUL_STOP
532 apr_signal(AP_SIG_GRACEFUL_STOP, sig_term);
533 #endif /* AP_SIG_GRACEFUL_STOP */
534 #ifdef SIGPIPE
535 apr_signal(SIGPIPE, SIG_IGN);
536 #endif /* SIGPIPE */
538 #endif
541 /*****************************************************************
542 * Child process main loop.
545 static int process_socket(apr_thread_t *thd, apr_pool_t * p, apr_socket_t * sock,
546 conn_state_t * cs, int my_child_num,
547 int my_thread_num)
549 conn_rec *c;
550 listener_poll_type *pt;
551 long conn_id = ID_FROM_CHILD_THREAD(my_child_num, my_thread_num);
552 int rc;
553 ap_sb_handle_t *sbh;
555 ap_create_sb_handle(&sbh, p, my_child_num, my_thread_num);
557 if (cs == NULL) { /* This is a new connection */
559 cs = apr_pcalloc(p, sizeof(conn_state_t));
561 pt = apr_pcalloc(p, sizeof(*pt));
563 cs->bucket_alloc = apr_bucket_alloc_create(p);
564 c = ap_run_create_connection(p, ap_server_conf, sock,
565 conn_id, sbh, cs->bucket_alloc);
566 c->current_thread = thd;
567 cs->c = c;
568 c->cs = cs;
569 cs->p = p;
570 cs->pfd.desc_type = APR_POLL_SOCKET;
571 cs->pfd.reqevents = APR_POLLIN;
572 cs->pfd.desc.s = sock;
573 pt->type = PT_CSD;
574 pt->bypass_push = 1;
575 pt->baton = cs;
576 cs->pfd.client_data = pt;
577 APR_RING_ELEM_INIT(cs, timeout_list);
579 ap_update_vhost_given_ip(c);
581 rc = ap_run_pre_connection(c, sock);
582 if (rc != OK && rc != DONE) {
583 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
584 "process_socket: connection aborted");
585 c->aborted = 1;
589 * XXX If the platform does not have a usable way of bundling
590 * accept() with a socket readability check, like Win32,
591 * and there are measurable delays before the
592 * socket is readable due to the first data packet arriving,
593 * it might be better to create the cs on the listener thread
594 * with the state set to CONN_STATE_CHECK_REQUEST_LINE_READABLE
596 * FreeBSD users will want to enable the HTTP accept filter
597 * module in their kernel for the highest performance
598 * When the accept filter is active, sockets are kept in the
599 * kernel until a HTTP request is received.
601 cs->state = CONN_STATE_READ_REQUEST_LINE;
604 else {
605 c = cs->c;
606 c->sbh = sbh;
607 pt = cs->pfd.client_data;
608 c->current_thread = thd;
611 if (c->clogging_input_filters && !c->aborted) {
612 /* Since we have an input filter which 'cloggs' the input stream,
613 * like mod_ssl, lets just do the normal read from input filters,
614 * like the Worker MPM does.
616 ap_run_process_connection(c);
617 if (cs->state != CONN_STATE_SUSPENDED) {
618 cs->state = CONN_STATE_LINGER;
622 read_request:
623 if (cs->state == CONN_STATE_READ_REQUEST_LINE) {
624 if (!c->aborted) {
625 ap_run_process_connection(c);
627 /* state will be updated upon return
628 * fall thru to either wait for readability/timeout or
629 * do lingering close
632 else {
633 cs->state = CONN_STATE_LINGER;
637 if (cs->state == CONN_STATE_WRITE_COMPLETION) {
638 ap_filter_t *output_filter = c->output_filters;
639 apr_status_t rv;
640 while (output_filter->next != NULL) {
641 output_filter = output_filter->next;
643 rv = output_filter->frec->filter_func.out_func(output_filter, NULL);
644 if (rv != APR_SUCCESS) {
645 ap_log_error(APLOG_MARK, APLOG_WARNING, rv, ap_server_conf,
646 "network write failure in core output filter");
647 cs->state = CONN_STATE_LINGER;
649 else if (c->data_in_output_filters) {
650 /* Still in WRITE_COMPLETION_STATE:
651 * Set a write timeout for this connection, and let the
652 * event thread poll for writeability.
654 cs->expiration_time = ap_server_conf->timeout + apr_time_now();
655 apr_thread_mutex_lock(timeout_mutex);
656 APR_RING_INSERT_TAIL(&timeout_head, cs, conn_state_t, timeout_list);
657 apr_thread_mutex_unlock(timeout_mutex);
658 pt->bypass_push = 0;
659 cs->pfd.reqevents = APR_POLLOUT | APR_POLLHUP | APR_POLLERR;
660 rc = apr_pollset_add(event_pollset, &cs->pfd);
661 return 1;
663 else if (c->keepalive != AP_CONN_KEEPALIVE || c->aborted ||
664 listener_may_exit) {
665 c->cs->state = CONN_STATE_LINGER;
667 else if (c->data_in_input_filters) {
668 cs->state = CONN_STATE_READ_REQUEST_LINE;
669 goto read_request;
671 else {
672 cs->state = CONN_STATE_CHECK_REQUEST_LINE_READABLE;
676 if (cs->state == CONN_STATE_LINGER) {
677 ap_lingering_close(c);
678 apr_pool_clear(p);
679 ap_push_pool(worker_queue_info, p);
680 return 0;
682 else if (cs->state == CONN_STATE_CHECK_REQUEST_LINE_READABLE) {
683 apr_status_t rc;
684 listener_poll_type *pt = (listener_poll_type *) cs->pfd.client_data;
686 /* It greatly simplifies the logic to use a single timeout value here
687 * because the new element can just be added to the end of the list and
688 * it will stay sorted in expiration time sequence. If brand new
689 * sockets are sent to the event thread for a readability check, this
690 * will be a slight behavior change - they use the non-keepalive
691 * timeout today. With a normal client, the socket will be readable in
692 * a few milliseconds anyway.
694 cs->expiration_time = ap_server_conf->keep_alive_timeout +
695 apr_time_now();
696 apr_thread_mutex_lock(timeout_mutex);
697 APR_RING_INSERT_TAIL(&keepalive_timeout_head, cs, conn_state_t, timeout_list);
698 apr_thread_mutex_unlock(timeout_mutex);
700 pt->bypass_push = 0;
701 /* Add work to pollset. */
702 cs->pfd.reqevents = APR_POLLIN;
703 rc = apr_pollset_add(event_pollset, &cs->pfd);
705 if (rc != APR_SUCCESS) {
706 ap_log_error(APLOG_MARK, APLOG_ERR, rc, ap_server_conf,
707 "process_socket: apr_pollset_add failure");
708 AP_DEBUG_ASSERT(rc == APR_SUCCESS);
711 return 1;
714 /* requests_this_child has gone to zero or below. See if the admin coded
715 "MaxRequestsPerChild 0", and keep going in that case. Doing it this way
716 simplifies the hot path in worker_thread */
717 static void check_infinite_requests(void)
719 if (ap_max_requests_per_child) {
720 signal_threads(ST_GRACEFUL);
722 else {
723 /* wow! if you're executing this code, you may have set a record.
724 * either this child process has served over 2 billion requests, or
725 * you're running a threaded 2.0 on a 16 bit machine.
727 * I'll buy pizza and beers at Apachecon for the first person to do
728 * the former without cheating (dorking with INT_MAX, or running with
729 * uncommitted performance patches, for example).
731 * for the latter case, you probably deserve a beer too. Greg Ames
734 requests_this_child = INT_MAX; /* keep going */
738 static void unblock_signal(int sig)
740 sigset_t sig_mask;
742 sigemptyset(&sig_mask);
743 sigaddset(&sig_mask, sig);
744 #if defined(SIGPROCMASK_SETS_THREAD_MASK)
745 sigprocmask(SIG_UNBLOCK, &sig_mask, NULL);
746 #else
747 pthread_sigmask(SIG_UNBLOCK, &sig_mask, NULL);
748 #endif
751 static void dummy_signal_handler(int sig)
753 /* XXX If specifying SIG_IGN is guaranteed to unblock a syscall,
754 * then we don't need this goofy function.
758 static apr_status_t init_pollset(apr_pool_t *p)
760 apr_status_t rv;
761 ap_listen_rec *lr;
762 listener_poll_type *pt;
764 rv = apr_thread_mutex_create(&timeout_mutex, APR_THREAD_MUTEX_DEFAULT, p);
765 if (rv != APR_SUCCESS) {
766 ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf,
767 "creation of the timeout mutex failed.");
768 return rv;
771 APR_RING_INIT(&timeout_head, conn_state_t, timeout_list);
772 APR_RING_INIT(&keepalive_timeout_head, conn_state_t, timeout_list);
774 /* Create the main pollset */
775 rv = apr_pollset_create(&event_pollset,
776 ap_threads_per_child,
777 p, APR_POLLSET_THREADSAFE | APR_POLLSET_NOCOPY);
778 if (rv != APR_SUCCESS) {
779 ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf,
780 "apr_pollset_create with Thread Safety failed.");
781 return rv;
784 for (lr = ap_listeners; lr != NULL; lr = lr->next) {
785 apr_pollfd_t *pfd = apr_palloc(p, sizeof(*pfd));
786 pt = apr_pcalloc(p, sizeof(*pt));
787 pfd->desc_type = APR_POLL_SOCKET;
788 pfd->desc.s = lr->sd;
789 pfd->reqevents = APR_POLLIN;
791 pt->type = PT_ACCEPT;
792 pt->baton = lr;
794 pfd->client_data = pt;
796 apr_socket_opt_set(pfd->desc.s, APR_SO_NONBLOCK, 1);
797 apr_pollset_add(event_pollset, pfd);
800 return APR_SUCCESS;
803 static apr_status_t push_timer2worker(timer_event_t* te)
805 return ap_queue_push_timer(worker_queue, te);
808 static apr_status_t push2worker(const apr_pollfd_t * pfd,
809 apr_pollset_t * pollset)
811 listener_poll_type *pt = (listener_poll_type *) pfd->client_data;
812 conn_state_t *cs = (conn_state_t *) pt->baton;
813 apr_status_t rc;
815 if (pt->bypass_push) {
816 return APR_SUCCESS;
819 pt->bypass_push = 1;
821 rc = apr_pollset_remove(pollset, pfd);
824 * Some of the pollset backends, like KQueue or Epoll
825 * automagically remove the FD if the socket is closed,
826 * therefore, we can accept _SUCCESS or _NOTFOUND,
827 * and we still want to keep going
829 if (rc != APR_SUCCESS && !APR_STATUS_IS_NOTFOUND(rc)) {
830 cs->state = CONN_STATE_LINGER;
833 rc = ap_queue_push(worker_queue, cs->pfd.desc.s, cs, cs->p);
834 if (rc != APR_SUCCESS) {
835 /* trash the connection; we couldn't queue the connected
836 * socket to a worker
838 apr_bucket_alloc_destroy(cs->bucket_alloc);
839 apr_socket_close(cs->pfd.desc.s);
840 ap_log_error(APLOG_MARK, APLOG_CRIT, rc,
841 ap_server_conf, "push2worker: ap_queue_push failed");
842 apr_pool_clear(cs->p);
843 ap_push_pool(worker_queue_info, cs->p);
846 return rc;
849 /* get_worker:
850 * reserve a worker thread, block if all are currently busy.
851 * this prevents the worker queue from overflowing and lets
852 * other processes accept new connections in the mean time.
854 static int get_worker(int *have_idle_worker_p)
856 apr_status_t rc;
858 if (!*have_idle_worker_p) {
859 rc = ap_queue_info_wait_for_idler(worker_queue_info);
861 if (rc == APR_SUCCESS) {
862 *have_idle_worker_p = 1;
863 return 1;
865 else {
866 if (!APR_STATUS_IS_EOF(rc)) {
867 ap_log_error(APLOG_MARK, APLOG_ERR, rc, ap_server_conf,
868 "ap_queue_info_wait_for_idler failed. "
869 "Attempting to shutdown process gracefully");
870 signal_threads(ST_GRACEFUL);
872 return 0;
875 else {
876 /* already reserved a worker thread - must have hit a
877 * transient error on a previous pass
879 return 1;
883 /* XXXXXX: Convert to skiplist or other better data structure
884 * (yes, this is VERY VERY VERY VERY BAD)
887 /* Structures to reuse */
888 static APR_RING_HEAD(timer_free_ring_t, timer_event_t) timer_free_ring;
889 /* Active timers */
890 static APR_RING_HEAD(timer_ring_t, timer_event_t) timer_ring;
892 static apr_thread_mutex_t *g_timer_ring_mtx;
894 AP_DECLARE(void) ap_mpm_register_timed_callback(apr_time_t t,
895 ap_mpm_callback_fn_t *cbfn,
896 void *baton)
898 int inserted = 0;
899 timer_event_t *ep;
900 timer_event_t *te;
901 /* oh yeah, and make locking smarter/fine grained. */
902 apr_thread_mutex_lock(g_timer_ring_mtx);
904 if (!APR_RING_EMPTY(&timer_free_ring, timer_event_t, link)) {
905 te = APR_RING_FIRST(&timer_free_ring);
906 APR_RING_REMOVE(te, link);
908 else {
909 /* XXXXX: lol, pool allocation without a context from any thread.Yeah. Right. MPMs Suck. */
910 te = malloc(sizeof(timer_event_t));
911 APR_RING_ELEM_INIT(te, link);
914 te->cbfunc = cbfn;
915 te->baton = baton;
916 /* XXXXX: optimize */
917 te->when = t + apr_time_now();
919 /* Okay, insert sorted by when.. */
920 for (ep = APR_RING_FIRST(&timer_ring);
921 ep != APR_RING_SENTINEL(&timer_ring,
922 timer_event_t, link);
923 ep = APR_RING_NEXT(ep, link))
925 if (ep->when > te->when) {
926 inserted = 1;
927 APR_RING_INSERT_BEFORE(ep, te, link);
928 break;
932 if (!inserted) {
933 APR_RING_INSERT_TAIL(&timer_ring, te, timer_event_t, link);
936 apr_thread_mutex_unlock(g_timer_ring_mtx);
939 #ifndef apr_time_from_msec
940 #define apr_time_from_msec(x) (x * 1000)
941 #endif
943 static void * APR_THREAD_FUNC listener_thread(apr_thread_t * thd, void *dummy)
945 timer_event_t *ep;
946 timer_event_t *te;
947 apr_status_t rc;
948 proc_info *ti = dummy;
949 int process_slot = ti->pid;
950 apr_pool_t *tpool = apr_thread_pool_get(thd);
951 void *csd = NULL;
952 apr_pool_t *ptrans; /* Pool for per-transaction stuff */
953 ap_listen_rec *lr;
954 int have_idle_worker = 0;
955 conn_state_t *cs;
956 const apr_pollfd_t *out_pfd;
957 apr_int32_t num = 0;
958 apr_time_t time_now = 0;
959 apr_interval_time_t timeout_interval;
960 apr_time_t timeout_time;
961 listener_poll_type *pt;
963 free(ti);
965 /* the following times out events that are really close in the future
966 * to prevent extra poll calls
968 * current value is .1 second
970 #define TIMEOUT_FUDGE_FACTOR 100000
971 #define EVENT_FUDGE_FACTOR 10000
973 rc = init_pollset(tpool);
974 if (rc != APR_SUCCESS) {
975 ap_log_error(APLOG_MARK, APLOG_ERR, rc, ap_server_conf,
976 "failed to initialize pollset, "
977 "attempting to shutdown process gracefully");
978 signal_threads(ST_GRACEFUL);
979 return NULL;
982 /* Unblock the signal used to wake this thread up, and set a handler for
983 * it.
985 unblock_signal(LISTENER_SIGNAL);
986 apr_signal(LISTENER_SIGNAL, dummy_signal_handler);
988 while (!listener_may_exit) {
990 if (requests_this_child <= 0) {
991 check_infinite_requests();
996 apr_time_t now = apr_time_now();
997 apr_thread_mutex_lock(g_timer_ring_mtx);
999 if (!APR_RING_EMPTY(&timer_ring, timer_event_t, link)) {
1000 te = APR_RING_FIRST(&timer_ring);
1001 if (te->when > now) {
1002 timeout_interval = te->when - now;
1004 else {
1005 timeout_interval = 1;
1008 else {
1009 timeout_interval = apr_time_from_msec(100);
1011 apr_thread_mutex_unlock(g_timer_ring_mtx);
1014 rc = apr_pollset_poll(event_pollset, timeout_interval, &num,
1015 &out_pfd);
1017 if (rc != APR_SUCCESS) {
1018 if (APR_STATUS_IS_EINTR(rc)) {
1019 continue;
1021 if (!APR_STATUS_IS_TIMEUP(rc)) {
1022 ap_log_error(APLOG_MARK, APLOG_ERR, rc, ap_server_conf,
1023 "apr_pollset_poll failed. Attempting to "
1024 "shutdown process gracefully");
1025 signal_threads(ST_GRACEFUL);
1029 if (listener_may_exit)
1030 break;
1033 apr_time_t now = apr_time_now();
1034 apr_thread_mutex_lock(g_timer_ring_mtx);
1035 for (ep = APR_RING_FIRST(&timer_ring);
1036 ep != APR_RING_SENTINEL(&timer_ring,
1037 timer_event_t, link);
1038 ep = APR_RING_FIRST(&timer_ring))
1040 if (ep->when < now + EVENT_FUDGE_FACTOR) {
1041 APR_RING_REMOVE(ep, link);
1042 push_timer2worker(ep);
1044 else {
1045 break;
1048 apr_thread_mutex_unlock(g_timer_ring_mtx);
1051 while (num && get_worker(&have_idle_worker)) {
1052 pt = (listener_poll_type *) out_pfd->client_data;
1053 if (pt->type == PT_CSD) {
1054 /* one of the sockets is readable */
1055 cs = (conn_state_t *) pt->baton;
1056 switch (cs->state) {
1057 case CONN_STATE_CHECK_REQUEST_LINE_READABLE:
1058 cs->state = CONN_STATE_READ_REQUEST_LINE;
1059 break;
1060 case CONN_STATE_WRITE_COMPLETION:
1061 break;
1062 default:
1063 ap_log_error(APLOG_MARK, APLOG_ERR, rc,
1064 ap_server_conf,
1065 "event_loop: unexpected state %d",
1066 cs->state);
1067 AP_DEBUG_ASSERT(0);
1070 apr_thread_mutex_lock(timeout_mutex);
1071 APR_RING_REMOVE(cs, timeout_list);
1072 apr_thread_mutex_unlock(timeout_mutex);
1073 APR_RING_ELEM_INIT(cs, timeout_list);
1075 rc = push2worker(out_pfd, event_pollset);
1076 if (rc != APR_SUCCESS) {
1077 ap_log_error(APLOG_MARK, APLOG_CRIT, rc,
1078 ap_server_conf, "push2worker failed");
1080 else {
1081 have_idle_worker = 0;
1084 else {
1085 /* A Listener Socket is ready for an accept() */
1087 lr = (ap_listen_rec *) pt->baton;
1089 ap_pop_pool(&ptrans, worker_queue_info);
1091 if (ptrans == NULL) {
1092 /* create a new transaction pool for each accepted socket */
1093 apr_allocator_t *allocator;
1095 apr_allocator_create(&allocator);
1096 apr_allocator_max_free_set(allocator,
1097 ap_max_mem_free);
1098 apr_pool_create_ex(&ptrans, pconf, NULL, allocator);
1099 apr_allocator_owner_set(allocator, ptrans);
1100 if (ptrans == NULL) {
1101 ap_log_error(APLOG_MARK, APLOG_CRIT, rc,
1102 ap_server_conf,
1103 "Failed to create transaction pool");
1104 signal_threads(ST_GRACEFUL);
1105 return NULL;
1109 apr_pool_tag(ptrans, "transaction");
1111 rc = lr->accept_func(&csd, lr, ptrans);
1113 /* later we trash rv and rely on csd to indicate
1114 * success/failure
1116 AP_DEBUG_ASSERT(rc == APR_SUCCESS || !csd);
1118 if (rc == APR_EGENERAL) {
1119 /* E[NM]FILE, ENOMEM, etc */
1120 resource_shortage = 1;
1121 signal_threads(ST_GRACEFUL);
1124 if (csd != NULL) {
1125 rc = ap_queue_push(worker_queue, csd, NULL, ptrans);
1126 if (rc != APR_SUCCESS) {
1127 /* trash the connection; we couldn't queue the connected
1128 * socket to a worker
1130 apr_socket_close(csd);
1131 ap_log_error(APLOG_MARK, APLOG_CRIT, rc,
1132 ap_server_conf,
1133 "ap_queue_push failed");
1134 apr_pool_clear(ptrans);
1135 ap_push_pool(worker_queue_info, ptrans);
1137 else {
1138 have_idle_worker = 0;
1141 else {
1142 apr_pool_clear(ptrans);
1143 ap_push_pool(worker_queue_info, ptrans);
1145 } /* if:else on pt->type */
1146 out_pfd++;
1147 num--;
1148 } /* while for processing poll */
1150 /* XXX possible optimization: stash the current time for use as
1151 * r->request_time for new requests
1153 time_now = apr_time_now();
1155 /* handle timed out sockets */
1156 apr_thread_mutex_lock(timeout_mutex);
1158 /* Step 1: keepalive timeouts */
1159 cs = APR_RING_FIRST(&keepalive_timeout_head);
1160 timeout_time = time_now + TIMEOUT_FUDGE_FACTOR;
1161 while (!APR_RING_EMPTY(&keepalive_timeout_head, conn_state_t, timeout_list)
1162 && cs->expiration_time < timeout_time) {
1164 cs->state = CONN_STATE_LINGER;
1166 APR_RING_REMOVE(cs, timeout_list);
1167 apr_thread_mutex_unlock(timeout_mutex);
1169 if (!get_worker(&have_idle_worker)) {
1170 apr_thread_mutex_lock(timeout_mutex);
1171 APR_RING_INSERT_HEAD(&keepalive_timeout_head, cs,
1172 conn_state_t, timeout_list);
1173 break;
1176 rc = push2worker(&cs->pfd, event_pollset);
1178 if (rc != APR_SUCCESS) {
1179 return NULL;
1180 /* XXX return NULL looks wrong - not an init failure
1181 * that bypasses all the cleanup outside the main loop
1182 * break seems more like it
1183 * need to evaluate seriousness of push2worker failures
1186 have_idle_worker = 0;
1187 apr_thread_mutex_lock(timeout_mutex);
1188 cs = APR_RING_FIRST(&keepalive_timeout_head);
1191 /* Step 2: write completion timeouts */
1192 cs = APR_RING_FIRST(&timeout_head);
1193 while (!APR_RING_EMPTY(&timeout_head, conn_state_t, timeout_list)
1194 && cs->expiration_time < timeout_time) {
1196 cs->state = CONN_STATE_LINGER;
1197 APR_RING_REMOVE(cs, timeout_list);
1198 apr_thread_mutex_unlock(timeout_mutex);
1200 if (!get_worker(&have_idle_worker)) {
1201 apr_thread_mutex_lock(timeout_mutex);
1202 APR_RING_INSERT_HEAD(&timeout_head, cs,
1203 conn_state_t, timeout_list);
1204 break;
1207 rc = push2worker(&cs->pfd, event_pollset);
1208 if (rc != APR_SUCCESS) {
1209 return NULL;
1211 have_idle_worker = 0;
1212 apr_thread_mutex_lock(timeout_mutex);
1213 cs = APR_RING_FIRST(&timeout_head);
1216 apr_thread_mutex_unlock(timeout_mutex);
1218 } /* listener main loop */
1220 ap_close_listeners();
1221 ap_queue_term(worker_queue);
1222 dying = 1;
1223 ap_scoreboard_image->parent[process_slot].quiescing = 1;
1225 /* wake up the main thread */
1226 kill(ap_my_pid, SIGTERM);
1228 apr_thread_exit(thd, APR_SUCCESS);
1229 return NULL;
1232 /* XXX For ungraceful termination/restart, we definitely don't want to
1233 * wait for active connections to finish but we may want to wait
1234 * for idle workers to get out of the queue code and release mutexes,
1235 * since those mutexes are cleaned up pretty soon and some systems
1236 * may not react favorably (i.e., segfault) if operations are attempted
1237 * on cleaned-up mutexes.
1239 static void *APR_THREAD_FUNC worker_thread(apr_thread_t * thd, void *dummy)
1241 proc_info *ti = dummy;
1242 int process_slot = ti->pid;
1243 int thread_slot = ti->tid;
1244 apr_socket_t *csd = NULL;
1245 conn_state_t *cs;
1246 apr_pool_t *ptrans; /* Pool for per-transaction stuff */
1247 apr_status_t rv;
1248 int is_idle = 0;
1249 timer_event_t *te = NULL;
1251 free(ti);
1253 ap_scoreboard_image->servers[process_slot][thread_slot].pid = ap_my_pid;
1254 ap_scoreboard_image->servers[process_slot][thread_slot].tid = apr_os_thread_current();
1255 ap_scoreboard_image->servers[process_slot][thread_slot].generation = ap_my_generation;
1256 ap_update_child_status_from_indexes(process_slot, thread_slot,
1257 SERVER_STARTING, NULL);
1259 while (!workers_may_exit) {
1260 if (!is_idle) {
1261 rv = ap_queue_info_set_idle(worker_queue_info, NULL);
1262 if (rv != APR_SUCCESS) {
1263 ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
1264 "ap_queue_info_set_idle failed. Attempting to "
1265 "shutdown process gracefully.");
1266 signal_threads(ST_GRACEFUL);
1267 break;
1269 is_idle = 1;
1272 ap_update_child_status_from_indexes(process_slot, thread_slot,
1273 SERVER_READY, NULL);
1274 worker_pop:
1275 if (workers_may_exit) {
1276 break;
1279 te = NULL;
1281 rv = ap_queue_pop_something(worker_queue, &csd, &cs, &ptrans, &te);
1283 if (rv != APR_SUCCESS) {
1284 /* We get APR_EOF during a graceful shutdown once all the
1285 * connections accepted by this server process have been handled.
1287 if (APR_STATUS_IS_EOF(rv)) {
1288 break;
1290 /* We get APR_EINTR whenever ap_queue_pop() has been interrupted
1291 * from an explicit call to ap_queue_interrupt_all(). This allows
1292 * us to unblock threads stuck in ap_queue_pop() when a shutdown
1293 * is pending.
1295 * If workers_may_exit is set and this is ungraceful termination/
1296 * restart, we are bound to get an error on some systems (e.g.,
1297 * AIX, which sanity-checks mutex operations) since the queue
1298 * may have already been cleaned up. Don't log the "error" if
1299 * workers_may_exit is set.
1301 else if (APR_STATUS_IS_EINTR(rv)) {
1302 goto worker_pop;
1304 /* We got some other error. */
1305 else if (!workers_may_exit) {
1306 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
1307 "ap_queue_pop failed");
1309 continue;
1311 if (te != NULL) {
1313 te->cbfunc(te->baton);
1316 apr_thread_mutex_lock(g_timer_ring_mtx);
1317 APR_RING_INSERT_TAIL(&timer_free_ring, te, timer_event_t, link);
1318 apr_thread_mutex_unlock(g_timer_ring_mtx);
1321 else {
1322 is_idle = 0;
1323 worker_sockets[thread_slot] = csd;
1324 rv = process_socket(thd, ptrans, csd, cs, process_slot, thread_slot);
1325 if (!rv) {
1326 requests_this_child--;
1328 worker_sockets[thread_slot] = NULL;
1332 ap_update_child_status_from_indexes(process_slot, thread_slot,
1333 (dying) ? SERVER_DEAD :
1334 SERVER_GRACEFUL,
1335 (request_rec *) NULL);
1337 apr_thread_exit(thd, APR_SUCCESS);
1338 return NULL;
1341 static int check_signal(int signum)
1343 switch (signum) {
1344 case SIGTERM:
1345 case SIGINT:
1346 return 1;
1348 return 0;
1353 static void create_listener_thread(thread_starter * ts)
1355 int my_child_num = ts->child_num_arg;
1356 apr_threadattr_t *thread_attr = ts->threadattr;
1357 proc_info *my_info;
1358 apr_status_t rv;
1360 my_info = (proc_info *) malloc(sizeof(proc_info));
1361 my_info->pid = my_child_num;
1362 my_info->tid = -1; /* listener thread doesn't have a thread slot */
1363 my_info->sd = 0;
1364 rv = apr_thread_create(&ts->listener, thread_attr, listener_thread,
1365 my_info, pchild);
1366 if (rv != APR_SUCCESS) {
1367 ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
1368 "apr_thread_create: unable to create listener thread");
1369 /* let the parent decide how bad this really is */
1370 clean_child_exit(APEXIT_CHILDSICK);
1372 apr_os_thread_get(&listener_os_thread, ts->listener);
1375 /* XXX under some circumstances not understood, children can get stuck
1376 * in start_threads forever trying to take over slots which will
1377 * never be cleaned up; for now there is an APLOG_DEBUG message issued
1378 * every so often when this condition occurs
1380 static void *APR_THREAD_FUNC start_threads(apr_thread_t * thd, void *dummy)
1382 thread_starter *ts = dummy;
1383 apr_thread_t **threads = ts->threads;
1384 apr_threadattr_t *thread_attr = ts->threadattr;
1385 int child_num_arg = ts->child_num_arg;
1386 int my_child_num = child_num_arg;
1387 proc_info *my_info;
1388 apr_status_t rv;
1389 int i;
1390 int threads_created = 0;
1391 int listener_started = 0;
1392 int loops;
1393 int prev_threads_created;
1395 /* We must create the fd queues before we start up the listener
1396 * and worker threads. */
1397 worker_queue = apr_pcalloc(pchild, sizeof(*worker_queue));
1398 rv = ap_queue_init(worker_queue, ap_threads_per_child, pchild);
1399 if (rv != APR_SUCCESS) {
1400 ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
1401 "ap_queue_init() failed");
1402 clean_child_exit(APEXIT_CHILDFATAL);
1405 rv = ap_queue_info_create(&worker_queue_info, pchild,
1406 ap_threads_per_child);
1407 if (rv != APR_SUCCESS) {
1408 ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
1409 "ap_queue_info_create() failed");
1410 clean_child_exit(APEXIT_CHILDFATAL);
1413 worker_sockets = apr_pcalloc(pchild, ap_threads_per_child
1414 * sizeof(apr_socket_t *));
1416 loops = prev_threads_created = 0;
1417 while (1) {
1418 /* ap_threads_per_child does not include the listener thread */
1419 for (i = 0; i < ap_threads_per_child; i++) {
1420 int status =
1421 ap_scoreboard_image->servers[child_num_arg][i].status;
1423 if (status != SERVER_GRACEFUL && status != SERVER_DEAD) {
1424 continue;
1427 my_info = (proc_info *) malloc(sizeof(proc_info));
1428 if (my_info == NULL) {
1429 ap_log_error(APLOG_MARK, APLOG_ALERT, errno, ap_server_conf,
1430 "malloc: out of memory");
1431 clean_child_exit(APEXIT_CHILDFATAL);
1433 my_info->pid = my_child_num;
1434 my_info->tid = i;
1435 my_info->sd = 0;
1437 /* We are creating threads right now */
1438 ap_update_child_status_from_indexes(my_child_num, i,
1439 SERVER_STARTING, NULL);
1440 /* We let each thread update its own scoreboard entry. This is
1441 * done because it lets us deal with tid better.
1443 rv = apr_thread_create(&threads[i], thread_attr,
1444 worker_thread, my_info, pchild);
1445 if (rv != APR_SUCCESS) {
1446 ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
1447 "apr_thread_create: unable to create worker thread");
1448 /* let the parent decide how bad this really is */
1449 clean_child_exit(APEXIT_CHILDSICK);
1451 threads_created++;
1454 /* Start the listener only when there are workers available */
1455 if (!listener_started && threads_created) {
1456 create_listener_thread(ts);
1457 listener_started = 1;
1461 if (start_thread_may_exit || threads_created == ap_threads_per_child) {
1462 break;
1464 /* wait for previous generation to clean up an entry */
1465 apr_sleep(apr_time_from_sec(1));
1466 ++loops;
1467 if (loops % 120 == 0) { /* every couple of minutes */
1468 if (prev_threads_created == threads_created) {
1469 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
1470 "child %" APR_PID_T_FMT " isn't taking over "
1471 "slots very quickly (%d of %d)",
1472 ap_my_pid, threads_created,
1473 ap_threads_per_child);
1475 prev_threads_created = threads_created;
1479 /* What state should this child_main process be listed as in the
1480 * scoreboard...?
1481 * ap_update_child_status_from_indexes(my_child_num, i, SERVER_STARTING,
1482 * (request_rec *) NULL);
1484 * This state should be listed separately in the scoreboard, in some kind
1485 * of process_status, not mixed in with the worker threads' status.
1486 * "life_status" is almost right, but it's in the worker's structure, and
1487 * the name could be clearer. gla
1489 apr_thread_exit(thd, APR_SUCCESS);
1490 return NULL;
1493 static void join_workers(apr_thread_t * listener, apr_thread_t ** threads)
1495 int i;
1496 apr_status_t rv, thread_rv;
1498 if (listener) {
1499 int iter;
1501 /* deal with a rare timing window which affects waking up the
1502 * listener thread... if the signal sent to the listener thread
1503 * is delivered between the time it verifies that the
1504 * listener_may_exit flag is clear and the time it enters a
1505 * blocking syscall, the signal didn't do any good... work around
1506 * that by sleeping briefly and sending it again
1509 iter = 0;
1510 while (iter < 10 &&
1511 #ifdef HAVE_PTHREAD_KILL
1512 pthread_kill(*listener_os_thread, 0)
1513 #else
1514 kill(ap_my_pid, 0)
1515 #endif
1516 == 0) {
1517 /* listener not dead yet */
1518 apr_sleep(apr_time_make(0, 500000));
1519 wakeup_listener();
1520 ++iter;
1522 if (iter >= 10) {
1523 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
1524 "the listener thread didn't exit");
1526 else {
1527 rv = apr_thread_join(&thread_rv, listener);
1528 if (rv != APR_SUCCESS) {
1529 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
1530 "apr_thread_join: unable to join listener thread");
1535 for (i = 0; i < ap_threads_per_child; i++) {
1536 if (threads[i]) { /* if we ever created this thread */
1537 rv = apr_thread_join(&thread_rv, threads[i]);
1538 if (rv != APR_SUCCESS) {
1539 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
1540 "apr_thread_join: unable to join worker "
1541 "thread %d", i);
1547 static void join_start_thread(apr_thread_t * start_thread_id)
1549 apr_status_t rv, thread_rv;
1551 start_thread_may_exit = 1; /* tell it to give up in case it is still
1552 * trying to take over slots from a
1553 * previous generation
1555 rv = apr_thread_join(&thread_rv, start_thread_id);
1556 if (rv != APR_SUCCESS) {
1557 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
1558 "apr_thread_join: unable to join the start " "thread");
1562 static void child_main(int child_num_arg)
1564 apr_thread_t **threads;
1565 apr_status_t rv;
1566 thread_starter *ts;
1567 apr_threadattr_t *thread_attr;
1568 apr_thread_t *start_thread_id;
1570 mpm_state = AP_MPMQ_STARTING; /* for benefit of any hooks that run as this
1571 * child initializes
1573 ap_my_pid = getpid();
1574 ap_fatal_signal_child_setup(ap_server_conf);
1575 apr_pool_create(&pchild, pconf);
1577 /*stuff to do before we switch id's, so we have permissions. */
1578 ap_reopen_scoreboard(pchild, NULL, 0);
1580 if (ap_run_drop_privileges(pchild, ap_server_conf)) {
1581 clean_child_exit(APEXIT_CHILDFATAL);
1584 apr_thread_mutex_create(&g_timer_ring_mtx, APR_THREAD_MUTEX_DEFAULT, pchild);
1585 APR_RING_INIT(&timer_free_ring, timer_event_t, link);
1586 APR_RING_INIT(&timer_ring, timer_event_t, link);
1588 ap_run_child_init(pchild, ap_server_conf);
1590 /* done with init critical section */
1592 /* Just use the standard apr_setup_signal_thread to block all signals
1593 * from being received. The child processes no longer use signals for
1594 * any communication with the parent process.
1596 rv = apr_setup_signal_thread();
1597 if (rv != APR_SUCCESS) {
1598 ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
1599 "Couldn't initialize signal thread");
1600 clean_child_exit(APEXIT_CHILDFATAL);
1603 if (ap_max_requests_per_child) {
1604 requests_this_child = ap_max_requests_per_child;
1606 else {
1607 /* coding a value of zero means infinity */
1608 requests_this_child = INT_MAX;
1611 /* Setup worker threads */
1613 /* clear the storage; we may not create all our threads immediately,
1614 * and we want a 0 entry to indicate a thread which was not created
1616 threads = (apr_thread_t **) calloc(1,
1617 sizeof(apr_thread_t *) *
1618 ap_threads_per_child);
1619 if (threads == NULL) {
1620 ap_log_error(APLOG_MARK, APLOG_ALERT, errno, ap_server_conf,
1621 "malloc: out of memory");
1622 clean_child_exit(APEXIT_CHILDFATAL);
1625 ts = (thread_starter *) apr_palloc(pchild, sizeof(*ts));
1627 apr_threadattr_create(&thread_attr, pchild);
1628 /* 0 means PTHREAD_CREATE_JOINABLE */
1629 apr_threadattr_detach_set(thread_attr, 0);
1631 if (ap_thread_stacksize != 0) {
1632 apr_threadattr_stacksize_set(thread_attr, ap_thread_stacksize);
1635 ts->threads = threads;
1636 ts->listener = NULL;
1637 ts->child_num_arg = child_num_arg;
1638 ts->threadattr = thread_attr;
1640 rv = apr_thread_create(&start_thread_id, thread_attr, start_threads,
1641 ts, pchild);
1642 if (rv != APR_SUCCESS) {
1643 ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
1644 "apr_thread_create: unable to create worker thread");
1645 /* let the parent decide how bad this really is */
1646 clean_child_exit(APEXIT_CHILDSICK);
1649 mpm_state = AP_MPMQ_RUNNING;
1651 /* If we are only running in one_process mode, we will want to
1652 * still handle signals. */
1653 if (one_process) {
1654 /* Block until we get a terminating signal. */
1655 apr_signal_thread(check_signal);
1656 /* make sure the start thread has finished; signal_threads()
1657 * and join_workers() depend on that
1659 /* XXX join_start_thread() won't be awakened if one of our
1660 * threads encounters a critical error and attempts to
1661 * shutdown this child
1663 join_start_thread(start_thread_id);
1665 /* helps us terminate a little more quickly than the dispatch of the
1666 * signal thread; beats the Pipe of Death and the browsers
1668 signal_threads(ST_UNGRACEFUL);
1670 /* A terminating signal was received. Now join each of the
1671 * workers to clean them up.
1672 * If the worker already exited, then the join frees
1673 * their resources and returns.
1674 * If the worker hasn't exited, then this blocks until
1675 * they have (then cleans up).
1677 join_workers(ts->listener, threads);
1679 else { /* !one_process */
1680 /* remove SIGTERM from the set of blocked signals... if one of
1681 * the other threads in the process needs to take us down
1682 * (e.g., for MaxRequestsPerChild) it will send us SIGTERM
1684 unblock_signal(SIGTERM);
1685 apr_signal(SIGTERM, dummy_signal_handler);
1686 /* Watch for any messages from the parent over the POD */
1687 while (1) {
1688 rv = ap_mpm_pod_check(pod);
1689 if (rv == AP_NORESTART) {
1690 /* see if termination was triggered while we slept */
1691 switch (terminate_mode) {
1692 case ST_GRACEFUL:
1693 rv = AP_GRACEFUL;
1694 break;
1695 case ST_UNGRACEFUL:
1696 rv = AP_RESTART;
1697 break;
1700 if (rv == AP_GRACEFUL || rv == AP_RESTART) {
1701 /* make sure the start thread has finished;
1702 * signal_threads() and join_workers depend on that
1704 join_start_thread(start_thread_id);
1705 signal_threads(rv ==
1706 AP_GRACEFUL ? ST_GRACEFUL : ST_UNGRACEFUL);
1707 break;
1711 /* A terminating signal was received. Now join each of the
1712 * workers to clean them up.
1713 * If the worker already exited, then the join frees
1714 * their resources and returns.
1715 * If the worker hasn't exited, then this blocks until
1716 * they have (then cleans up).
1718 join_workers(ts->listener, threads);
1721 free(threads);
1723 clean_child_exit(resource_shortage ? APEXIT_CHILDSICK : 0);
1726 static int make_child(server_rec * s, int slot)
1728 int pid;
1730 if (slot + 1 > ap_max_daemons_limit) {
1731 ap_max_daemons_limit = slot + 1;
1734 if (one_process) {
1735 set_signals();
1736 ap_scoreboard_image->parent[slot].pid = getpid();
1737 child_main(slot);
1740 if ((pid = fork()) == -1) {
1741 ap_log_error(APLOG_MARK, APLOG_ERR, errno, s,
1742 "fork: Unable to fork new process");
1744 /* fork didn't succeed. There's no need to touch the scoreboard;
1745 * if we were trying to replace a failed child process, then
1746 * server_main_loop() marked its workers SERVER_DEAD, and if
1747 * we were trying to replace a child process that exited normally,
1748 * its worker_thread()s left SERVER_DEAD or SERVER_GRACEFUL behind.
1751 /* In case system resources are maxxed out, we don't want
1752 Apache running away with the CPU trying to fork over and
1753 over and over again. */
1754 apr_sleep(apr_time_from_sec(10));
1756 return -1;
1759 if (!pid) {
1760 #ifdef HAVE_BINDPROCESSOR
1761 /* By default, AIX binds to a single processor. This bit unbinds
1762 * children which will then bind to another CPU.
1764 int status = bindprocessor(BINDPROCESS, (int) getpid(),
1765 PROCESSOR_CLASS_ANY);
1766 if (status != OK)
1767 ap_log_error(APLOG_MARK, APLOG_WARNING, errno,
1768 ap_server_conf,
1769 "processor unbind failed %d", status);
1770 #endif
1771 RAISE_SIGSTOP(MAKE_CHILD);
1773 apr_signal(SIGTERM, just_die);
1774 child_main(slot);
1776 clean_child_exit(0);
1778 /* else */
1779 if (ap_scoreboard_image->parent[slot].pid != 0) {
1780 /* This new child process is squatting on the scoreboard
1781 * entry owned by an exiting child process, which cannot
1782 * exit until all active requests complete.
1783 * Don't forget about this exiting child process, or we
1784 * won't be able to kill it if it doesn't exit by the
1785 * time the server is shut down.
1787 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
1788 "taking over scoreboard slot from %" APR_PID_T_FMT "%s",
1789 ap_scoreboard_image->parent[slot].pid,
1790 ap_scoreboard_image->parent[slot].quiescing ?
1791 " (quiescing)" : "");
1792 ap_register_extra_mpm_process(ap_scoreboard_image->parent[slot].pid);
1794 ap_scoreboard_image->parent[slot].quiescing = 0;
1795 ap_scoreboard_image->parent[slot].pid = pid;
1796 return 0;
1799 /* start up a bunch of children */
1800 static void startup_children(int number_to_start)
1802 int i;
1804 for (i = 0; number_to_start && i < ap_daemons_limit; ++i) {
1805 if (ap_scoreboard_image->parent[i].pid != 0) {
1806 continue;
1808 if (make_child(ap_server_conf, i) < 0) {
1809 break;
1811 --number_to_start;
1817 * idle_spawn_rate is the number of children that will be spawned on the
1818 * next maintenance cycle if there aren't enough idle servers. It is
1819 * doubled up to MAX_SPAWN_RATE, and reset only when a cycle goes by
1820 * without the need to spawn.
1822 static int idle_spawn_rate = 1;
1823 #ifndef MAX_SPAWN_RATE
1824 #define MAX_SPAWN_RATE (32)
1825 #endif
1826 static int hold_off_on_exponential_spawning;
1828 static void perform_idle_server_maintenance(void)
1830 int i, j;
1831 int idle_thread_count;
1832 worker_score *ws;
1833 process_score *ps;
1834 int free_length;
1835 int totally_free_length = 0;
1836 int free_slots[MAX_SPAWN_RATE];
1837 int last_non_dead;
1838 int total_non_dead;
1839 int active_thread_count = 0;
1841 /* initialize the free_list */
1842 free_length = 0;
1844 idle_thread_count = 0;
1845 last_non_dead = -1;
1846 total_non_dead = 0;
1848 for (i = 0; i < ap_daemons_limit; ++i) {
1849 /* Initialization to satisfy the compiler. It doesn't know
1850 * that ap_threads_per_child is always > 0 */
1851 int status = SERVER_DEAD;
1852 int any_dying_threads = 0;
1853 int any_dead_threads = 0;
1854 int all_dead_threads = 1;
1856 if (i >= ap_max_daemons_limit
1857 && totally_free_length == idle_spawn_rate)
1858 /* short cut if all active processes have been examined and
1859 * enough empty scoreboard slots have been found
1862 break;
1863 ps = &ap_scoreboard_image->parent[i];
1864 for (j = 0; j < ap_threads_per_child; j++) {
1865 ws = &ap_scoreboard_image->servers[i][j];
1866 status = ws->status;
1868 /* XXX any_dying_threads is probably no longer needed GLA */
1869 any_dying_threads = any_dying_threads ||
1870 (status == SERVER_GRACEFUL);
1871 any_dead_threads = any_dead_threads || (status == SERVER_DEAD);
1872 all_dead_threads = all_dead_threads &&
1873 (status == SERVER_DEAD || status == SERVER_GRACEFUL);
1875 /* We consider a starting server as idle because we started it
1876 * at least a cycle ago, and if it still hasn't finished starting
1877 * then we're just going to swamp things worse by forking more.
1878 * So we hopefully won't need to fork more if we count it.
1879 * This depends on the ordering of SERVER_READY and SERVER_STARTING.
1881 if (ps->pid != 0) { /* XXX just set all_dead_threads in outer
1882 for loop if no pid? not much else matters */
1883 if (status <= SERVER_READY &&
1884 !ps->quiescing && ps->generation == ap_my_generation) {
1885 ++idle_thread_count;
1887 if (status >= SERVER_READY && status < SERVER_GRACEFUL) {
1888 ++active_thread_count;
1892 if (any_dead_threads
1893 && totally_free_length < idle_spawn_rate
1894 && free_length < MAX_SPAWN_RATE
1895 && (!ps->pid /* no process in the slot */
1896 || ps->quiescing)) { /* or at least one is going away */
1897 if (all_dead_threads) {
1898 /* great! we prefer these, because the new process can
1899 * start more threads sooner. So prioritize this slot
1900 * by putting it ahead of any slots with active threads.
1902 * first, make room by moving a slot that's potentially still
1903 * in use to the end of the array
1905 free_slots[free_length] = free_slots[totally_free_length];
1906 free_slots[totally_free_length++] = i;
1908 else {
1909 /* slot is still in use - back of the bus
1911 free_slots[free_length] = i;
1913 ++free_length;
1915 /* XXX if (!ps->quiescing) is probably more reliable GLA */
1916 if (!any_dying_threads) {
1917 last_non_dead = i;
1918 ++total_non_dead;
1922 if (sick_child_detected) {
1923 if (active_thread_count > 0) {
1924 /* some child processes appear to be working. don't kill the
1925 * whole server.
1927 sick_child_detected = 0;
1929 else {
1930 /* looks like a basket case. give up.
1932 shutdown_pending = 1;
1933 child_fatal = 1;
1934 ap_log_error(APLOG_MARK, APLOG_ALERT, 0,
1935 ap_server_conf,
1936 "No active workers found..."
1937 " Apache is exiting!");
1938 /* the child already logged the failure details */
1939 return;
1943 ap_max_daemons_limit = last_non_dead + 1;
1945 if (idle_thread_count > max_spare_threads) {
1946 /* Kill off one child */
1947 ap_mpm_pod_signal(pod, TRUE);
1948 idle_spawn_rate = 1;
1950 else if (idle_thread_count < min_spare_threads) {
1951 /* terminate the free list */
1952 if (free_length == 0) { /* scoreboard is full, can't fork */
1954 if (active_thread_count >= ap_daemons_limit * ap_threads_per_child) {
1955 static int reported = 0;
1956 if (!reported) {
1957 /* only report this condition once */
1958 ap_log_error(APLOG_MARK, APLOG_ERR, 0,
1959 ap_server_conf,
1960 "server reached MaxClients setting, consider"
1961 " raising the MaxClients setting");
1962 reported = 1;
1965 else {
1966 ap_log_error(APLOG_MARK, APLOG_ERR, 0,
1967 ap_server_conf,
1968 "scoreboard is full, not at MaxClients");
1970 idle_spawn_rate = 1;
1972 else {
1973 if (free_length > idle_spawn_rate) {
1974 free_length = idle_spawn_rate;
1976 if (idle_spawn_rate >= 8) {
1977 ap_log_error(APLOG_MARK, APLOG_INFO, 0,
1978 ap_server_conf,
1979 "server seems busy, (you may need "
1980 "to increase StartServers, ThreadsPerChild "
1981 "or Min/MaxSpareThreads), "
1982 "spawning %d children, there are around %d idle "
1983 "threads, and %d total children", free_length,
1984 idle_thread_count, total_non_dead);
1986 for (i = 0; i < free_length; ++i) {
1987 make_child(ap_server_conf, free_slots[i]);
1989 /* the next time around we want to spawn twice as many if this
1990 * wasn't good enough, but not if we've just done a graceful
1992 if (hold_off_on_exponential_spawning) {
1993 --hold_off_on_exponential_spawning;
1995 else if (idle_spawn_rate < MAX_SPAWN_RATE) {
1996 idle_spawn_rate *= 2;
2000 else {
2001 idle_spawn_rate = 1;
2005 static void server_main_loop(int remaining_children_to_start)
2007 int child_slot;
2008 apr_exit_why_e exitwhy;
2009 int status, processed_status;
2010 apr_proc_t pid;
2011 int i;
2013 while (!restart_pending && !shutdown_pending) {
2014 ap_wait_or_timeout(&exitwhy, &status, &pid, pconf);
2016 if (pid.pid != -1) {
2017 processed_status = ap_process_child_status(&pid, exitwhy, status);
2018 if (processed_status == APEXIT_CHILDFATAL) {
2019 shutdown_pending = 1;
2020 child_fatal = 1;
2021 return;
2023 else if (processed_status == APEXIT_CHILDSICK) {
2024 /* tell perform_idle_server_maintenance to check into this
2025 * on the next timer pop
2027 sick_child_detected = 1;
2029 /* non-fatal death... note that it's gone in the scoreboard. */
2030 child_slot = ap_find_child_by_pid(&pid);
2031 if (child_slot >= 0) {
2032 for (i = 0; i < ap_threads_per_child; i++)
2033 ap_update_child_status_from_indexes(child_slot, i,
2034 SERVER_DEAD,
2035 (request_rec *) NULL);
2037 ap_scoreboard_image->parent[child_slot].pid = 0;
2038 ap_scoreboard_image->parent[child_slot].quiescing = 0;
2039 if (processed_status == APEXIT_CHILDSICK) {
2040 /* resource shortage, minimize the fork rate */
2041 idle_spawn_rate = 1;
2043 else if (remaining_children_to_start
2044 && child_slot < ap_daemons_limit) {
2045 /* we're still doing a 1-for-1 replacement of dead
2046 * children with new children
2048 make_child(ap_server_conf, child_slot);
2049 --remaining_children_to_start;
2052 else if (ap_unregister_extra_mpm_process(pid.pid) == 1) {
2053 /* handled */
2054 #if APR_HAS_OTHER_CHILD
2056 else if (apr_proc_other_child_alert(&pid, APR_OC_REASON_DEATH,
2057 status) == 0) {
2058 /* handled */
2059 #endif
2061 else if (is_graceful) {
2062 /* Great, we've probably just lost a slot in the
2063 * scoreboard. Somehow we don't know about this child.
2065 ap_log_error(APLOG_MARK, APLOG_WARNING, 0,
2066 ap_server_conf,
2067 "long lost child came home! (pid %ld)",
2068 (long) pid.pid);
2070 /* Don't perform idle maintenance when a child dies,
2071 * only do it when there's a timeout. Remember only a
2072 * finite number of children can die, and it's pretty
2073 * pathological for a lot to die suddenly.
2075 continue;
2077 else if (remaining_children_to_start) {
2078 /* we hit a 1 second timeout in which none of the previous
2079 * generation of children needed to be reaped... so assume
2080 * they're all done, and pick up the slack if any is left.
2082 startup_children(remaining_children_to_start);
2083 remaining_children_to_start = 0;
2084 /* In any event we really shouldn't do the code below because
2085 * few of the servers we just started are in the IDLE state
2086 * yet, so we'd mistakenly create an extra server.
2088 continue;
2091 perform_idle_server_maintenance();
2095 int ap_mpm_run(apr_pool_t * _pconf, apr_pool_t * plog, server_rec * s)
2097 int remaining_children_to_start;
2099 ap_log_pid(pconf, ap_pid_fname);
2101 if (!is_graceful) {
2102 if (ap_run_pre_mpm(s->process->pool, SB_SHARED) != OK) {
2103 mpm_state = AP_MPMQ_STOPPING;
2104 return 1;
2106 /* fix the generation number in the global score; we just got a new,
2107 * cleared scoreboard
2109 ap_scoreboard_image->global->running_generation = ap_my_generation;
2112 set_signals();
2113 /* Don't thrash... */
2114 if (max_spare_threads < min_spare_threads + ap_threads_per_child)
2115 max_spare_threads = min_spare_threads + ap_threads_per_child;
2117 /* If we're doing a graceful_restart then we're going to see a lot
2118 * of children exiting immediately when we get into the main loop
2119 * below (because we just sent them AP_SIG_GRACEFUL). This happens pretty
2120 * rapidly... and for each one that exits we may start a new one, until
2121 * there are at least min_spare_threads idle threads, counting across
2122 * all children. But we may be permitted to start more children than
2123 * that, so we'll just keep track of how many we're
2124 * supposed to start up without the 1 second penalty between each fork.
2126 remaining_children_to_start = ap_daemons_to_start;
2127 if (remaining_children_to_start > ap_daemons_limit) {
2128 remaining_children_to_start = ap_daemons_limit;
2130 if (!is_graceful) {
2131 startup_children(remaining_children_to_start);
2132 remaining_children_to_start = 0;
2134 else {
2135 /* give the system some time to recover before kicking into
2136 * exponential mode */
2137 hold_off_on_exponential_spawning = 10;
2140 ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
2141 "%s configured -- resuming normal operations",
2142 ap_get_server_description());
2143 ap_log_error(APLOG_MARK, APLOG_INFO, 0, ap_server_conf,
2144 "Server built: %s", ap_get_server_built());
2146 restart_pending = shutdown_pending = 0;
2147 mpm_state = AP_MPMQ_RUNNING;
2149 server_main_loop(remaining_children_to_start);
2150 mpm_state = AP_MPMQ_STOPPING;
2152 if (shutdown_pending && !is_graceful) {
2153 /* Time to shut down:
2154 * Kill child processes, tell them to call child_exit, etc...
2156 ap_mpm_pod_killpg(pod, ap_daemons_limit, FALSE);
2157 ap_reclaim_child_processes(1); /* Start with SIGTERM */
2159 if (!child_fatal) {
2160 /* cleanup pid file on normal shutdown */
2161 const char *pidfile = NULL;
2162 pidfile = ap_server_root_relative(pconf, ap_pid_fname);
2163 if (pidfile != NULL && unlink(pidfile) == 0)
2164 ap_log_error(APLOG_MARK, APLOG_INFO, 0,
2165 ap_server_conf,
2166 "removed PID file %s (pid=%ld)",
2167 pidfile, (long) getpid());
2169 ap_log_error(APLOG_MARK, APLOG_NOTICE, 0,
2170 ap_server_conf, "caught SIGTERM, shutting down");
2172 return 1;
2173 } else if (shutdown_pending) {
2174 /* Time to gracefully shut down:
2175 * Kill child processes, tell them to call child_exit, etc...
2177 int active_children;
2178 int index;
2179 apr_time_t cutoff = 0;
2181 /* Close our listeners, and then ask our children to do same */
2182 ap_close_listeners();
2183 ap_mpm_pod_killpg(pod, ap_daemons_limit, TRUE);
2184 ap_relieve_child_processes();
2186 if (!child_fatal) {
2187 /* cleanup pid file on normal shutdown */
2188 const char *pidfile = NULL;
2189 pidfile = ap_server_root_relative (pconf, ap_pid_fname);
2190 if ( pidfile != NULL && unlink(pidfile) == 0)
2191 ap_log_error(APLOG_MARK, APLOG_INFO, 0,
2192 ap_server_conf,
2193 "removed PID file %s (pid=%ld)",
2194 pidfile, (long)getpid());
2196 ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
2197 "caught " AP_SIG_GRACEFUL_STOP_STRING
2198 ", shutting down gracefully");
2201 if (ap_graceful_shutdown_timeout) {
2202 cutoff = apr_time_now() +
2203 apr_time_from_sec(ap_graceful_shutdown_timeout);
2206 /* Don't really exit until each child has finished */
2207 shutdown_pending = 0;
2208 do {
2209 /* Pause for a second */
2210 apr_sleep(apr_time_from_sec(1));
2212 /* Relieve any children which have now exited */
2213 ap_relieve_child_processes();
2215 active_children = 0;
2216 for (index = 0; index < ap_daemons_limit; ++index) {
2217 if (ap_mpm_safe_kill(MPM_CHILD_PID(index), 0) == APR_SUCCESS) {
2218 active_children = 1;
2219 /* Having just one child is enough to stay around */
2220 break;
2223 } while (!shutdown_pending && active_children &&
2224 (!ap_graceful_shutdown_timeout || apr_time_now() < cutoff));
2226 /* We might be here because we received SIGTERM, either
2227 * way, try and make sure that all of our processes are
2228 * really dead.
2230 ap_mpm_pod_killpg(pod, ap_daemons_limit, FALSE);
2231 ap_reclaim_child_processes(1);
2233 return 1;
2236 /* we've been told to restart */
2237 apr_signal(SIGHUP, SIG_IGN);
2239 if (one_process) {
2240 /* not worth thinking about */
2241 return 1;
2244 /* advance to the next generation */
2245 /* XXX: we really need to make sure this new generation number isn't in
2246 * use by any of the children.
2248 ++ap_my_generation;
2249 ap_scoreboard_image->global->running_generation = ap_my_generation;
2251 if (is_graceful) {
2252 ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
2253 AP_SIG_GRACEFUL_STRING
2254 " received. Doing graceful restart");
2255 /* wake up the children...time to die. But we'll have more soon */
2256 ap_mpm_pod_killpg(pod, ap_daemons_limit, TRUE);
2259 /* This is mostly for debugging... so that we know what is still
2260 * gracefully dealing with existing request.
2264 else {
2265 /* Kill 'em all. Since the child acts the same on the parents SIGTERM
2266 * and a SIGHUP, we may as well use the same signal, because some user
2267 * pthreads are stealing signals from us left and right.
2269 ap_mpm_pod_killpg(pod, ap_daemons_limit, FALSE);
2271 ap_reclaim_child_processes(1); /* Start with SIGTERM */
2272 ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
2273 "SIGHUP received. Attempting to restart");
2276 return 0;
2279 /* This really should be a post_config hook, but the error log is already
2280 * redirected by that point, so we need to do this in the open_logs phase.
2282 static int event_open_logs(apr_pool_t * p, apr_pool_t * plog,
2283 apr_pool_t * ptemp, server_rec * s)
2285 static int restart_num = 0;
2286 int startup = 0;
2287 int level_flags = 0;
2288 apr_status_t rv;
2290 pconf = p;
2291 ap_server_conf = s;
2293 /* the reverse of pre_config, we want this only the first time around */
2294 if (restart_num++ == 0) {
2295 startup = 1;
2296 level_flags |= APLOG_STARTUP;
2299 if ((num_listensocks = ap_setup_listeners(ap_server_conf)) < 1) {
2300 ap_log_error(APLOG_MARK, APLOG_ALERT | level_flags, 0,
2301 (startup ? NULL : s),
2302 "no listening sockets available, shutting down");
2303 return DONE;
2306 if (!one_process) {
2307 if ((rv = ap_mpm_pod_open(pconf, &pod))) {
2308 ap_log_error(APLOG_MARK, APLOG_CRIT | level_flags, rv,
2309 (startup ? NULL : s),
2310 "could not open pipe-of-death");
2311 return DONE;
2314 return OK;
2317 static int event_pre_config(apr_pool_t * pconf, apr_pool_t * plog,
2318 apr_pool_t * ptemp)
2320 static int restart_num = 0;
2321 int no_detach, debug, foreground;
2322 apr_status_t rv;
2324 mpm_state = AP_MPMQ_STARTING;
2326 debug = ap_exists_config_define("DEBUG");
2328 if (debug) {
2329 foreground = one_process = 1;
2330 no_detach = 0;
2332 else {
2333 one_process = ap_exists_config_define("ONE_PROCESS");
2334 no_detach = ap_exists_config_define("NO_DETACH");
2335 foreground = ap_exists_config_define("FOREGROUND");
2338 /* sigh, want this only the second time around */
2339 if (restart_num++ == 1) {
2340 is_graceful = 0;
2341 rv = apr_pollset_create(&event_pollset, 1, plog,
2342 APR_POLLSET_THREADSAFE | APR_POLLSET_NOCOPY);
2343 if (rv != APR_SUCCESS) {
2344 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL,
2345 "Couldn't create a Thread Safe Pollset. "
2346 "Is it supported on your platform?");
2347 return HTTP_INTERNAL_SERVER_ERROR;
2349 apr_pollset_destroy(event_pollset);
2351 if (!one_process && !foreground) {
2352 rv = apr_proc_detach(no_detach ? APR_PROC_DETACH_FOREGROUND
2353 : APR_PROC_DETACH_DAEMONIZE);
2354 if (rv != APR_SUCCESS) {
2355 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL,
2356 "apr_proc_detach failed");
2357 return HTTP_INTERNAL_SERVER_ERROR;
2360 parent_pid = ap_my_pid = getpid();
2363 ap_listen_pre_config();
2364 ap_daemons_to_start = DEFAULT_START_DAEMON;
2365 min_spare_threads = DEFAULT_MIN_FREE_DAEMON * DEFAULT_THREADS_PER_CHILD;
2366 max_spare_threads = DEFAULT_MAX_FREE_DAEMON * DEFAULT_THREADS_PER_CHILD;
2367 server_limit = DEFAULT_SERVER_LIMIT;
2368 thread_limit = DEFAULT_THREAD_LIMIT;
2369 ap_daemons_limit = server_limit;
2370 ap_threads_per_child = DEFAULT_THREADS_PER_CHILD;
2371 max_clients = ap_daemons_limit * ap_threads_per_child;
2372 ap_pid_fname = DEFAULT_PIDLOG;
2373 ap_lock_fname = DEFAULT_LOCKFILE;
2374 ap_max_requests_per_child = DEFAULT_MAX_REQUESTS_PER_CHILD;
2375 ap_extended_status = 0;
2376 #ifdef AP_MPM_WANT_SET_MAX_MEM_FREE
2377 ap_max_mem_free = APR_ALLOCATOR_MAX_FREE_UNLIMITED;
2378 #endif
2380 apr_cpystrn(ap_coredump_dir, ap_server_root, sizeof(ap_coredump_dir));
2382 return OK;
2385 static int event_check_config(apr_pool_t *p, apr_pool_t *plog,
2386 apr_pool_t *ptemp, server_rec *s)
2388 static int restart_num = 0;
2389 int startup = 0;
2391 /* the reverse of pre_config, we want this only the first time around */
2392 if (restart_num++ == 0) {
2393 startup = 1;
2396 if (server_limit > MAX_SERVER_LIMIT) {
2397 if (startup) {
2398 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2399 "WARNING: ServerLimit of %d exceeds compile-time "
2400 "limit of", server_limit);
2401 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2402 " %d servers, decreasing to %d.",
2403 MAX_SERVER_LIMIT, MAX_SERVER_LIMIT);
2404 } else {
2405 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
2406 "ServerLimit of %d exceeds compile-time limit "
2407 "of %d, decreasing to match",
2408 server_limit, MAX_SERVER_LIMIT);
2410 server_limit = MAX_SERVER_LIMIT;
2412 else if (server_limit < 1) {
2413 if (startup) {
2414 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2415 "WARNING: ServerLimit of %d not allowed, "
2416 "increasing to 1.", server_limit);
2417 } else {
2418 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
2419 "ServerLimit of %d not allowed, increasing to 1",
2420 server_limit);
2422 server_limit = 1;
2425 /* you cannot change ServerLimit across a restart; ignore
2426 * any such attempts
2428 if (!first_server_limit) {
2429 first_server_limit = server_limit;
2431 else if (server_limit != first_server_limit) {
2432 /* don't need a startup console version here */
2433 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
2434 "changing ServerLimit to %d from original value of %d "
2435 "not allowed during restart",
2436 server_limit, first_server_limit);
2437 server_limit = first_server_limit;
2440 if (thread_limit > MAX_THREAD_LIMIT) {
2441 if (startup) {
2442 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2443 "WARNING: ThreadLimit of %d exceeds compile-time "
2444 "limit of", thread_limit);
2445 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2446 " %d threads, decreasing to %d.",
2447 MAX_THREAD_LIMIT, MAX_THREAD_LIMIT);
2448 } else {
2449 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
2450 "ThreadLimit of %d exceeds compile-time limit "
2451 "of %d, decreasing to match",
2452 thread_limit, MAX_THREAD_LIMIT);
2454 thread_limit = MAX_THREAD_LIMIT;
2456 else if (thread_limit < 1) {
2457 if (startup) {
2458 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2459 "WARNING: ThreadLimit of %d not allowed, "
2460 "increasing to 1.", thread_limit);
2461 } else {
2462 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
2463 "ThreadLimit of %d not allowed, increasing to 1",
2464 thread_limit);
2466 thread_limit = 1;
2469 /* you cannot change ThreadLimit across a restart; ignore
2470 * any such attempts
2472 if (!first_thread_limit) {
2473 first_thread_limit = thread_limit;
2475 else if (thread_limit != first_thread_limit) {
2476 /* don't need a startup console version here */
2477 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
2478 "changing ThreadLimit to %d from original value of %d "
2479 "not allowed during restart",
2480 thread_limit, first_thread_limit);
2481 thread_limit = first_thread_limit;
2484 if (ap_threads_per_child > thread_limit) {
2485 if (startup) {
2486 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2487 "WARNING: ThreadsPerChild of %d exceeds ThreadLimit "
2488 "of", ap_threads_per_child);
2489 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2490 " %d threads, decreasing to %d.",
2491 thread_limit, thread_limit);
2492 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2493 " To increase, please see the ThreadLimit "
2494 "directive.");
2495 } else {
2496 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
2497 "ThreadsPerChild of %d exceeds ThreadLimit "
2498 "of %d, decreasing to match",
2499 ap_threads_per_child, thread_limit);
2501 ap_threads_per_child = thread_limit;
2503 else if (ap_threads_per_child < 1) {
2504 if (startup) {
2505 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2506 "WARNING: ThreadsPerChild of %d not allowed, "
2507 "increasing to 1.", ap_threads_per_child);
2508 } else {
2509 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
2510 "ThreadsPerChild of %d not allowed, increasing to 1",
2511 ap_threads_per_child);
2513 ap_threads_per_child = 1;
2516 if (max_clients < ap_threads_per_child) {
2517 if (startup) {
2518 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2519 "WARNING: MaxClients of %d is less than "
2520 "ThreadsPerChild of", max_clients);
2521 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2522 " %d, increasing to %d. MaxClients must be at "
2523 "least as large",
2524 ap_threads_per_child, ap_threads_per_child);
2525 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2526 " as the number of threads in a single server.");
2527 } else {
2528 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
2529 "MaxClients of %d is less than ThreadsPerChild "
2530 "of %d, increasing to match",
2531 max_clients, ap_threads_per_child);
2533 max_clients = ap_threads_per_child;
2536 ap_daemons_limit = max_clients / ap_threads_per_child;
2538 if (max_clients % ap_threads_per_child) {
2539 int tmp_max_clients = ap_daemons_limit * ap_threads_per_child;
2541 if (startup) {
2542 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2543 "WARNING: MaxClients of %d is not an integer "
2544 "multiple of", max_clients);
2545 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2546 " ThreadsPerChild of %d, decreasing to nearest "
2547 "multiple %d,", ap_threads_per_child,
2548 tmp_max_clients);
2549 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2550 " for a maximum of %d servers.",
2551 ap_daemons_limit);
2552 } else {
2553 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
2554 "MaxClients of %d is not an integer multiple of "
2555 "ThreadsPerChild of %d, decreasing to nearest "
2556 "multiple %d", max_clients, ap_threads_per_child,
2557 tmp_max_clients);
2559 max_clients = tmp_max_clients;
2562 if (ap_daemons_limit > server_limit) {
2563 if (startup) {
2564 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2565 "WARNING: MaxClients of %d would require %d "
2566 "servers and ", max_clients, ap_daemons_limit);
2567 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2568 " would exceed ServerLimit of %d, decreasing to %d.",
2569 server_limit, server_limit * ap_threads_per_child);
2570 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2571 " To increase, please see the ServerLimit "
2572 "directive.");
2573 } else {
2574 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
2575 "MaxClients of %d would require %d servers and "
2576 "exceed ServerLimit of %d, decreasing to %d",
2577 max_clients, ap_daemons_limit, server_limit,
2578 server_limit * ap_threads_per_child);
2580 ap_daemons_limit = server_limit;
2583 /* ap_daemons_to_start > ap_daemons_limit checked in ap_mpm_run() */
2584 if (ap_daemons_to_start < 0) {
2585 if (startup) {
2586 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2587 "WARNING: StartServers of %d not allowed, "
2588 "increasing to 1.", ap_daemons_to_start);
2589 } else {
2590 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
2591 "StartServers of %d not allowed, increasing to 1",
2592 ap_daemons_to_start);
2594 ap_daemons_to_start = 1;
2597 if (min_spare_threads < 1) {
2598 if (startup) {
2599 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2600 "WARNING: MinSpareThreads of %d not allowed, "
2601 "increasing to 1", min_spare_threads);
2602 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2603 " to avoid almost certain server failure.");
2604 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2605 " Please read the documentation.");
2606 } else {
2607 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
2608 "MinSpareThreads of %d not allowed, increasing to 1",
2609 min_spare_threads);
2611 min_spare_threads = 1;
2614 /* max_spare_threads < min_spare_threads + ap_threads_per_child
2615 * checked in ap_mpm_run()
2618 return OK;
2621 static void event_hooks(apr_pool_t * p)
2623 /* Our open_logs hook function must run before the core's, or stderr
2624 * will be redirected to a file, and the messages won't print to the
2625 * console.
2627 static const char *const aszSucc[] = { "core.c", NULL };
2628 one_process = 0;
2630 ap_hook_open_logs(event_open_logs, NULL, aszSucc, APR_HOOK_REALLY_FIRST);
2631 /* we need to set the MPM state before other pre-config hooks use MPM query
2632 * to retrieve it, so register as REALLY_FIRST
2634 ap_hook_pre_config(event_pre_config, NULL, NULL, APR_HOOK_REALLY_FIRST);
2635 ap_hook_check_config(event_check_config, NULL, NULL, APR_HOOK_MIDDLE);
2638 static const char *set_daemons_to_start(cmd_parms *cmd, void *dummy,
2639 const char *arg)
2641 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
2642 if (err != NULL) {
2643 return err;
2646 ap_daemons_to_start = atoi(arg);
2647 return NULL;
2650 static const char *set_min_spare_threads(cmd_parms * cmd, void *dummy,
2651 const char *arg)
2653 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
2654 if (err != NULL) {
2655 return err;
2658 min_spare_threads = atoi(arg);
2659 return NULL;
2662 static const char *set_max_spare_threads(cmd_parms * cmd, void *dummy,
2663 const char *arg)
2665 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
2666 if (err != NULL) {
2667 return err;
2670 max_spare_threads = atoi(arg);
2671 return NULL;
2674 static const char *set_max_clients(cmd_parms * cmd, void *dummy,
2675 const char *arg)
2677 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
2678 if (err != NULL) {
2679 return err;
2682 max_clients = atoi(arg);
2683 return NULL;
2686 static const char *set_threads_per_child(cmd_parms * cmd, void *dummy,
2687 const char *arg)
2689 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
2690 if (err != NULL) {
2691 return err;
2694 ap_threads_per_child = atoi(arg);
2695 return NULL;
2697 static const char *set_server_limit (cmd_parms *cmd, void *dummy, const char *arg)
2699 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
2700 if (err != NULL) {
2701 return err;
2704 server_limit = atoi(arg);
2705 return NULL;
2708 static const char *set_thread_limit(cmd_parms * cmd, void *dummy,
2709 const char *arg)
2711 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
2712 if (err != NULL) {
2713 return err;
2716 thread_limit = atoi(arg);
2717 return NULL;
2720 static const command_rec event_cmds[] = {
2721 LISTEN_COMMANDS,
2722 AP_INIT_TAKE1("StartServers", set_daemons_to_start, NULL, RSRC_CONF,
2723 "Number of child processes launched at server startup"),
2724 AP_INIT_TAKE1("ServerLimit", set_server_limit, NULL, RSRC_CONF,
2725 "Maximum number of child processes for this run of Apache"),
2726 AP_INIT_TAKE1("MinSpareThreads", set_min_spare_threads, NULL, RSRC_CONF,
2727 "Minimum number of idle threads, to handle request spikes"),
2728 AP_INIT_TAKE1("MaxSpareThreads", set_max_spare_threads, NULL, RSRC_CONF,
2729 "Maximum number of idle threads"),
2730 AP_INIT_TAKE1("MaxClients", set_max_clients, NULL, RSRC_CONF,
2731 "Maximum number of threads alive at the same time"),
2732 AP_INIT_TAKE1("ThreadsPerChild", set_threads_per_child, NULL, RSRC_CONF,
2733 "Number of threads each child creates"),
2734 AP_INIT_TAKE1("ThreadLimit", set_thread_limit, NULL, RSRC_CONF,
2735 "Maximum number of worker threads per child process for this "
2736 "run of Apache - Upper limit for ThreadsPerChild"),
2737 AP_GRACEFUL_SHUTDOWN_TIMEOUT_COMMAND,
2738 {NULL}
2741 module AP_MODULE_DECLARE_DATA mpm_event_module = {
2742 MPM20_MODULE_STUFF,
2743 ap_mpm_rewrite_args, /* hook to run before apache parses args */
2744 NULL, /* create per-directory config structure */
2745 NULL, /* merge per-directory config structures */
2746 NULL, /* create per-server config structure */
2747 NULL, /* merge per-server config structures */
2748 event_cmds, /* command apr_table_t */
2749 event_hooks /* register_hooks */