]> granicus.if.org Git - apache/blob - server/mpm/event/event.c
38b70dee5a9b05a979cd9368dabe68d2d1f153ad
[apache] / server / mpm / event / event.c
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
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 /**
18  * This MPM tries to fix the 'keep alive problem' in HTTP.
19  *
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.
27  *
28  * The MPM assumes the underlying apr_pollset implementation is somewhat
29  * threadsafe.  This currently is only compatible with KQueue and EPoll.  This
30  * enables the MPM to avoid extra high level locking or having to wake up the
31  * listener thread when a keep-alive socket needs to be sent to it.
32  *
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.
36  *
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`).
39  *
40  * For NetBSD, use at least 2.0.
41  *
42  * For Linux, you should use a 2.6 kernel, and make sure your glibc has epoll
43  * support compiled in.
44  *
45  */
46
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_poll.h"
55 #include "apr_ring.h"
56 #include "apr_queue.h"
57 #include "apr_atomic.h"
58 #define APR_WANT_STRFUNC
59 #include "apr_want.h"
60 #include "apr_version.h"
61
62 #if APR_HAVE_UNISTD_H
63 #include <unistd.h>
64 #endif
65 #if APR_HAVE_SYS_SOCKET_H
66 #include <sys/socket.h>
67 #endif
68 #if APR_HAVE_SYS_WAIT_H
69 #include <sys/wait.h>
70 #endif
71 #ifdef HAVE_SYS_PROCESSOR_H
72 #include <sys/processor.h>      /* for bindprocessor() */
73 #endif
74
75 #if !APR_HAS_THREADS
76 #error The Event MPM requires APR threads, but they are unavailable.
77 #endif
78
79 #include "ap_config.h"
80 #include "httpd.h"
81 #include "http_main.h"
82 #include "http_log.h"
83 #include "http_config.h"        /* for read_config */
84 #include "http_core.h"          /* for get_remote_host */
85 #include "http_connection.h"
86 #include "ap_mpm.h"
87 #include "pod.h"
88 #include "mpm_common.h"
89 #include "ap_listen.h"
90 #include "scoreboard.h"
91 #include "fdqueue.h"
92 #include "mpm_default.h"
93 #include "http_vhost.h"
94 #include "unixd.h"
95
96 #include <signal.h>
97 #include <limits.h>             /* for INT_MAX */
98
99
100 #if HAVE_SERF
101 #include "mod_serf.h"
102 #include "serf.h"
103 #endif
104
105 /* Limit on the total --- clients will be locked out if more servers than
106  * this are needed.  It is intended solely to keep the server from crashing
107  * when things get out of hand.
108  *
109  * We keep a hard maximum number of servers, for two reasons --- first off,
110  * in case something goes seriously wrong, we want to stop the fork bomb
111  * short of actually crashing the machine we're running on by filling some
112  * kernel table.  Secondly, it keeps the size of the scoreboard file small
113  * enough that we can read the whole thing without worrying too much about
114  * the overhead.
115  */
116 #ifndef DEFAULT_SERVER_LIMIT
117 #define DEFAULT_SERVER_LIMIT 16
118 #endif
119
120 /* Admin can't tune ServerLimit beyond MAX_SERVER_LIMIT.  We want
121  * some sort of compile-time limit to help catch typos.
122  */
123 #ifndef MAX_SERVER_LIMIT
124 #define MAX_SERVER_LIMIT 20000
125 #endif
126
127 /* Limit on the threads per process.  Clients will be locked out if more than
128  * this are needed.
129  *
130  * We keep this for one reason it keeps the size of the scoreboard file small
131  * enough that we can read the whole thing without worrying too much about
132  * the overhead.
133  */
134 #ifndef DEFAULT_THREAD_LIMIT
135 #define DEFAULT_THREAD_LIMIT 64
136 #endif
137
138 /* Admin can't tune ThreadLimit beyond MAX_THREAD_LIMIT.  We want
139  * some sort of compile-time limit to help catch typos.
140  */
141 #ifndef MAX_THREAD_LIMIT
142 #define MAX_THREAD_LIMIT 100000
143 #endif
144
145 #define MPM_CHILD_PID(i) (ap_scoreboard_image->parent[i].pid)
146
147 #if !APR_VERSION_AT_LEAST(1,4,0)
148 #define apr_time_from_msec(x) (x * 1000)
149 #endif
150
151 #ifndef MAX_SECS_TO_LINGER
152 #define MAX_SECS_TO_LINGER 30
153 #endif
154 #define SECONDS_TO_LINGER  2
155
156 /*
157  * Actual definitions of config globals
158  */
159
160 #ifndef DEFAULT_WORKER_FACTOR
161 #define DEFAULT_WORKER_FACTOR 2
162 #endif
163 #define WORKER_FACTOR_SCALE   16  /* scale factor to allow fractional values */
164 static unsigned int worker_factor = DEFAULT_WORKER_FACTOR * WORKER_FACTOR_SCALE;
165
166 static int threads_per_child = 0;   /* Worker threads per child */
167 static int ap_daemons_to_start = 0;
168 static int min_spare_threads = 0;
169 static int max_spare_threads = 0;
170 static int ap_daemons_limit = 0;
171 static int max_workers = 0;
172 static int server_limit = 0;
173 static int thread_limit = 0;
174 static int dying = 0;
175 static int workers_may_exit = 0;
176 static int start_thread_may_exit = 0;
177 static int listener_may_exit = 0;
178 static int requests_this_child;
179 static int num_listensocks = 0;
180 static apr_uint32_t connection_count = 0;
181 static int resource_shortage = 0;
182 static fd_queue_t *worker_queue;
183 static fd_queue_info_t *worker_queue_info;
184 static int mpm_state = AP_MPMQ_STARTING;
185
186 static apr_thread_mutex_t *timeout_mutex;
187 APR_RING_HEAD(timeout_head_t, conn_state_t);
188 struct timeout_queue {
189     struct timeout_head_t head;
190     int count;
191     const char *tag;
192 };
193 static struct timeout_queue write_completion_q, keepalive_q, linger_q,
194                             short_linger_q;
195 static apr_pollfd_t *listener_pollfd;
196
197 /*
198  * Macros for accessing struct timeout_queue.
199  * For TO_QUEUE_APPEND and TO_QUEUE_REMOVE, timeout_mutex must be held.
200  */
201 #define TO_QUEUE_APPEND(q, el)                                            \
202     do {                                                                  \
203         APR_RING_INSERT_TAIL(&(q).head, el, conn_state_t, timeout_list);  \
204         (q).count++;                                                      \
205     } while (0)
206
207 #define TO_QUEUE_REMOVE(q, el)             \
208     do {                                   \
209         APR_RING_REMOVE(el, timeout_list); \
210         (q).count--;                       \
211     } while (0)
212
213 #define TO_QUEUE_INIT(q)                                            \
214     do {                                                            \
215             APR_RING_INIT(&(q).head, conn_state_t, timeout_list);   \
216             (q).tag = #q;                                           \
217     } while (0)
218
219 #define TO_QUEUE_ELEM_INIT(el) APR_RING_ELEM_INIT(el, timeout_list)
220
221 static apr_pollset_t *event_pollset;
222
223 #if HAVE_SERF
224 typedef struct {
225     apr_pollset_t *pollset;
226     apr_pool_t *pool;
227 } s_baton_t;
228
229 static serf_context_t *g_serf;
230 #endif
231
232 /* The structure used to pass unique initialization info to each thread */
233 typedef struct
234 {
235     int pid;
236     int tid;
237     int sd;
238 } proc_info;
239
240 /* Structure used to pass information to the thread responsible for
241  * creating the rest of the threads.
242  */
243 typedef struct
244 {
245     apr_thread_t **threads;
246     apr_thread_t *listener;
247     int child_num_arg;
248     apr_threadattr_t *threadattr;
249 } thread_starter;
250
251 typedef enum
252 {
253     PT_CSD,
254     PT_ACCEPT
255 #if HAVE_SERF
256     , PT_SERF
257 #endif
258 } poll_type_e;
259
260 typedef struct
261 {
262     poll_type_e type;
263     void *baton;
264 } listener_poll_type;
265
266 /* data retained by event across load/unload of the module
267  * allocated on first call to pre-config hook; located on
268  * subsequent calls to pre-config hook
269  */
270 typedef struct event_retained_data {
271     int first_server_limit;
272     int first_thread_limit;
273     int module_loads;
274     int sick_child_detected;
275     ap_generation_t my_generation;
276     int volatile is_graceful; /* set from signal handler */
277     int maxclients_reported;
278     /*
279      * The max child slot ever assigned, preserved across restarts.  Necessary
280      * to deal with MaxRequestWorkers changes across AP_SIG_GRACEFUL restarts.
281      * We use this value to optimize routines that have to scan the entire
282      * scoreboard.
283      */
284     int max_daemons_limit;
285     /*
286      * idle_spawn_rate is the number of children that will be spawned on the
287      * next maintenance cycle if there aren't enough idle servers.  It is
288      * doubled up to MAX_SPAWN_RATE, and reset only when a cycle goes by
289      * without the need to spawn.
290      */
291     int idle_spawn_rate;
292 #ifndef MAX_SPAWN_RATE
293 #define MAX_SPAWN_RATE        (32)
294 #endif
295     int hold_off_on_exponential_spawning;
296 } event_retained_data;
297 static event_retained_data *retained;
298
299 #define ID_FROM_CHILD_THREAD(c, t)    ((c * thread_limit) + t)
300
301 static ap_event_pod_t *pod;
302
303 /* The event MPM respects a couple of runtime flags that can aid
304  * in debugging. Setting the -DNO_DETACH flag will prevent the root process
305  * from detaching from its controlling terminal. Additionally, setting
306  * the -DONE_PROCESS flag (which implies -DNO_DETACH) will get you the
307  * child_main loop running in the process which originally started up.
308  * This gives you a pretty nice debugging environment.  (You'll get a SIGHUP
309  * early in standalone_main; just continue through.  This is the server
310  * trying to kill off any child processes which it might have lying
311  * around --- Apache doesn't keep track of their pids, it just sends
312  * SIGHUP to the process group, ignoring it in the root process.
313  * Continue through and you'll be fine.).
314  */
315
316 static int one_process = 0;
317
318 #ifdef DEBUG_SIGSTOP
319 int raise_sigstop_flags;
320 #endif
321
322 static apr_pool_t *pconf;       /* Pool for config stuff */
323 static apr_pool_t *pchild;      /* Pool for httpd child stuff */
324
325 static pid_t ap_my_pid;         /* Linux getpid() doesn't work except in main
326                                    thread. Use this instead */
327 static pid_t parent_pid;
328 static apr_os_thread_t *listener_os_thread;
329
330 /* The LISTENER_SIGNAL signal will be sent from the main thread to the
331  * listener thread to wake it up for graceful termination (what a child
332  * process from an old generation does when the admin does "apachectl
333  * graceful").  This signal will be blocked in all threads of a child
334  * process except for the listener thread.
335  */
336 #define LISTENER_SIGNAL     SIGHUP
337
338 /* An array of socket descriptors in use by each thread used to
339  * perform a non-graceful (forced) shutdown of the server.
340  */
341 static apr_socket_t **worker_sockets;
342
343 static void disable_listensocks(int process_slot)
344 {
345     int i;
346     for (i = 0; i < num_listensocks; i++) {
347         apr_pollset_remove(event_pollset, &listener_pollfd[i]);
348     }
349     ap_scoreboard_image->parent[process_slot].not_accepting = 1;
350 }
351
352 static void enable_listensocks(int process_slot)
353 {
354     int i;
355     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
356                  "Accepting new connections again: "
357                  "%u active conns, %u idle workers",
358                  apr_atomic_read32(&connection_count),
359                  ap_queue_info_get_idlers(worker_queue_info));
360     for (i = 0; i < num_listensocks; i++)
361         apr_pollset_add(event_pollset, &listener_pollfd[i]);
362     /*
363      * XXX: This is not yet optimal. If many workers suddenly become available,
364      * XXX: the parent may kill some processes off too soon.
365      */
366     ap_scoreboard_image->parent[process_slot].not_accepting = 0;
367 }
368
369 static void close_worker_sockets(void)
370 {
371     int i;
372     for (i = 0; i < threads_per_child; i++) {
373         if (worker_sockets[i]) {
374             apr_socket_close(worker_sockets[i]);
375             worker_sockets[i] = NULL;
376         }
377     }
378 }
379
380 static void wakeup_listener(void)
381 {
382     listener_may_exit = 1;
383     if (!listener_os_thread) {
384         /* XXX there is an obscure path that this doesn't handle perfectly:
385          *     right after listener thread is created but before
386          *     listener_os_thread is set, the first worker thread hits an
387          *     error and starts graceful termination
388          */
389         return;
390     }
391
392     /* unblock the listener if it's waiting for a worker */
393     ap_queue_info_term(worker_queue_info);
394
395     /*
396      * we should just be able to "kill(ap_my_pid, LISTENER_SIGNAL)" on all
397      * platforms and wake up the listener thread since it is the only thread
398      * with SIGHUP unblocked, but that doesn't work on Linux
399      */
400 #ifdef HAVE_PTHREAD_KILL
401     pthread_kill(*listener_os_thread, LISTENER_SIGNAL);
402 #else
403     kill(ap_my_pid, LISTENER_SIGNAL);
404 #endif
405 }
406
407 #define ST_INIT              0
408 #define ST_GRACEFUL          1
409 #define ST_UNGRACEFUL        2
410
411 static int terminate_mode = ST_INIT;
412
413 static void signal_threads(int mode)
414 {
415     if (terminate_mode == mode) {
416         return;
417     }
418     terminate_mode = mode;
419     mpm_state = AP_MPMQ_STOPPING;
420
421     /* in case we weren't called from the listener thread, wake up the
422      * listener thread
423      */
424     wakeup_listener();
425
426     /* for ungraceful termination, let the workers exit now;
427      * for graceful termination, the listener thread will notify the
428      * workers to exit once it has stopped accepting new connections
429      */
430     if (mode == ST_UNGRACEFUL) {
431         workers_may_exit = 1;
432         ap_queue_interrupt_all(worker_queue);
433         close_worker_sockets(); /* forcefully kill all current connections */
434     }
435 }
436
437 static int event_query(int query_code, int *result, apr_status_t *rv)
438 {
439     *rv = APR_SUCCESS;
440     switch (query_code) {
441     case AP_MPMQ_MAX_DAEMON_USED:
442         *result = retained->max_daemons_limit;
443         break;
444     case AP_MPMQ_IS_THREADED:
445         *result = AP_MPMQ_STATIC;
446         break;
447     case AP_MPMQ_IS_FORKED:
448         *result = AP_MPMQ_DYNAMIC;
449         break;
450     case AP_MPMQ_IS_ASYNC:
451         *result = 1;
452         break;
453     case AP_MPMQ_HAS_SERF:
454         *result = 1;
455         break;
456     case AP_MPMQ_HARD_LIMIT_DAEMONS:
457         *result = server_limit;
458         break;
459     case AP_MPMQ_HARD_LIMIT_THREADS:
460         *result = thread_limit;
461         break;
462     case AP_MPMQ_MAX_THREADS:
463         *result = threads_per_child;
464         break;
465     case AP_MPMQ_MIN_SPARE_DAEMONS:
466         *result = 0;
467         break;
468     case AP_MPMQ_MIN_SPARE_THREADS:
469         *result = min_spare_threads;
470         break;
471     case AP_MPMQ_MAX_SPARE_DAEMONS:
472         *result = 0;
473         break;
474     case AP_MPMQ_MAX_SPARE_THREADS:
475         *result = max_spare_threads;
476         break;
477     case AP_MPMQ_MAX_REQUESTS_DAEMON:
478         *result = ap_max_requests_per_child;
479         break;
480     case AP_MPMQ_MAX_DAEMONS:
481         *result = ap_daemons_limit;
482         break;
483     case AP_MPMQ_MPM_STATE:
484         *result = mpm_state;
485         break;
486     case AP_MPMQ_GENERATION:
487         *result = retained->my_generation;
488         break;
489     default:
490         *rv = APR_ENOTIMPL;
491         break;
492     }
493     return OK;
494 }
495
496 static void event_note_child_killed(int childnum, pid_t pid, ap_generation_t gen)
497 {
498     if (childnum != -1) { /* child had a scoreboard slot? */
499         ap_run_child_status(ap_server_conf,
500                             ap_scoreboard_image->parent[childnum].pid,
501                             ap_scoreboard_image->parent[childnum].generation,
502                             childnum, MPM_CHILD_EXITED);
503         ap_scoreboard_image->parent[childnum].pid = 0;
504     }
505     else {
506         ap_run_child_status(ap_server_conf, pid, gen, -1, MPM_CHILD_EXITED);
507     }
508 }
509
510 static void event_note_child_started(int slot, pid_t pid)
511 {
512     ap_scoreboard_image->parent[slot].pid = pid;
513     ap_run_child_status(ap_server_conf,
514                         ap_scoreboard_image->parent[slot].pid,
515                         retained->my_generation, slot, MPM_CHILD_STARTED);
516 }
517
518 static void event_note_child_lost_slot(int slot, pid_t newpid)
519 {
520     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
521                  "pid %" APR_PID_T_FMT " taking over scoreboard slot from "
522                  "%" APR_PID_T_FMT "%s",
523                  newpid,
524                  ap_scoreboard_image->parent[slot].pid,
525                  ap_scoreboard_image->parent[slot].quiescing ?
526                  " (quiescing)" : "");
527     ap_run_child_status(ap_server_conf,
528                         ap_scoreboard_image->parent[slot].pid,
529                         ap_scoreboard_image->parent[slot].generation,
530                         slot, MPM_CHILD_LOST_SLOT);
531     /* Don't forget about this exiting child process, or we
532      * won't be able to kill it if it doesn't exit by the
533      * time the server is shut down.
534      */
535     ap_register_extra_mpm_process(ap_scoreboard_image->parent[slot].pid,
536                                   ap_scoreboard_image->parent[slot].generation);
537 }
538
539 static const char *event_get_name(void)
540 {
541     return "event";
542 }
543
544 /* a clean exit from a child with proper cleanup */
545 static void clean_child_exit(int code) __attribute__ ((noreturn));
546 static void clean_child_exit(int code)
547 {
548     mpm_state = AP_MPMQ_STOPPING;
549     if (pchild) {
550         apr_pool_destroy(pchild);
551     }
552
553     if (one_process) {
554         event_note_child_killed(/* slot */ 0, 0, 0);
555     }
556
557     exit(code);
558 }
559
560 static void just_die(int sig)
561 {
562     clean_child_exit(0);
563 }
564
565 /*****************************************************************
566  * Connection structures and accounting...
567  */
568
569 static int child_fatal;
570
571 /* volatile because they're updated from a signal handler */
572 static int volatile shutdown_pending;
573 static int volatile restart_pending;
574 ap_generation_t volatile ap_my_generation = 0;
575
576 static apr_status_t decrement_connection_count(void *dummy) {
577     apr_atomic_dec32(&connection_count);
578     return APR_SUCCESS;
579 }
580
581 /*
582  * ap_start_shutdown() and ap_start_restart(), below, are a first stab at
583  * functions to initiate shutdown or restart without relying on signals.
584  * Previously this was initiated in sig_term() and restart() signal handlers,
585  * but we want to be able to start a shutdown/restart from other sources --
586  * e.g. on Win32, from the service manager. Now the service manager can
587  * call ap_start_shutdown() or ap_start_restart() as appropiate.  Note that
588  * these functions can also be called by the child processes, since global
589  * variables are no longer used to pass on the required action to the parent.
590  *
591  * These should only be called from the parent process itself, since the
592  * parent process will use the shutdown_pending and restart_pending variables
593  * to determine whether to shutdown or restart. The child process should
594  * call signal_parent() directly to tell the parent to die -- this will
595  * cause neither of those variable to be set, which the parent will
596  * assume means something serious is wrong (which it will be, for the
597  * child to force an exit) and so do an exit anyway.
598  */
599
600 static void ap_start_shutdown(int graceful)
601 {
602     mpm_state = AP_MPMQ_STOPPING;
603     if (shutdown_pending == 1) {
604         /* Um, is this _probably_ not an error, if the user has
605          * tried to do a shutdown twice quickly, so we won't
606          * worry about reporting it.
607          */
608         return;
609     }
610     shutdown_pending = 1;
611     retained->is_graceful = graceful;
612 }
613
614 /* do a graceful restart if graceful == 1 */
615 static void ap_start_restart(int graceful)
616 {
617     mpm_state = AP_MPMQ_STOPPING;
618     if (restart_pending == 1) {
619         /* Probably not an error - don't bother reporting it */
620         return;
621     }
622     restart_pending = 1;
623     retained->is_graceful = graceful;
624 }
625
626 static void sig_term(int sig)
627 {
628     ap_start_shutdown(sig == AP_SIG_GRACEFUL_STOP);
629 }
630
631 static void restart(int sig)
632 {
633     ap_start_restart(sig == AP_SIG_GRACEFUL);
634 }
635
636 static void set_signals(void)
637 {
638 #ifndef NO_USE_SIGACTION
639     struct sigaction sa;
640 #endif
641
642     if (!one_process) {
643         ap_fatal_signal_setup(ap_server_conf, pconf);
644     }
645
646 #ifndef NO_USE_SIGACTION
647     sigemptyset(&sa.sa_mask);
648     sa.sa_flags = 0;
649
650     sa.sa_handler = sig_term;
651     if (sigaction(SIGTERM, &sa, NULL) < 0)
652         ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
653                      "sigaction(SIGTERM)");
654 #ifdef AP_SIG_GRACEFUL_STOP
655     if (sigaction(AP_SIG_GRACEFUL_STOP, &sa, NULL) < 0)
656         ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
657                      "sigaction(" AP_SIG_GRACEFUL_STOP_STRING ")");
658 #endif
659 #ifdef SIGINT
660     if (sigaction(SIGINT, &sa, NULL) < 0)
661         ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
662                      "sigaction(SIGINT)");
663 #endif
664 #ifdef SIGXCPU
665     sa.sa_handler = SIG_DFL;
666     if (sigaction(SIGXCPU, &sa, NULL) < 0)
667         ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
668                      "sigaction(SIGXCPU)");
669 #endif
670 #ifdef SIGXFSZ
671     /* For systems following the LFS standard, ignoring SIGXFSZ allows
672      * a write() beyond the 2GB limit to fail gracefully with E2BIG
673      * rather than terminate the process. */
674     sa.sa_handler = SIG_IGN;
675     if (sigaction(SIGXFSZ, &sa, NULL) < 0)
676         ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
677                      "sigaction(SIGXFSZ)");
678 #endif
679 #ifdef SIGPIPE
680     sa.sa_handler = SIG_IGN;
681     if (sigaction(SIGPIPE, &sa, NULL) < 0)
682         ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
683                      "sigaction(SIGPIPE)");
684 #endif
685
686     /* we want to ignore HUPs and AP_SIG_GRACEFUL while we're busy
687      * processing one */
688     sigaddset(&sa.sa_mask, SIGHUP);
689     sigaddset(&sa.sa_mask, AP_SIG_GRACEFUL);
690     sa.sa_handler = restart;
691     if (sigaction(SIGHUP, &sa, NULL) < 0)
692         ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
693                      "sigaction(SIGHUP)");
694     if (sigaction(AP_SIG_GRACEFUL, &sa, NULL) < 0)
695         ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
696                      "sigaction(" AP_SIG_GRACEFUL_STRING ")");
697 #else
698     if (!one_process) {
699 #ifdef SIGXCPU
700         apr_signal(SIGXCPU, SIG_DFL);
701 #endif /* SIGXCPU */
702 #ifdef SIGXFSZ
703         apr_signal(SIGXFSZ, SIG_IGN);
704 #endif /* SIGXFSZ */
705     }
706
707     apr_signal(SIGTERM, sig_term);
708 #ifdef SIGHUP
709     apr_signal(SIGHUP, restart);
710 #endif /* SIGHUP */
711 #ifdef AP_SIG_GRACEFUL
712     apr_signal(AP_SIG_GRACEFUL, restart);
713 #endif /* AP_SIG_GRACEFUL */
714 #ifdef AP_SIG_GRACEFUL_STOP
715      apr_signal(AP_SIG_GRACEFUL_STOP, sig_term);
716 #endif /* AP_SIG_GRACEFUL_STOP */
717 #ifdef SIGPIPE
718     apr_signal(SIGPIPE, SIG_IGN);
719 #endif /* SIGPIPE */
720
721 #endif
722 }
723
724 static int start_lingering_close(conn_state_t *cs)
725 {
726     apr_status_t rv;
727     if (ap_start_lingering_close(cs->c)) {
728         apr_pool_clear(cs->p);
729         ap_push_pool(worker_queue_info, cs->p);
730         return 0;
731     }
732     else {
733         apr_socket_t *csd = ap_get_conn_socket(cs->c);
734         struct timeout_queue *q;
735
736         rv = apr_socket_timeout_set(csd, 0);
737         AP_DEBUG_ASSERT(rv == APR_SUCCESS);
738         /*
739          * If some module requested a shortened waiting period, only wait for
740          * 2s (SECONDS_TO_LINGER). This is useful for mitigating certain
741          * DoS attacks.
742          */
743         if (apr_table_get(cs->c->notes, "short-lingering-close")) {
744             cs->expiration_time =
745                 apr_time_now() + apr_time_from_sec(SECONDS_TO_LINGER);
746             q = &short_linger_q;
747             cs->state = CONN_STATE_LINGER_SHORT;
748         }
749         else {
750             cs->expiration_time =
751                 apr_time_now() + apr_time_from_sec(MAX_SECS_TO_LINGER);
752             q = &linger_q;
753             cs->state = CONN_STATE_LINGER_NORMAL;
754         }
755         apr_thread_mutex_lock(timeout_mutex);
756         TO_QUEUE_APPEND(*q, cs);
757         apr_thread_mutex_unlock(timeout_mutex);
758         cs->pfd.reqevents = APR_POLLIN | APR_POLLHUP | APR_POLLERR;
759         rv = apr_pollset_add(event_pollset, &cs->pfd);
760         if (rv != APR_SUCCESS && !APR_STATUS_IS_EEXIST(rv)) {
761             ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf,
762                          "start_lingering_close: apr_pollset_add failure");
763             AP_DEBUG_ASSERT(0);
764         }
765     }
766     return 1;
767 }
768
769 static int stop_lingering_close(conn_state_t *cs)
770 {
771     apr_status_t rv;
772     apr_socket_t *csd = ap_get_conn_socket(cs->c);
773     ap_log_error(APLOG_MARK, APLOG_TRACE4, 0, ap_server_conf,
774                  "socket reached timeout in lingering-close state");
775     rv = apr_socket_close(csd);
776     if (rv != APR_SUCCESS) {
777         ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf, "error closing socket");
778         AP_DEBUG_ASSERT(0);
779     }
780     apr_pool_clear(cs->p);
781     ap_push_pool(worker_queue_info, cs->p);
782     return 0;
783 }
784
785
786
787 /*****************************************************************
788  * Child process main loop.
789  */
790
791 static int process_socket(apr_thread_t *thd, apr_pool_t * p, apr_socket_t * sock,
792                           conn_state_t * cs, int my_child_num,
793                           int my_thread_num)
794 {
795     conn_rec *c;
796     long conn_id = ID_FROM_CHILD_THREAD(my_child_num, my_thread_num);
797     int rc;
798     ap_sb_handle_t *sbh;
799
800     ap_create_sb_handle(&sbh, p, my_child_num, my_thread_num);
801
802     if (cs == NULL) {           /* This is a new connection */
803         listener_poll_type *pt = apr_pcalloc(p, sizeof(*pt));
804         cs = apr_pcalloc(p, sizeof(conn_state_t));
805         cs->bucket_alloc = apr_bucket_alloc_create(p);
806         c = ap_run_create_connection(p, ap_server_conf, sock,
807                                      conn_id, sbh, cs->bucket_alloc);
808         if (!c) {
809             apr_bucket_alloc_destroy(cs->bucket_alloc);
810             apr_pool_clear(p);
811             ap_push_pool(worker_queue_info, p);
812             return 1;
813         }
814         apr_atomic_inc32(&connection_count);
815         apr_pool_cleanup_register(c->pool, NULL, decrement_connection_count, apr_pool_cleanup_null);
816         c->current_thread = thd;
817         cs->c = c;
818         c->cs = cs;
819         cs->p = p;
820         cs->pfd.desc_type = APR_POLL_SOCKET;
821         cs->pfd.reqevents = APR_POLLIN;
822         cs->pfd.desc.s = sock;
823         pt->type = PT_CSD;
824         pt->baton = cs;
825         cs->pfd.client_data = pt;
826         TO_QUEUE_ELEM_INIT(cs);
827
828         ap_update_vhost_given_ip(c);
829
830         rc = ap_run_pre_connection(c, sock);
831         if (rc != OK && rc != DONE) {
832             ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c,
833                           "process_socket: connection aborted");
834             c->aborted = 1;
835         }
836
837         /**
838          * XXX If the platform does not have a usable way of bundling
839          * accept() with a socket readability check, like Win32,
840          * and there are measurable delays before the
841          * socket is readable due to the first data packet arriving,
842          * it might be better to create the cs on the listener thread
843          * with the state set to CONN_STATE_CHECK_REQUEST_LINE_READABLE
844          *
845          * FreeBSD users will want to enable the HTTP accept filter
846          * module in their kernel for the highest performance
847          * When the accept filter is active, sockets are kept in the
848          * kernel until a HTTP request is received.
849          */
850         cs->state = CONN_STATE_READ_REQUEST_LINE;
851
852     }
853     else {
854         c = cs->c;
855         c->sbh = sbh;
856         c->current_thread = thd;
857     }
858
859     if (c->clogging_input_filters && !c->aborted) {
860         /* Since we have an input filter which 'cloggs' the input stream,
861          * like mod_ssl, lets just do the normal read from input filters,
862          * like the Worker MPM does.
863          */
864         ap_run_process_connection(c);
865         if (cs->state != CONN_STATE_SUSPENDED) {
866             cs->state = CONN_STATE_LINGER;
867         }
868     }
869
870 read_request:
871     if (cs->state == CONN_STATE_READ_REQUEST_LINE) {
872         if (!c->aborted) {
873             ap_run_process_connection(c);
874
875             /* state will be updated upon return
876              * fall thru to either wait for readability/timeout or
877              * do lingering close
878              */
879         }
880         else {
881             cs->state = CONN_STATE_LINGER;
882         }
883     }
884
885     if (cs->state == CONN_STATE_WRITE_COMPLETION) {
886         ap_filter_t *output_filter = c->output_filters;
887         apr_status_t rv;
888         ap_update_child_status_from_conn(sbh, SERVER_BUSY_WRITE, c);
889         while (output_filter->next != NULL) {
890             output_filter = output_filter->next;
891         }
892         rv = output_filter->frec->filter_func.out_func(output_filter, NULL);
893         if (rv != APR_SUCCESS) {
894             ap_log_cerror(APLOG_MARK, APLOG_WARNING, rv, c,
895                           "network write failure in core output filter");
896             cs->state = CONN_STATE_LINGER;
897         }
898         else if (c->data_in_output_filters) {
899             /* Still in WRITE_COMPLETION_STATE:
900              * Set a write timeout for this connection, and let the
901              * event thread poll for writeability.
902              */
903             cs->expiration_time = ap_server_conf->timeout + apr_time_now();
904             apr_thread_mutex_lock(timeout_mutex);
905             TO_QUEUE_APPEND(write_completion_q, cs);
906             apr_thread_mutex_unlock(timeout_mutex);
907             cs->pfd.reqevents = APR_POLLOUT | APR_POLLHUP | APR_POLLERR;
908             rc = apr_pollset_add(event_pollset, &cs->pfd);
909             return 1;
910         }
911         else if (c->keepalive != AP_CONN_KEEPALIVE || c->aborted ||
912             listener_may_exit) {
913             c->cs->state = CONN_STATE_LINGER;
914         }
915         else if (c->data_in_input_filters) {
916             cs->state = CONN_STATE_READ_REQUEST_LINE;
917             goto read_request;
918         }
919         else {
920             cs->state = CONN_STATE_CHECK_REQUEST_LINE_READABLE;
921         }
922     }
923
924     if (cs->state == CONN_STATE_LINGER) {
925         if (!start_lingering_close(cs))
926             return 0;
927     }
928     else if (cs->state == CONN_STATE_CHECK_REQUEST_LINE_READABLE) {
929         apr_status_t rc;
930
931         /* It greatly simplifies the logic to use a single timeout value here
932          * because the new element can just be added to the end of the list and
933          * it will stay sorted in expiration time sequence.  If brand new
934          * sockets are sent to the event thread for a readability check, this
935          * will be a slight behavior change - they use the non-keepalive
936          * timeout today.  With a normal client, the socket will be readable in
937          * a few milliseconds anyway.
938          */
939         cs->expiration_time = ap_server_conf->keep_alive_timeout +
940                               apr_time_now();
941         apr_thread_mutex_lock(timeout_mutex);
942         TO_QUEUE_APPEND(keepalive_q, cs);
943         apr_thread_mutex_unlock(timeout_mutex);
944
945         /* Add work to pollset. */
946         cs->pfd.reqevents = APR_POLLIN;
947         rc = apr_pollset_add(event_pollset, &cs->pfd);
948
949         if (rc != APR_SUCCESS) {
950             ap_log_error(APLOG_MARK, APLOG_ERR, rc, ap_server_conf,
951                          "process_socket: apr_pollset_add failure");
952             AP_DEBUG_ASSERT(rc == APR_SUCCESS);
953         }
954     }
955     return 1;
956 }
957
958 /* requests_this_child has gone to zero or below.  See if the admin coded
959    "MaxConnectionsPerChild 0", and keep going in that case.  Doing it this way
960    simplifies the hot path in worker_thread */
961 static void check_infinite_requests(void)
962 {
963     if (ap_max_requests_per_child) {
964         signal_threads(ST_GRACEFUL);
965     }
966     else {
967         requests_this_child = INT_MAX;  /* keep going */
968     }
969 }
970
971 static void close_listeners(int process_slot, int *closed) {
972     if (!*closed) {
973         int i;
974         disable_listensocks(process_slot);
975         ap_close_listeners();
976         *closed = 1;
977         dying = 1;
978         ap_scoreboard_image->parent[process_slot].quiescing = 1;
979         for (i = 0; i < threads_per_child; ++i) {
980             ap_update_child_status_from_indexes(process_slot, i,
981                                                 SERVER_GRACEFUL, NULL);
982         }
983         /* wake up the main thread */
984         kill(ap_my_pid, SIGTERM);
985     }
986 }
987
988 static void unblock_signal(int sig)
989 {
990     sigset_t sig_mask;
991
992     sigemptyset(&sig_mask);
993     sigaddset(&sig_mask, sig);
994 #if defined(SIGPROCMASK_SETS_THREAD_MASK)
995     sigprocmask(SIG_UNBLOCK, &sig_mask, NULL);
996 #else
997     pthread_sigmask(SIG_UNBLOCK, &sig_mask, NULL);
998 #endif
999 }
1000
1001 static void dummy_signal_handler(int sig)
1002 {
1003     /* XXX If specifying SIG_IGN is guaranteed to unblock a syscall,
1004      *     then we don't need this goofy function.
1005      */
1006 }
1007
1008
1009 #if HAVE_SERF
1010 static apr_status_t s_socket_add(void *user_baton,
1011                                  apr_pollfd_t *pfd,
1012                                  void *serf_baton)
1013 {
1014     s_baton_t *s = (s_baton_t*)user_baton;
1015     /* XXXXX: recycle listener_poll_types */
1016     listener_poll_type *pt = ap_malloc(sizeof(*pt));
1017     pt->type = PT_SERF;
1018     pt->baton = serf_baton;
1019     pfd->client_data = pt;
1020     return apr_pollset_add(s->pollset, pfd);
1021 }
1022
1023 static apr_status_t s_socket_remove(void *user_baton,
1024                                     apr_pollfd_t *pfd,
1025                                     void *serf_baton)
1026 {
1027     s_baton_t *s = (s_baton_t*)user_baton;
1028     listener_poll_type *pt = pfd->client_data;
1029     free(pt);
1030     return apr_pollset_remove(s->pollset, pfd);
1031 }
1032 #endif
1033
1034 static apr_status_t init_pollset(apr_pool_t *p)
1035 {
1036 #if HAVE_SERF
1037     s_baton_t *baton = NULL;
1038 #endif
1039     ap_listen_rec *lr;
1040     listener_poll_type *pt;
1041     int i = 0;
1042
1043     TO_QUEUE_INIT(write_completion_q);
1044     TO_QUEUE_INIT(keepalive_q);
1045     TO_QUEUE_INIT(linger_q);
1046     TO_QUEUE_INIT(short_linger_q);
1047
1048     listener_pollfd = apr_palloc(p, sizeof(apr_pollfd_t) * num_listensocks);
1049     for (lr = ap_listeners; lr != NULL; lr = lr->next, i++) {
1050         apr_pollfd_t *pfd;
1051         AP_DEBUG_ASSERT(i < num_listensocks);
1052         pfd = &listener_pollfd[i];
1053         pt = apr_pcalloc(p, sizeof(*pt));
1054         pfd->desc_type = APR_POLL_SOCKET;
1055         pfd->desc.s = lr->sd;
1056         pfd->reqevents = APR_POLLIN;
1057
1058         pt->type = PT_ACCEPT;
1059         pt->baton = lr;
1060
1061         pfd->client_data = pt;
1062
1063         apr_socket_opt_set(pfd->desc.s, APR_SO_NONBLOCK, 1);
1064         apr_pollset_add(event_pollset, pfd);
1065
1066         lr->accept_func = ap_unixd_accept;
1067     }
1068
1069 #if HAVE_SERF
1070     baton = apr_pcalloc(p, sizeof(*baton));
1071     baton->pollset = event_pollset;
1072     /* TODO: subpools, threads, reuse, etc.  -- currently use malloc() inside :( */
1073     baton->pool = p;
1074
1075     g_serf = serf_context_create_ex(baton,
1076                                     s_socket_add,
1077                                     s_socket_remove, p);
1078
1079     ap_register_provider(p, "mpm_serf",
1080                          "instance", "0", g_serf);
1081
1082 #endif
1083
1084     return APR_SUCCESS;
1085 }
1086
1087 static apr_status_t push_timer2worker(timer_event_t* te)
1088 {
1089     return ap_queue_push_timer(worker_queue, te);
1090 }
1091
1092 static apr_status_t push2worker(const apr_pollfd_t * pfd,
1093                                 apr_pollset_t * pollset)
1094 {
1095     listener_poll_type *pt = (listener_poll_type *) pfd->client_data;
1096     conn_state_t *cs = (conn_state_t *) pt->baton;
1097     apr_status_t rc;
1098
1099     rc = apr_pollset_remove(pollset, pfd);
1100
1101     /*
1102      * Some of the pollset backends, like KQueue or Epoll
1103      * automagically remove the FD if the socket is closed,
1104      * therefore, we can accept _SUCCESS or _NOTFOUND,
1105      * and we still want to keep going
1106      */
1107     if (rc != APR_SUCCESS && !APR_STATUS_IS_NOTFOUND(rc)) {
1108         ap_log_error(APLOG_MARK, APLOG_ERR, rc, ap_server_conf,
1109                      "pollset remove failed");
1110         start_lingering_close(cs);
1111         return rc;
1112     }
1113
1114     rc = ap_queue_push(worker_queue, cs->pfd.desc.s, cs, cs->p);
1115     if (rc != APR_SUCCESS) {
1116         /* trash the connection; we couldn't queue the connected
1117          * socket to a worker
1118          */
1119         apr_bucket_alloc_destroy(cs->bucket_alloc);
1120         apr_socket_close(cs->pfd.desc.s);
1121         ap_log_error(APLOG_MARK, APLOG_CRIT, rc,
1122                      ap_server_conf, "push2worker: ap_queue_push failed");
1123         apr_pool_clear(cs->p);
1124         ap_push_pool(worker_queue_info, cs->p);
1125     }
1126
1127     return rc;
1128 }
1129
1130 /* get_worker:
1131  *     If *have_idle_worker_p == 0, reserve a worker thread, and set
1132  *     *have_idle_worker_p = 1.
1133  *     If *have_idle_worker_p is already 1, will do nothing.
1134  *     If blocking == 1, block if all workers are currently busy.
1135  *     If no worker was available immediately, will set *all_busy to 1.
1136  *     XXX: If there are no workers, we should not block immediately but
1137  *     XXX: close all keep-alive connections first.
1138  */
1139 static void get_worker(int *have_idle_worker_p, int blocking, int *all_busy)
1140 {
1141     apr_status_t rc;
1142
1143     if (*have_idle_worker_p) {
1144         /* already reserved a worker thread - must have hit a
1145          * transient error on a previous pass
1146          */
1147         return;
1148     }
1149
1150     if (blocking)
1151         rc = ap_queue_info_wait_for_idler(worker_queue_info, all_busy);
1152     else
1153         rc = ap_queue_info_try_get_idler(worker_queue_info);
1154
1155     if (rc == APR_SUCCESS) {
1156         *have_idle_worker_p = 1;
1157     }
1158     else if (!blocking && rc == APR_EAGAIN) {
1159         *all_busy = 1;
1160     }
1161     else if (!APR_STATUS_IS_EOF(rc)) {
1162         ap_log_error(APLOG_MARK, APLOG_ERR, rc, ap_server_conf,
1163                      "ap_queue_info_wait_for_idler failed.  "
1164                      "Attempting to shutdown process gracefully");
1165         signal_threads(ST_GRACEFUL);
1166     }
1167 }
1168
1169 /* XXXXXX: Convert to skiplist or other better data structure
1170  * (yes, this is VERY VERY VERY VERY BAD)
1171  */
1172
1173 /* Structures to reuse */
1174 static APR_RING_HEAD(timer_free_ring_t, timer_event_t) timer_free_ring;
1175 /* Active timers */
1176 static APR_RING_HEAD(timer_ring_t, timer_event_t) timer_ring;
1177
1178 static apr_thread_mutex_t *g_timer_ring_mtx;
1179
1180 static apr_status_t event_register_timed_callback(apr_time_t t,
1181                                                   ap_mpm_callback_fn_t *cbfn,
1182                                                   void *baton)
1183 {
1184     int inserted = 0;
1185     timer_event_t *ep;
1186     timer_event_t *te;
1187     /* oh yeah, and make locking smarter/fine grained. */
1188     apr_thread_mutex_lock(g_timer_ring_mtx);
1189
1190     if (!APR_RING_EMPTY(&timer_free_ring, timer_event_t, link)) {
1191         te = APR_RING_FIRST(&timer_free_ring);
1192         APR_RING_REMOVE(te, link);
1193     }
1194     else {
1195         /* XXXXX: lol, pool allocation without a context from any thread.Yeah. Right. MPMs Suck. */
1196         te = ap_malloc(sizeof(timer_event_t));
1197         APR_RING_ELEM_INIT(te, link);
1198     }
1199
1200     te->cbfunc = cbfn;
1201     te->baton = baton;
1202     /* XXXXX: optimize */
1203     te->when = t + apr_time_now();
1204
1205     /* Okay, insert sorted by when.. */
1206     for (ep = APR_RING_FIRST(&timer_ring);
1207          ep != APR_RING_SENTINEL(&timer_ring,
1208                                  timer_event_t, link);
1209          ep = APR_RING_NEXT(ep, link))
1210     {
1211         if (ep->when > te->when) {
1212             inserted = 1;
1213             APR_RING_INSERT_BEFORE(ep, te, link);
1214             break;
1215         }
1216     }
1217
1218     if (!inserted) {
1219         APR_RING_INSERT_TAIL(&timer_ring, te, timer_event_t, link);
1220     }
1221
1222     apr_thread_mutex_unlock(g_timer_ring_mtx);
1223
1224     return APR_SUCCESS;
1225 }
1226
1227 static void process_lingering_close(conn_state_t *cs, const apr_pollfd_t *pfd)
1228 {
1229     apr_socket_t *csd = ap_get_conn_socket(cs->c);
1230     char dummybuf[2048];
1231     apr_size_t nbytes;
1232     apr_status_t rv;
1233     struct timeout_queue *q;
1234     q = (cs->state == CONN_STATE_LINGER_SHORT) ?  &short_linger_q : &linger_q;
1235
1236     /* socket is already in non-blocking state */
1237     do {
1238         nbytes = sizeof(dummybuf);
1239         rv = apr_socket_recv(csd, dummybuf, &nbytes);
1240     } while (rv == APR_SUCCESS);
1241
1242     if (!APR_STATUS_IS_EOF(rv)) {
1243         return;
1244     }
1245
1246     rv = apr_pollset_remove(event_pollset, pfd);
1247     AP_DEBUG_ASSERT(rv == APR_SUCCESS);
1248
1249     rv = apr_socket_close(csd);
1250     AP_DEBUG_ASSERT(rv == APR_SUCCESS);
1251
1252     apr_thread_mutex_lock(timeout_mutex);
1253     TO_QUEUE_REMOVE(*q, cs);
1254     apr_thread_mutex_unlock(timeout_mutex);
1255     TO_QUEUE_ELEM_INIT(cs);
1256
1257     apr_pool_clear(cs->p);
1258     ap_push_pool(worker_queue_info, cs->p);
1259 }
1260
1261 /* call 'func' for all elements of 'q' with timeout less than 'timeout_time'.
1262  * Pre-condition: timeout_mutex must already be locked
1263  * Post-condition: timeout_mutex will be locked again
1264  */
1265 static void process_timeout_queue(struct timeout_queue *q,
1266                                   apr_time_t timeout_time,
1267                                   int (*func)(conn_state_t *))
1268 {
1269     int count = 0;
1270     conn_state_t *first, *cs, *last;
1271     if (!q->count) {
1272         return;
1273     }
1274     AP_DEBUG_ASSERT(!APR_RING_EMPTY(&q->head, conn_state_t, timeout_list));
1275
1276     cs = first = APR_RING_FIRST(&q->head);
1277     while (cs != APR_RING_SENTINEL(&q->head, conn_state_t, timeout_list)
1278            && cs->expiration_time < timeout_time) {
1279         last = cs;
1280         cs = APR_RING_NEXT(cs, timeout_list);
1281         count++;
1282     }
1283     if (!count)
1284         return;
1285
1286     APR_RING_UNSPLICE(first, last, timeout_list);
1287     AP_DEBUG_ASSERT(q->count >= count);
1288     q->count -= count;
1289     apr_thread_mutex_unlock(timeout_mutex);
1290     while (count) {
1291         cs = APR_RING_NEXT(first, timeout_list);
1292         TO_QUEUE_ELEM_INIT(first);
1293         func(first);
1294         first = cs;
1295         count--;
1296     }
1297     apr_thread_mutex_lock(timeout_mutex);
1298 }
1299
1300 static void * APR_THREAD_FUNC listener_thread(apr_thread_t * thd, void *dummy)
1301 {
1302     timer_event_t *ep;
1303     timer_event_t *te;
1304     apr_status_t rc;
1305     proc_info *ti = dummy;
1306     int process_slot = ti->pid;
1307     apr_pool_t *tpool = apr_thread_pool_get(thd);
1308     void *csd = NULL;
1309     apr_pool_t *ptrans;         /* Pool for per-transaction stuff */
1310     ap_listen_rec *lr;
1311     int have_idle_worker = 0;
1312     conn_state_t *cs;
1313     const apr_pollfd_t *out_pfd;
1314     apr_int32_t num = 0;
1315     apr_interval_time_t timeout_interval;
1316     apr_time_t timeout_time = 0, now, last_log;
1317     listener_poll_type *pt;
1318     int closed = 0, listeners_disabled = 0;
1319
1320     last_log = apr_time_now();
1321     free(ti);
1322
1323     /* the following times out events that are really close in the future
1324      *   to prevent extra poll calls
1325      *
1326      * current value is .1 second
1327      */
1328 #define TIMEOUT_FUDGE_FACTOR 100000
1329 #define EVENT_FUDGE_FACTOR 10000
1330
1331     rc = init_pollset(tpool);
1332     if (rc != APR_SUCCESS) {
1333         ap_log_error(APLOG_MARK, APLOG_ERR, rc, ap_server_conf,
1334                      "failed to initialize pollset, "
1335                      "attempting to shutdown process gracefully");
1336         signal_threads(ST_GRACEFUL);
1337         return NULL;
1338     }
1339
1340     /* Unblock the signal used to wake this thread up, and set a handler for
1341      * it.
1342      */
1343     unblock_signal(LISTENER_SIGNAL);
1344     apr_signal(LISTENER_SIGNAL, dummy_signal_handler);
1345
1346     for (;;) {
1347         int workers_were_busy = 0;
1348         if (listener_may_exit) {
1349             close_listeners(process_slot, &closed);
1350             if (terminate_mode == ST_UNGRACEFUL
1351                 || apr_atomic_read32(&connection_count) == 0)
1352                 break;
1353         }
1354
1355         if (requests_this_child <= 0) {
1356             check_infinite_requests();
1357         }
1358
1359         now = apr_time_now();
1360         if (APLOGtrace6(ap_server_conf)) {
1361             /* trace log status every second */
1362             if (now - last_log > apr_time_from_msec(1000)) {
1363                 last_log = now;
1364                 apr_thread_mutex_lock(timeout_mutex);
1365                 ap_log_error(APLOG_MARK, APLOG_TRACE6, 0, ap_server_conf,
1366                              "connections: %d (write-completion: %d "
1367                              "keep-alive: %d lingering: %d)",
1368                              connection_count, write_completion_q.count,
1369                              keepalive_q.count,
1370                              linger_q.count + short_linger_q.count);
1371                 apr_thread_mutex_unlock(timeout_mutex);
1372             }
1373         }
1374
1375         apr_thread_mutex_lock(g_timer_ring_mtx);
1376         if (!APR_RING_EMPTY(&timer_ring, timer_event_t, link)) {
1377             te = APR_RING_FIRST(&timer_ring);
1378             if (te->when > now) {
1379                 timeout_interval = te->when - now;
1380             }
1381             else {
1382                 timeout_interval = 1;
1383             }
1384         }
1385         else {
1386             timeout_interval = apr_time_from_msec(100);
1387         }
1388         apr_thread_mutex_unlock(g_timer_ring_mtx);
1389
1390 #if HAVE_SERF
1391         rc = serf_context_prerun(g_serf);
1392         if (rc != APR_SUCCESS) {
1393             /* TOOD: what should do here? ugh. */
1394         }
1395 #endif
1396         rc = apr_pollset_poll(event_pollset, timeout_interval, &num, &out_pfd);
1397         if (rc != APR_SUCCESS) {
1398             if (APR_STATUS_IS_EINTR(rc)) {
1399                 continue;
1400             }
1401             if (!APR_STATUS_IS_TIMEUP(rc)) {
1402                 ap_log_error(APLOG_MARK, APLOG_CRIT, rc, ap_server_conf,
1403                              "apr_pollset_poll failed.  Attempting to "
1404                              "shutdown process gracefully");
1405                 signal_threads(ST_GRACEFUL);
1406             }
1407         }
1408
1409         if (listener_may_exit) {
1410             close_listeners(process_slot, &closed);
1411             if (terminate_mode == ST_UNGRACEFUL
1412                 || apr_atomic_read32(&connection_count) == 0)
1413                 break;
1414         }
1415
1416         now = apr_time_now();
1417         apr_thread_mutex_lock(g_timer_ring_mtx);
1418         for (ep = APR_RING_FIRST(&timer_ring);
1419              ep != APR_RING_SENTINEL(&timer_ring,
1420                                      timer_event_t, link);
1421              ep = APR_RING_FIRST(&timer_ring))
1422         {
1423             if (ep->when < now + EVENT_FUDGE_FACTOR) {
1424                 APR_RING_REMOVE(ep, link);
1425                 push_timer2worker(ep);
1426             }
1427             else {
1428                 break;
1429             }
1430         }
1431         apr_thread_mutex_unlock(g_timer_ring_mtx);
1432
1433         while (num) {
1434             pt = (listener_poll_type *) out_pfd->client_data;
1435             if (pt->type == PT_CSD) {
1436                 /* one of the sockets is readable */
1437                 struct timeout_queue *remove_from_q = &write_completion_q;
1438                 int blocking = 1;
1439                 cs = (conn_state_t *) pt->baton;
1440                 switch (cs->state) {
1441                 case CONN_STATE_CHECK_REQUEST_LINE_READABLE:
1442                     cs->state = CONN_STATE_READ_REQUEST_LINE;
1443                     remove_from_q = &keepalive_q;
1444                     /* don't wait for a worker for a keepalive request */
1445                     blocking = 0;
1446                     /* FALL THROUGH */
1447                 case CONN_STATE_WRITE_COMPLETION:
1448                     get_worker(&have_idle_worker, blocking,
1449                                &workers_were_busy);
1450                     apr_thread_mutex_lock(timeout_mutex);
1451                     TO_QUEUE_REMOVE(*remove_from_q, cs);
1452                     apr_thread_mutex_unlock(timeout_mutex);
1453                     TO_QUEUE_ELEM_INIT(cs);
1454                     /* If we didn't get a worker immediately for a keep-alive
1455                      * request, we close the connection, so that the client can
1456                      * re-connect to a different process.
1457                      */
1458                     if (!have_idle_worker) {
1459                         start_lingering_close(cs);
1460                         break;
1461                     }
1462                     rc = push2worker(out_pfd, event_pollset);
1463                     if (rc != APR_SUCCESS) {
1464                         ap_log_error(APLOG_MARK, APLOG_CRIT, rc,
1465                                      ap_server_conf, "push2worker failed");
1466                     }
1467                     else {
1468                         have_idle_worker = 0;
1469                     }
1470                     break;
1471                 case CONN_STATE_LINGER_NORMAL:
1472                 case CONN_STATE_LINGER_SHORT:
1473                     process_lingering_close(cs, out_pfd);
1474                     break;
1475                 default:
1476                     ap_log_error(APLOG_MARK, APLOG_CRIT, rc,
1477                                  ap_server_conf,
1478                                  "event_loop: unexpected state %d",
1479                                  cs->state);
1480                     AP_DEBUG_ASSERT(0);
1481                 }
1482             }
1483             else if (pt->type == PT_ACCEPT) {
1484                 /* A Listener Socket is ready for an accept() */
1485                 if (workers_were_busy) {
1486                     if (!listeners_disabled)
1487                         disable_listensocks(process_slot);
1488                     listeners_disabled = 1;
1489                     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
1490                                  "All workers busy, not accepting new conns"
1491                                  "in this process");
1492                 }
1493                 else if (apr_atomic_read32(&connection_count) > threads_per_child
1494                          + ap_queue_info_get_idlers(worker_queue_info) *
1495                            worker_factor / WORKER_FACTOR_SCALE)
1496                 {
1497                     if (!listeners_disabled)
1498                         disable_listensocks(process_slot);
1499                     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
1500                                  "Too many open connections (%u), "
1501                                  "not accepting new conns in this process",
1502                                  apr_atomic_read32(&connection_count));
1503                     ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, ap_server_conf,
1504                                  "Idle workers: %u",
1505                                  ap_queue_info_get_idlers(worker_queue_info));
1506                     listeners_disabled = 1;
1507                 }
1508                 else if (listeners_disabled) {
1509                     listeners_disabled = 0;
1510                     enable_listensocks(process_slot);
1511                 }
1512                 if (!listeners_disabled) {
1513                     lr = (ap_listen_rec *) pt->baton;
1514                     ap_pop_pool(&ptrans, worker_queue_info);
1515
1516                     if (ptrans == NULL) {
1517                         /* create a new transaction pool for each accepted socket */
1518                         apr_allocator_t *allocator;
1519
1520                         apr_allocator_create(&allocator);
1521                         apr_allocator_max_free_set(allocator,
1522                                                    ap_max_mem_free);
1523                         apr_pool_create_ex(&ptrans, pconf, NULL, allocator);
1524                         apr_allocator_owner_set(allocator, ptrans);
1525                         if (ptrans == NULL) {
1526                             ap_log_error(APLOG_MARK, APLOG_CRIT, rc,
1527                                          ap_server_conf,
1528                                          "Failed to create transaction pool");
1529                             signal_threads(ST_GRACEFUL);
1530                             return NULL;
1531                         }
1532                     }
1533                     apr_pool_tag(ptrans, "transaction");
1534
1535                     get_worker(&have_idle_worker, 1, &workers_were_busy);
1536                     rc = lr->accept_func(&csd, lr, ptrans);
1537
1538                     /* later we trash rv and rely on csd to indicate
1539                      * success/failure
1540                      */
1541                     AP_DEBUG_ASSERT(rc == APR_SUCCESS || !csd);
1542
1543                     if (rc == APR_EGENERAL) {
1544                         /* E[NM]FILE, ENOMEM, etc */
1545                         resource_shortage = 1;
1546                         signal_threads(ST_GRACEFUL);
1547                     }
1548
1549                     if (csd != NULL) {
1550                         rc = ap_queue_push(worker_queue, csd, NULL, ptrans);
1551                         if (rc != APR_SUCCESS) {
1552                             /* trash the connection; we couldn't queue the connected
1553                              * socket to a worker
1554                              */
1555                             apr_socket_close(csd);
1556                             ap_log_error(APLOG_MARK, APLOG_CRIT, rc,
1557                                          ap_server_conf,
1558                                          "ap_queue_push failed");
1559                             apr_pool_clear(ptrans);
1560                             ap_push_pool(worker_queue_info, ptrans);
1561                         }
1562                         else {
1563                             have_idle_worker = 0;
1564                         }
1565                     }
1566                     else {
1567                         apr_pool_clear(ptrans);
1568                         ap_push_pool(worker_queue_info, ptrans);
1569                     }
1570                 }
1571             }               /* if:else on pt->type */
1572 #if HAVE_SERF
1573             else if (pt->type == PT_SERF) {
1574                 /* send socket to serf. */
1575                 /* XXXX: this doesn't require get_worker() */
1576                 serf_event_trigger(g_serf, pt->baton, out_pfd);
1577             }
1578 #endif
1579             out_pfd++;
1580             num--;
1581         }                   /* while for processing poll */
1582
1583         /* XXX possible optimization: stash the current time for use as
1584          * r->request_time for new requests
1585          */
1586         now = apr_time_now();
1587         /* we only do this once per 0.1s (TIMEOUT_FUDGE_FACTOR) */
1588         if (now > timeout_time) {
1589             struct process_score *ps;
1590             timeout_time = now + TIMEOUT_FUDGE_FACTOR;
1591
1592             /* handle timed out sockets */
1593             apr_thread_mutex_lock(timeout_mutex);
1594
1595             /* Step 1: keepalive timeouts */
1596             /* If all workers are busy, we kill older keep-alive connections so that they
1597              * may connect to another process.
1598              */
1599             if (workers_were_busy && keepalive_q.count) {
1600                 ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, ap_server_conf,
1601                              "All workers are busy, will close %d keep-alive "
1602                              "connections",
1603                              keepalive_q.count);
1604                 process_timeout_queue(&keepalive_q,
1605                                       timeout_time + ap_server_conf->keep_alive_timeout,
1606                                       start_lingering_close);
1607             }
1608             else {
1609                 process_timeout_queue(&keepalive_q, timeout_time,
1610                                       start_lingering_close);
1611             }
1612             /* Step 2: write completion timeouts */
1613             process_timeout_queue(&write_completion_q, timeout_time, start_lingering_close);
1614             /* Step 3: (normal) lingering close completion timeouts */
1615             process_timeout_queue(&linger_q, timeout_time, stop_lingering_close);
1616             /* Step 4: (short) lingering close completion timeouts */
1617             process_timeout_queue(&short_linger_q, timeout_time, stop_lingering_close);
1618
1619             ps = ap_get_scoreboard_process(process_slot);
1620             ps->write_completion = write_completion_q.count;
1621             ps->lingering_close = linger_q.count + short_linger_q.count;
1622             ps->keep_alive = keepalive_q.count;
1623             apr_thread_mutex_unlock(timeout_mutex);
1624
1625             ps->connections = apr_atomic_read32(&connection_count);
1626             /* XXX: should count CONN_STATE_SUSPENDED and set ps->suspended */
1627         }
1628         if (listeners_disabled && !workers_were_busy &&
1629             (int)apr_atomic_read32(&connection_count) <
1630             ((int)ap_queue_info_get_idlers(worker_queue_info) - 1) *
1631             worker_factor / WORKER_FACTOR_SCALE + threads_per_child)
1632         {
1633             listeners_disabled = 0;
1634             enable_listensocks(process_slot);
1635         }
1636         /*
1637          * XXX: do we need to set some timeout that re-enables the listensocks
1638          * XXX: in case no other event occurs?
1639          */
1640     }     /* listener main loop */
1641
1642     close_listeners(process_slot, &closed);
1643     ap_queue_term(worker_queue);
1644
1645     apr_thread_exit(thd, APR_SUCCESS);
1646     return NULL;
1647 }
1648
1649 /* XXX For ungraceful termination/restart, we definitely don't want to
1650  *     wait for active connections to finish but we may want to wait
1651  *     for idle workers to get out of the queue code and release mutexes,
1652  *     since those mutexes are cleaned up pretty soon and some systems
1653  *     may not react favorably (i.e., segfault) if operations are attempted
1654  *     on cleaned-up mutexes.
1655  */
1656 static void *APR_THREAD_FUNC worker_thread(apr_thread_t * thd, void *dummy)
1657 {
1658     proc_info *ti = dummy;
1659     int process_slot = ti->pid;
1660     int thread_slot = ti->tid;
1661     apr_socket_t *csd = NULL;
1662     conn_state_t *cs;
1663     apr_pool_t *ptrans;         /* Pool for per-transaction stuff */
1664     apr_status_t rv;
1665     int is_idle = 0;
1666     timer_event_t *te = NULL;
1667
1668     free(ti);
1669
1670     ap_scoreboard_image->servers[process_slot][thread_slot].pid = ap_my_pid;
1671     ap_scoreboard_image->servers[process_slot][thread_slot].tid = apr_os_thread_current();
1672     ap_scoreboard_image->servers[process_slot][thread_slot].generation = retained->my_generation;
1673     ap_update_child_status_from_indexes(process_slot, thread_slot,
1674                                         SERVER_STARTING, NULL);
1675
1676     while (!workers_may_exit) {
1677         if (!is_idle) {
1678             rv = ap_queue_info_set_idle(worker_queue_info, NULL);
1679             if (rv != APR_SUCCESS) {
1680                 ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
1681                              "ap_queue_info_set_idle failed. Attempting to "
1682                              "shutdown process gracefully.");
1683                 signal_threads(ST_GRACEFUL);
1684                 break;
1685             }
1686             is_idle = 1;
1687         }
1688
1689         ap_update_child_status_from_indexes(process_slot, thread_slot,
1690                                             dying ? SERVER_GRACEFUL : SERVER_READY, NULL);
1691       worker_pop:
1692         if (workers_may_exit) {
1693             break;
1694         }
1695
1696         te = NULL;
1697         rv = ap_queue_pop_something(worker_queue, &csd, &cs, &ptrans, &te);
1698
1699         if (rv != APR_SUCCESS) {
1700             /* We get APR_EOF during a graceful shutdown once all the
1701              * connections accepted by this server process have been handled.
1702              */
1703             if (APR_STATUS_IS_EOF(rv)) {
1704                 break;
1705             }
1706             /* We get APR_EINTR whenever ap_queue_pop() has been interrupted
1707              * from an explicit call to ap_queue_interrupt_all(). This allows
1708              * us to unblock threads stuck in ap_queue_pop() when a shutdown
1709              * is pending.
1710              *
1711              * If workers_may_exit is set and this is ungraceful termination/
1712              * restart, we are bound to get an error on some systems (e.g.,
1713              * AIX, which sanity-checks mutex operations) since the queue
1714              * may have already been cleaned up.  Don't log the "error" if
1715              * workers_may_exit is set.
1716              */
1717             else if (APR_STATUS_IS_EINTR(rv)) {
1718                 goto worker_pop;
1719             }
1720             /* We got some other error. */
1721             else if (!workers_may_exit) {
1722                 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
1723                              "ap_queue_pop failed");
1724             }
1725             continue;
1726         }
1727         if (te != NULL) {
1728             te->cbfunc(te->baton);
1729
1730             {
1731                 apr_thread_mutex_lock(g_timer_ring_mtx);
1732                 APR_RING_INSERT_TAIL(&timer_free_ring, te, timer_event_t, link);
1733                 apr_thread_mutex_unlock(g_timer_ring_mtx);
1734             }
1735         }
1736         else {
1737             is_idle = 0;
1738             worker_sockets[thread_slot] = csd;
1739             rv = process_socket(thd, ptrans, csd, cs, process_slot, thread_slot);
1740             if (!rv) {
1741                 requests_this_child--;
1742             }
1743             worker_sockets[thread_slot] = NULL;
1744         }
1745     }
1746
1747     ap_update_child_status_from_indexes(process_slot, thread_slot,
1748                                         dying ? SERVER_DEAD :
1749                                         SERVER_GRACEFUL,
1750                                         (request_rec *) NULL);
1751
1752     apr_thread_exit(thd, APR_SUCCESS);
1753     return NULL;
1754 }
1755
1756 static int check_signal(int signum)
1757 {
1758     switch (signum) {
1759     case SIGTERM:
1760     case SIGINT:
1761         return 1;
1762     }
1763     return 0;
1764 }
1765
1766
1767
1768 static void create_listener_thread(thread_starter * ts)
1769 {
1770     int my_child_num = ts->child_num_arg;
1771     apr_threadattr_t *thread_attr = ts->threadattr;
1772     proc_info *my_info;
1773     apr_status_t rv;
1774
1775     my_info = (proc_info *) ap_malloc(sizeof(proc_info));
1776     my_info->pid = my_child_num;
1777     my_info->tid = -1;          /* listener thread doesn't have a thread slot */
1778     my_info->sd = 0;
1779     rv = apr_thread_create(&ts->listener, thread_attr, listener_thread,
1780                            my_info, pchild);
1781     if (rv != APR_SUCCESS) {
1782         ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
1783                      "apr_thread_create: unable to create listener thread");
1784         /* let the parent decide how bad this really is */
1785         clean_child_exit(APEXIT_CHILDSICK);
1786     }
1787     apr_os_thread_get(&listener_os_thread, ts->listener);
1788 }
1789
1790 /* XXX under some circumstances not understood, children can get stuck
1791  *     in start_threads forever trying to take over slots which will
1792  *     never be cleaned up; for now there is an APLOG_DEBUG message issued
1793  *     every so often when this condition occurs
1794  */
1795 static void *APR_THREAD_FUNC start_threads(apr_thread_t * thd, void *dummy)
1796 {
1797     thread_starter *ts = dummy;
1798     apr_thread_t **threads = ts->threads;
1799     apr_threadattr_t *thread_attr = ts->threadattr;
1800     int child_num_arg = ts->child_num_arg;
1801     int my_child_num = child_num_arg;
1802     proc_info *my_info;
1803     apr_status_t rv;
1804     int i;
1805     int threads_created = 0;
1806     int listener_started = 0;
1807     int loops;
1808     int prev_threads_created;
1809     int max_recycled_pools = -1;
1810
1811     /* We must create the fd queues before we start up the listener
1812      * and worker threads. */
1813     worker_queue = apr_pcalloc(pchild, sizeof(*worker_queue));
1814     rv = ap_queue_init(worker_queue, threads_per_child, pchild);
1815     if (rv != APR_SUCCESS) {
1816         ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
1817                      "ap_queue_init() failed");
1818         clean_child_exit(APEXIT_CHILDFATAL);
1819     }
1820
1821     if (ap_max_mem_free != APR_ALLOCATOR_MAX_FREE_UNLIMITED) {
1822         /* If we want to conserve memory, let's not keep an unlimited number of
1823          * pools & allocators.
1824          * XXX: This should probably be a separate config directive
1825          */
1826         max_recycled_pools = threads_per_child * 3 / 4 ;
1827     }
1828     rv = ap_queue_info_create(&worker_queue_info, pchild,
1829                               threads_per_child, max_recycled_pools);
1830     if (rv != APR_SUCCESS) {
1831         ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
1832                      "ap_queue_info_create() failed");
1833         clean_child_exit(APEXIT_CHILDFATAL);
1834     }
1835
1836     /* Create the timeout mutex and main pollset before the listener
1837      * thread starts.
1838      */
1839     rv = apr_thread_mutex_create(&timeout_mutex, APR_THREAD_MUTEX_DEFAULT,
1840                                  pchild);
1841     if (rv != APR_SUCCESS) {
1842         ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf,
1843                      "creation of the timeout mutex failed.");
1844         clean_child_exit(APEXIT_CHILDFATAL);
1845     }
1846
1847     /* Create the main pollset */
1848     rv = apr_pollset_create(&event_pollset,
1849                             threads_per_child, /* XXX don't we need more, to handle
1850                                                 * connections in K-A or lingering
1851                                                 * close?
1852                                                 */
1853                             pchild, APR_POLLSET_THREADSAFE | APR_POLLSET_NOCOPY);
1854     if (rv != APR_SUCCESS) {
1855         ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf,
1856                      "apr_pollset_create with Thread Safety failed.");
1857         clean_child_exit(APEXIT_CHILDFATAL);
1858     }
1859
1860     worker_sockets = apr_pcalloc(pchild, threads_per_child
1861                                  * sizeof(apr_socket_t *));
1862
1863     loops = prev_threads_created = 0;
1864     while (1) {
1865         /* threads_per_child does not include the listener thread */
1866         for (i = 0; i < threads_per_child; i++) {
1867             int status =
1868                 ap_scoreboard_image->servers[child_num_arg][i].status;
1869
1870             if (status != SERVER_GRACEFUL && status != SERVER_DEAD) {
1871                 continue;
1872             }
1873
1874             my_info = (proc_info *) ap_malloc(sizeof(proc_info));
1875             my_info->pid = my_child_num;
1876             my_info->tid = i;
1877             my_info->sd = 0;
1878
1879             /* We are creating threads right now */
1880             ap_update_child_status_from_indexes(my_child_num, i,
1881                                                 SERVER_STARTING, NULL);
1882             /* We let each thread update its own scoreboard entry.  This is
1883              * done because it lets us deal with tid better.
1884              */
1885             rv = apr_thread_create(&threads[i], thread_attr,
1886                                    worker_thread, my_info, pchild);
1887             if (rv != APR_SUCCESS) {
1888                 ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
1889                              "apr_thread_create: unable to create worker thread");
1890                 /* let the parent decide how bad this really is */
1891                 clean_child_exit(APEXIT_CHILDSICK);
1892             }
1893             threads_created++;
1894         }
1895
1896         /* Start the listener only when there are workers available */
1897         if (!listener_started && threads_created) {
1898             create_listener_thread(ts);
1899             listener_started = 1;
1900         }
1901
1902
1903         if (start_thread_may_exit || threads_created == threads_per_child) {
1904             break;
1905         }
1906         /* wait for previous generation to clean up an entry */
1907         apr_sleep(apr_time_from_sec(1));
1908         ++loops;
1909         if (loops % 120 == 0) { /* every couple of minutes */
1910             if (prev_threads_created == threads_created) {
1911                 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
1912                              "child %" APR_PID_T_FMT " isn't taking over "
1913                              "slots very quickly (%d of %d)",
1914                              ap_my_pid, threads_created,
1915                              threads_per_child);
1916             }
1917             prev_threads_created = threads_created;
1918         }
1919     }
1920
1921     /* What state should this child_main process be listed as in the
1922      * scoreboard...?
1923      *  ap_update_child_status_from_indexes(my_child_num, i, SERVER_STARTING,
1924      *                                      (request_rec *) NULL);
1925      *
1926      *  This state should be listed separately in the scoreboard, in some kind
1927      *  of process_status, not mixed in with the worker threads' status.
1928      *  "life_status" is almost right, but it's in the worker's structure, and
1929      *  the name could be clearer.   gla
1930      */
1931     apr_thread_exit(thd, APR_SUCCESS);
1932     return NULL;
1933 }
1934
1935 static void join_workers(apr_thread_t * listener, apr_thread_t ** threads)
1936 {
1937     int i;
1938     apr_status_t rv, thread_rv;
1939
1940     if (listener) {
1941         int iter;
1942
1943         /* deal with a rare timing window which affects waking up the
1944          * listener thread...  if the signal sent to the listener thread
1945          * is delivered between the time it verifies that the
1946          * listener_may_exit flag is clear and the time it enters a
1947          * blocking syscall, the signal didn't do any good...  work around
1948          * that by sleeping briefly and sending it again
1949          */
1950
1951         iter = 0;
1952         while (iter < 10 && !dying) {
1953             /* listener has not stopped accepting yet */
1954             apr_sleep(apr_time_make(0, 500000));
1955             wakeup_listener();
1956             ++iter;
1957         }
1958         if (iter >= 10) {
1959             ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
1960                          "the listener thread didn't stop accepting");
1961         }
1962         else {
1963             rv = apr_thread_join(&thread_rv, listener);
1964             if (rv != APR_SUCCESS) {
1965                 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
1966                              "apr_thread_join: unable to join listener thread");
1967             }
1968         }
1969     }
1970
1971     for (i = 0; i < threads_per_child; i++) {
1972         if (threads[i]) {       /* if we ever created this thread */
1973             rv = apr_thread_join(&thread_rv, threads[i]);
1974             if (rv != APR_SUCCESS) {
1975                 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
1976                              "apr_thread_join: unable to join worker "
1977                              "thread %d", i);
1978             }
1979         }
1980     }
1981 }
1982
1983 static void join_start_thread(apr_thread_t * start_thread_id)
1984 {
1985     apr_status_t rv, thread_rv;
1986
1987     start_thread_may_exit = 1;  /* tell it to give up in case it is still
1988                                  * trying to take over slots from a
1989                                  * previous generation
1990                                  */
1991     rv = apr_thread_join(&thread_rv, start_thread_id);
1992     if (rv != APR_SUCCESS) {
1993         ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
1994                      "apr_thread_join: unable to join the start " "thread");
1995     }
1996 }
1997
1998 static void child_main(int child_num_arg)
1999 {
2000     apr_thread_t **threads;
2001     apr_status_t rv;
2002     thread_starter *ts;
2003     apr_threadattr_t *thread_attr;
2004     apr_thread_t *start_thread_id;
2005
2006     mpm_state = AP_MPMQ_STARTING;       /* for benefit of any hooks that run as this
2007                                          * child initializes
2008                                          */
2009     ap_my_pid = getpid();
2010     ap_fatal_signal_child_setup(ap_server_conf);
2011     apr_pool_create(&pchild, pconf);
2012
2013     /*stuff to do before we switch id's, so we have permissions. */
2014     ap_reopen_scoreboard(pchild, NULL, 0);
2015
2016     if (ap_run_drop_privileges(pchild, ap_server_conf)) {
2017         clean_child_exit(APEXIT_CHILDFATAL);
2018     }
2019
2020     apr_thread_mutex_create(&g_timer_ring_mtx, APR_THREAD_MUTEX_DEFAULT, pchild);
2021     APR_RING_INIT(&timer_free_ring, timer_event_t, link);
2022     APR_RING_INIT(&timer_ring, timer_event_t, link);
2023     ap_run_child_init(pchild, ap_server_conf);
2024
2025     /* done with init critical section */
2026
2027     /* Just use the standard apr_setup_signal_thread to block all signals
2028      * from being received.  The child processes no longer use signals for
2029      * any communication with the parent process.
2030      */
2031     rv = apr_setup_signal_thread();
2032     if (rv != APR_SUCCESS) {
2033         ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
2034                      "Couldn't initialize signal thread");
2035         clean_child_exit(APEXIT_CHILDFATAL);
2036     }
2037
2038     if (ap_max_requests_per_child) {
2039         requests_this_child = ap_max_requests_per_child;
2040     }
2041     else {
2042         /* coding a value of zero means infinity */
2043         requests_this_child = INT_MAX;
2044     }
2045
2046     /* Setup worker threads */
2047
2048     /* clear the storage; we may not create all our threads immediately,
2049      * and we want a 0 entry to indicate a thread which was not created
2050      */
2051     threads = ap_calloc(threads_per_child, sizeof(apr_thread_t *));
2052     ts = apr_palloc(pchild, sizeof(*ts));
2053
2054     apr_threadattr_create(&thread_attr, pchild);
2055     /* 0 means PTHREAD_CREATE_JOINABLE */
2056     apr_threadattr_detach_set(thread_attr, 0);
2057
2058     if (ap_thread_stacksize != 0) {
2059         apr_threadattr_stacksize_set(thread_attr, ap_thread_stacksize);
2060     }
2061
2062     ts->threads = threads;
2063     ts->listener = NULL;
2064     ts->child_num_arg = child_num_arg;
2065     ts->threadattr = thread_attr;
2066
2067     rv = apr_thread_create(&start_thread_id, thread_attr, start_threads,
2068                            ts, pchild);
2069     if (rv != APR_SUCCESS) {
2070         ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
2071                      "apr_thread_create: unable to create worker thread");
2072         /* let the parent decide how bad this really is */
2073         clean_child_exit(APEXIT_CHILDSICK);
2074     }
2075
2076     mpm_state = AP_MPMQ_RUNNING;
2077
2078     /* If we are only running in one_process mode, we will want to
2079      * still handle signals. */
2080     if (one_process) {
2081         /* Block until we get a terminating signal. */
2082         apr_signal_thread(check_signal);
2083         /* make sure the start thread has finished; signal_threads()
2084          * and join_workers() depend on that
2085          */
2086         /* XXX join_start_thread() won't be awakened if one of our
2087          *     threads encounters a critical error and attempts to
2088          *     shutdown this child
2089          */
2090         join_start_thread(start_thread_id);
2091
2092         /* helps us terminate a little more quickly than the dispatch of the
2093          * signal thread; beats the Pipe of Death and the browsers
2094          */
2095         signal_threads(ST_UNGRACEFUL);
2096
2097         /* A terminating signal was received. Now join each of the
2098          * workers to clean them up.
2099          *   If the worker already exited, then the join frees
2100          *   their resources and returns.
2101          *   If the worker hasn't exited, then this blocks until
2102          *   they have (then cleans up).
2103          */
2104         join_workers(ts->listener, threads);
2105     }
2106     else {                      /* !one_process */
2107         /* remove SIGTERM from the set of blocked signals...  if one of
2108          * the other threads in the process needs to take us down
2109          * (e.g., for MaxConnectionsPerChild) it will send us SIGTERM
2110          */
2111         unblock_signal(SIGTERM);
2112         apr_signal(SIGTERM, dummy_signal_handler);
2113         /* Watch for any messages from the parent over the POD */
2114         while (1) {
2115             rv = ap_event_pod_check(pod);
2116             if (rv == AP_NORESTART) {
2117                 /* see if termination was triggered while we slept */
2118                 switch (terminate_mode) {
2119                 case ST_GRACEFUL:
2120                     rv = AP_GRACEFUL;
2121                     break;
2122                 case ST_UNGRACEFUL:
2123                     rv = AP_RESTART;
2124                     break;
2125                 }
2126             }
2127             if (rv == AP_GRACEFUL || rv == AP_RESTART) {
2128                 /* make sure the start thread has finished;
2129                  * signal_threads() and join_workers depend on that
2130                  */
2131                 join_start_thread(start_thread_id);
2132                 signal_threads(rv ==
2133                                AP_GRACEFUL ? ST_GRACEFUL : ST_UNGRACEFUL);
2134                 break;
2135             }
2136         }
2137
2138         /* A terminating signal was received. Now join each of the
2139          * workers to clean them up.
2140          *   If the worker already exited, then the join frees
2141          *   their resources and returns.
2142          *   If the worker hasn't exited, then this blocks until
2143          *   they have (then cleans up).
2144          */
2145         join_workers(ts->listener, threads);
2146     }
2147
2148     free(threads);
2149
2150     clean_child_exit(resource_shortage ? APEXIT_CHILDSICK : 0);
2151 }
2152
2153 static int make_child(server_rec * s, int slot)
2154 {
2155     int pid;
2156
2157     if (slot + 1 > retained->max_daemons_limit) {
2158         retained->max_daemons_limit = slot + 1;
2159     }
2160
2161     if (one_process) {
2162         set_signals();
2163         event_note_child_started(slot, getpid());
2164         child_main(slot);
2165         /* NOTREACHED */
2166     }
2167
2168     if ((pid = fork()) == -1) {
2169         ap_log_error(APLOG_MARK, APLOG_ERR, errno, s,
2170                      "fork: Unable to fork new process");
2171
2172         /* fork didn't succeed.  There's no need to touch the scoreboard;
2173          * if we were trying to replace a failed child process, then
2174          * server_main_loop() marked its workers SERVER_DEAD, and if
2175          * we were trying to replace a child process that exited normally,
2176          * its worker_thread()s left SERVER_DEAD or SERVER_GRACEFUL behind.
2177          */
2178
2179         /* In case system resources are maxxed out, we don't want
2180            Apache running away with the CPU trying to fork over and
2181            over and over again. */
2182         apr_sleep(apr_time_from_sec(10));
2183
2184         return -1;
2185     }
2186
2187     if (!pid) {
2188 #ifdef HAVE_BINDPROCESSOR
2189         /* By default, AIX binds to a single processor.  This bit unbinds
2190          * children which will then bind to another CPU.
2191          */
2192         int status = bindprocessor(BINDPROCESS, (int) getpid(),
2193                                    PROCESSOR_CLASS_ANY);
2194         if (status != OK)
2195             ap_log_error(APLOG_MARK, APLOG_DEBUG, errno,
2196                          ap_server_conf,
2197                          "processor unbind failed");
2198 #endif
2199         RAISE_SIGSTOP(MAKE_CHILD);
2200
2201         apr_signal(SIGTERM, just_die);
2202         child_main(slot);
2203         /* NOTREACHED */
2204     }
2205     /* else */
2206     if (ap_scoreboard_image->parent[slot].pid != 0) {
2207         /* This new child process is squatting on the scoreboard
2208          * entry owned by an exiting child process, which cannot
2209          * exit until all active requests complete.
2210          */
2211         event_note_child_lost_slot(slot, pid);
2212     }
2213     ap_scoreboard_image->parent[slot].quiescing = 0;
2214     ap_scoreboard_image->parent[slot].not_accepting = 0;
2215     event_note_child_started(slot, pid);
2216     return 0;
2217 }
2218
2219 /* start up a bunch of children */
2220 static void startup_children(int number_to_start)
2221 {
2222     int i;
2223
2224     for (i = 0; number_to_start && i < ap_daemons_limit; ++i) {
2225         if (ap_scoreboard_image->parent[i].pid != 0) {
2226             continue;
2227         }
2228         if (make_child(ap_server_conf, i) < 0) {
2229             break;
2230         }
2231         --number_to_start;
2232     }
2233 }
2234
2235 static void perform_idle_server_maintenance(void)
2236 {
2237     int i, j;
2238     int idle_thread_count;
2239     worker_score *ws;
2240     process_score *ps;
2241     int free_length;
2242     int totally_free_length = 0;
2243     int free_slots[MAX_SPAWN_RATE];
2244     int last_non_dead;
2245     int total_non_dead;
2246     int active_thread_count = 0;
2247
2248     /* initialize the free_list */
2249     free_length = 0;
2250
2251     idle_thread_count = 0;
2252     last_non_dead = -1;
2253     total_non_dead = 0;
2254
2255     for (i = 0; i < ap_daemons_limit; ++i) {
2256         /* Initialization to satisfy the compiler. It doesn't know
2257          * that threads_per_child is always > 0 */
2258         int status = SERVER_DEAD;
2259         int any_dying_threads = 0;
2260         int any_dead_threads = 0;
2261         int all_dead_threads = 1;
2262
2263         if (i >= retained->max_daemons_limit
2264             && totally_free_length == retained->idle_spawn_rate)
2265             /* short cut if all active processes have been examined and
2266              * enough empty scoreboard slots have been found
2267              */
2268
2269             break;
2270         ps = &ap_scoreboard_image->parent[i];
2271         for (j = 0; j < threads_per_child; j++) {
2272             ws = &ap_scoreboard_image->servers[i][j];
2273             status = ws->status;
2274
2275             /* XXX any_dying_threads is probably no longer needed    GLA */
2276             any_dying_threads = any_dying_threads ||
2277                 (status == SERVER_GRACEFUL);
2278             any_dead_threads = any_dead_threads || (status == SERVER_DEAD);
2279             all_dead_threads = all_dead_threads &&
2280                 (status == SERVER_DEAD || status == SERVER_GRACEFUL);
2281
2282             /* We consider a starting server as idle because we started it
2283              * at least a cycle ago, and if it still hasn't finished starting
2284              * then we're just going to swamp things worse by forking more.
2285              * So we hopefully won't need to fork more if we count it.
2286              * This depends on the ordering of SERVER_READY and SERVER_STARTING.
2287              */
2288             if (ps->pid != 0) { /* XXX just set all_dead_threads in outer
2289                                    for loop if no pid?  not much else matters */
2290                 if (status <= SERVER_READY && !ps->quiescing && !ps->not_accepting
2291                     && ps->generation == retained->my_generation)
2292                 {
2293                     ++idle_thread_count;
2294                 }
2295                 if (status >= SERVER_READY && status < SERVER_GRACEFUL) {
2296                     ++active_thread_count;
2297                 }
2298             }
2299         }
2300         if (any_dead_threads
2301             && totally_free_length < retained->idle_spawn_rate
2302             && free_length < MAX_SPAWN_RATE
2303             && (!ps->pid      /* no process in the slot */
2304                   || ps->quiescing)) {  /* or at least one is going away */
2305             if (all_dead_threads) {
2306                 /* great! we prefer these, because the new process can
2307                  * start more threads sooner.  So prioritize this slot
2308                  * by putting it ahead of any slots with active threads.
2309                  *
2310                  * first, make room by moving a slot that's potentially still
2311                  * in use to the end of the array
2312                  */
2313                 free_slots[free_length] = free_slots[totally_free_length];
2314                 free_slots[totally_free_length++] = i;
2315             }
2316             else {
2317                 /* slot is still in use - back of the bus
2318                  */
2319                 free_slots[free_length] = i;
2320             }
2321             ++free_length;
2322         }
2323         /* XXX if (!ps->quiescing)     is probably more reliable  GLA */
2324         if (!any_dying_threads) {
2325             last_non_dead = i;
2326             ++total_non_dead;
2327         }
2328     }
2329
2330     if (retained->sick_child_detected) {
2331         if (active_thread_count > 0) {
2332             /* some child processes appear to be working.  don't kill the
2333              * whole server.
2334              */
2335             retained->sick_child_detected = 0;
2336         }
2337         else {
2338             /* looks like a basket case.  give up.
2339              */
2340             shutdown_pending = 1;
2341             child_fatal = 1;
2342             ap_log_error(APLOG_MARK, APLOG_ALERT, 0,
2343                          ap_server_conf,
2344                          "No active workers found..."
2345                          " Apache is exiting!");
2346             /* the child already logged the failure details */
2347             return;
2348         }
2349     }
2350
2351     retained->max_daemons_limit = last_non_dead + 1;
2352
2353     if (idle_thread_count > max_spare_threads) {
2354         /* Kill off one child */
2355         ap_event_pod_signal(pod, TRUE);
2356         retained->idle_spawn_rate = 1;
2357     }
2358     else if (idle_thread_count < min_spare_threads) {
2359         /* terminate the free list */
2360         if (free_length == 0) { /* scoreboard is full, can't fork */
2361
2362             if (active_thread_count >= ap_daemons_limit * threads_per_child) {
2363                 if (!retained->maxclients_reported) {
2364                     /* only report this condition once */
2365                     ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf,
2366                                  "server reached MaxRequestWorkers setting, "
2367                                  "consider raising the MaxRequestWorkers "
2368                                  "setting");
2369                     retained->maxclients_reported = 1;
2370                 }
2371             }
2372             else {
2373                 ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf,
2374                              "scoreboard is full, not at MaxRequestWorkers");
2375             }
2376             retained->idle_spawn_rate = 1;
2377         }
2378         else {
2379             if (free_length > retained->idle_spawn_rate) {
2380                 free_length = retained->idle_spawn_rate;
2381             }
2382             if (retained->idle_spawn_rate >= 8) {
2383                 ap_log_error(APLOG_MARK, APLOG_INFO, 0, ap_server_conf,
2384                              "server seems busy, (you may need "
2385                              "to increase StartServers, ThreadsPerChild "
2386                              "or Min/MaxSpareThreads), "
2387                              "spawning %d children, there are around %d idle "
2388                              "threads, and %d total children", free_length,
2389                              idle_thread_count, total_non_dead);
2390             }
2391             for (i = 0; i < free_length; ++i) {
2392                 make_child(ap_server_conf, free_slots[i]);
2393             }
2394             /* the next time around we want to spawn twice as many if this
2395              * wasn't good enough, but not if we've just done a graceful
2396              */
2397             if (retained->hold_off_on_exponential_spawning) {
2398                 --retained->hold_off_on_exponential_spawning;
2399             }
2400             else if (retained->idle_spawn_rate < MAX_SPAWN_RATE) {
2401                 retained->idle_spawn_rate *= 2;
2402             }
2403         }
2404     }
2405     else {
2406         retained->idle_spawn_rate = 1;
2407     }
2408 }
2409
2410 static void server_main_loop(int remaining_children_to_start)
2411 {
2412     ap_generation_t old_gen;
2413     int child_slot;
2414     apr_exit_why_e exitwhy;
2415     int status, processed_status;
2416     apr_proc_t pid;
2417     int i;
2418
2419     while (!restart_pending && !shutdown_pending) {
2420         ap_wait_or_timeout(&exitwhy, &status, &pid, pconf, ap_server_conf);
2421
2422         if (pid.pid != -1) {
2423             processed_status = ap_process_child_status(&pid, exitwhy, status);
2424             if (processed_status == APEXIT_CHILDFATAL) {
2425                 shutdown_pending = 1;
2426                 child_fatal = 1;
2427                 return;
2428             }
2429             else if (processed_status == APEXIT_CHILDSICK) {
2430                 /* tell perform_idle_server_maintenance to check into this
2431                  * on the next timer pop
2432                  */
2433                 retained->sick_child_detected = 1;
2434             }
2435             /* non-fatal death... note that it's gone in the scoreboard. */
2436             child_slot = ap_find_child_by_pid(&pid);
2437             if (child_slot >= 0) {
2438                 for (i = 0; i < threads_per_child; i++)
2439                     ap_update_child_status_from_indexes(child_slot, i,
2440                                                         SERVER_DEAD,
2441                                                         (request_rec *) NULL);
2442
2443                 event_note_child_killed(child_slot, 0, 0);
2444                 ap_scoreboard_image->parent[child_slot].quiescing = 0;
2445                 if (processed_status == APEXIT_CHILDSICK) {
2446                     /* resource shortage, minimize the fork rate */
2447                     retained->idle_spawn_rate = 1;
2448                 }
2449                 else if (remaining_children_to_start
2450                          && child_slot < ap_daemons_limit) {
2451                     /* we're still doing a 1-for-1 replacement of dead
2452                      * children with new children
2453                      */
2454                     make_child(ap_server_conf, child_slot);
2455                     --remaining_children_to_start;
2456                 }
2457             }
2458             else if (ap_unregister_extra_mpm_process(pid.pid, &old_gen) == 1) {
2459
2460                 event_note_child_killed(-1, /* already out of the scoreboard */
2461                                         pid.pid, old_gen);
2462 #if APR_HAS_OTHER_CHILD
2463             }
2464             else if (apr_proc_other_child_alert(&pid, APR_OC_REASON_DEATH,
2465                                                 status) == 0) {
2466                 /* handled */
2467 #endif
2468             }
2469             else if (retained->is_graceful) {
2470                 /* Great, we've probably just lost a slot in the
2471                  * scoreboard.  Somehow we don't know about this child.
2472                  */
2473                 ap_log_error(APLOG_MARK, APLOG_WARNING, 0,
2474                              ap_server_conf,
2475                              "long lost child came home! (pid %ld)",
2476                              (long) pid.pid);
2477             }
2478             /* Don't perform idle maintenance when a child dies,
2479              * only do it when there's a timeout.  Remember only a
2480              * finite number of children can die, and it's pretty
2481              * pathological for a lot to die suddenly.
2482              */
2483             continue;
2484         }
2485         else if (remaining_children_to_start) {
2486             /* we hit a 1 second timeout in which none of the previous
2487              * generation of children needed to be reaped... so assume
2488              * they're all done, and pick up the slack if any is left.
2489              */
2490             startup_children(remaining_children_to_start);
2491             remaining_children_to_start = 0;
2492             /* In any event we really shouldn't do the code below because
2493              * few of the servers we just started are in the IDLE state
2494              * yet, so we'd mistakenly create an extra server.
2495              */
2496             continue;
2497         }
2498
2499         perform_idle_server_maintenance();
2500     }
2501 }
2502
2503 static int event_run(apr_pool_t * _pconf, apr_pool_t * plog, server_rec * s)
2504 {
2505     int remaining_children_to_start;
2506
2507     ap_log_pid(pconf, ap_pid_fname);
2508
2509     if (!retained->is_graceful) {
2510         if (ap_run_pre_mpm(s->process->pool, SB_SHARED) != OK) {
2511             mpm_state = AP_MPMQ_STOPPING;
2512             return DONE;
2513         }
2514         /* fix the generation number in the global score; we just got a new,
2515          * cleared scoreboard
2516          */
2517         ap_scoreboard_image->global->running_generation = retained->my_generation;
2518     }
2519
2520     restart_pending = shutdown_pending = 0;
2521     set_signals();
2522     /* Don't thrash... */
2523     if (max_spare_threads < min_spare_threads + threads_per_child)
2524         max_spare_threads = min_spare_threads + threads_per_child;
2525
2526     /* If we're doing a graceful_restart then we're going to see a lot
2527      * of children exiting immediately when we get into the main loop
2528      * below (because we just sent them AP_SIG_GRACEFUL).  This happens pretty
2529      * rapidly... and for each one that exits we may start a new one, until
2530      * there are at least min_spare_threads idle threads, counting across
2531      * all children.  But we may be permitted to start more children than
2532      * that, so we'll just keep track of how many we're
2533      * supposed to start up without the 1 second penalty between each fork.
2534      */
2535     remaining_children_to_start = ap_daemons_to_start;
2536     if (remaining_children_to_start > ap_daemons_limit) {
2537         remaining_children_to_start = ap_daemons_limit;
2538     }
2539     if (!retained->is_graceful) {
2540         startup_children(remaining_children_to_start);
2541         remaining_children_to_start = 0;
2542     }
2543     else {
2544         /* give the system some time to recover before kicking into
2545          * exponential mode */
2546         retained->hold_off_on_exponential_spawning = 10;
2547     }
2548
2549     ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
2550                  "%s configured -- resuming normal operations",
2551                  ap_get_server_description());
2552     ap_log_error(APLOG_MARK, APLOG_INFO, 0, ap_server_conf,
2553                  "Server built: %s", ap_get_server_built());
2554     ap_log_command_line(plog, s);
2555
2556     mpm_state = AP_MPMQ_RUNNING;
2557
2558     server_main_loop(remaining_children_to_start);
2559     mpm_state = AP_MPMQ_STOPPING;
2560
2561     if (shutdown_pending && !retained->is_graceful) {
2562         /* Time to shut down:
2563          * Kill child processes, tell them to call child_exit, etc...
2564          */
2565         ap_event_pod_killpg(pod, ap_daemons_limit, FALSE);
2566         ap_reclaim_child_processes(1, /* Start with SIGTERM */
2567                                    event_note_child_killed);
2568
2569         if (!child_fatal) {
2570             /* cleanup pid file on normal shutdown */
2571             ap_remove_pid(pconf, ap_pid_fname);
2572             ap_log_error(APLOG_MARK, APLOG_NOTICE, 0,
2573                          ap_server_conf, "caught SIGTERM, shutting down");
2574         }
2575         return DONE;
2576     } else if (shutdown_pending) {
2577         /* Time to gracefully shut down:
2578          * Kill child processes, tell them to call child_exit, etc...
2579          */
2580         int active_children;
2581         int index;
2582         apr_time_t cutoff = 0;
2583
2584         /* Close our listeners, and then ask our children to do same */
2585         ap_close_listeners();
2586         ap_event_pod_killpg(pod, ap_daemons_limit, TRUE);
2587         ap_relieve_child_processes(event_note_child_killed);
2588
2589         if (!child_fatal) {
2590             /* cleanup pid file on normal shutdown */
2591             ap_remove_pid(pconf, ap_pid_fname);
2592             ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
2593                          "caught " AP_SIG_GRACEFUL_STOP_STRING
2594                          ", shutting down gracefully");
2595         }
2596
2597         if (ap_graceful_shutdown_timeout) {
2598             cutoff = apr_time_now() +
2599                      apr_time_from_sec(ap_graceful_shutdown_timeout);
2600         }
2601
2602         /* Don't really exit until each child has finished */
2603         shutdown_pending = 0;
2604         do {
2605             /* Pause for a second */
2606             apr_sleep(apr_time_from_sec(1));
2607
2608             /* Relieve any children which have now exited */
2609             ap_relieve_child_processes(event_note_child_killed);
2610
2611             active_children = 0;
2612             for (index = 0; index < ap_daemons_limit; ++index) {
2613                 if (ap_mpm_safe_kill(MPM_CHILD_PID(index), 0) == APR_SUCCESS) {
2614                     active_children = 1;
2615                     /* Having just one child is enough to stay around */
2616                     break;
2617                 }
2618             }
2619         } while (!shutdown_pending && active_children &&
2620                  (!ap_graceful_shutdown_timeout || apr_time_now() < cutoff));
2621
2622         /* We might be here because we received SIGTERM, either
2623          * way, try and make sure that all of our processes are
2624          * really dead.
2625          */
2626         ap_event_pod_killpg(pod, ap_daemons_limit, FALSE);
2627         ap_reclaim_child_processes(1, event_note_child_killed);
2628
2629         return DONE;
2630     }
2631
2632     /* we've been told to restart */
2633     apr_signal(SIGHUP, SIG_IGN);
2634
2635     if (one_process) {
2636         /* not worth thinking about */
2637         return DONE;
2638     }
2639
2640     /* advance to the next generation */
2641     /* XXX: we really need to make sure this new generation number isn't in
2642      * use by any of the children.
2643      */
2644     ++retained->my_generation;
2645     ap_scoreboard_image->global->running_generation = retained->my_generation;
2646
2647     if (retained->is_graceful) {
2648         ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
2649                      AP_SIG_GRACEFUL_STRING
2650                      " received.  Doing graceful restart");
2651         /* wake up the children...time to die.  But we'll have more soon */
2652         ap_event_pod_killpg(pod, ap_daemons_limit, TRUE);
2653
2654
2655         /* This is mostly for debugging... so that we know what is still
2656          * gracefully dealing with existing request.
2657          */
2658
2659     }
2660     else {
2661         /* Kill 'em all.  Since the child acts the same on the parents SIGTERM
2662          * and a SIGHUP, we may as well use the same signal, because some user
2663          * pthreads are stealing signals from us left and right.
2664          */
2665         ap_event_pod_killpg(pod, ap_daemons_limit, FALSE);
2666
2667         ap_reclaim_child_processes(1,  /* Start with SIGTERM */
2668                                    event_note_child_killed);
2669         ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
2670                      "SIGHUP received.  Attempting to restart");
2671     }
2672
2673     return OK;
2674 }
2675
2676 /* This really should be a post_config hook, but the error log is already
2677  * redirected by that point, so we need to do this in the open_logs phase.
2678  */
2679 static int event_open_logs(apr_pool_t * p, apr_pool_t * plog,
2680                            apr_pool_t * ptemp, server_rec * s)
2681 {
2682     int startup = 0;
2683     int level_flags = 0;
2684     apr_status_t rv;
2685
2686     pconf = p;
2687
2688     /* the reverse of pre_config, we want this only the first time around */
2689     if (retained->module_loads == 1) {
2690         startup = 1;
2691         level_flags |= APLOG_STARTUP;
2692     }
2693
2694     if ((num_listensocks = ap_setup_listeners(ap_server_conf)) < 1) {
2695         ap_log_error(APLOG_MARK, APLOG_ALERT | level_flags, 0,
2696                      (startup ? NULL : s),
2697                      "no listening sockets available, shutting down");
2698         return DONE;
2699     }
2700
2701     if (!one_process) {
2702         if ((rv = ap_event_pod_open(pconf, &pod))) {
2703             ap_log_error(APLOG_MARK, APLOG_CRIT | level_flags, rv,
2704                          (startup ? NULL : s),
2705                          "could not open pipe-of-death");
2706             return DONE;
2707         }
2708     }
2709     return OK;
2710 }
2711
2712 static int event_pre_config(apr_pool_t * pconf, apr_pool_t * plog,
2713                             apr_pool_t * ptemp)
2714 {
2715     int no_detach, debug, foreground;
2716     apr_status_t rv;
2717     const char *userdata_key = "mpm_event_module";
2718
2719     mpm_state = AP_MPMQ_STARTING;
2720
2721     debug = ap_exists_config_define("DEBUG");
2722
2723     if (debug) {
2724         foreground = one_process = 1;
2725         no_detach = 0;
2726     }
2727     else {
2728         one_process = ap_exists_config_define("ONE_PROCESS");
2729         no_detach = ap_exists_config_define("NO_DETACH");
2730         foreground = ap_exists_config_define("FOREGROUND");
2731     }
2732
2733     /* sigh, want this only the second time around */
2734     retained = ap_retained_data_get(userdata_key);
2735     if (!retained) {
2736         retained = ap_retained_data_create(userdata_key, sizeof(*retained));
2737         retained->max_daemons_limit = -1;
2738         retained->idle_spawn_rate = 1;
2739     }
2740     ++retained->module_loads;
2741     if (retained->module_loads == 2) {
2742         rv = apr_pollset_create(&event_pollset, 1, plog,
2743                                 APR_POLLSET_THREADSAFE | APR_POLLSET_NOCOPY);
2744         if (rv != APR_SUCCESS) {
2745             ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL,
2746                          "Couldn't create a Thread Safe Pollset. "
2747                          "Is it supported on your platform?"
2748                          "Also check system or user limits!");
2749             return HTTP_INTERNAL_SERVER_ERROR;
2750         }
2751         apr_pollset_destroy(event_pollset);
2752
2753         if (!one_process && !foreground) {
2754             /* before we detach, setup crash handlers to log to errorlog */
2755             ap_fatal_signal_setup(ap_server_conf, pconf);
2756             rv = apr_proc_detach(no_detach ? APR_PROC_DETACH_FOREGROUND
2757                                  : APR_PROC_DETACH_DAEMONIZE);
2758             if (rv != APR_SUCCESS) {
2759                 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL,
2760                              "apr_proc_detach failed");
2761                 return HTTP_INTERNAL_SERVER_ERROR;
2762             }
2763         }
2764     }
2765
2766     parent_pid = ap_my_pid = getpid();
2767
2768     ap_listen_pre_config();
2769     ap_daemons_to_start = DEFAULT_START_DAEMON;
2770     min_spare_threads = DEFAULT_MIN_FREE_DAEMON * DEFAULT_THREADS_PER_CHILD;
2771     max_spare_threads = DEFAULT_MAX_FREE_DAEMON * DEFAULT_THREADS_PER_CHILD;
2772     server_limit = DEFAULT_SERVER_LIMIT;
2773     thread_limit = DEFAULT_THREAD_LIMIT;
2774     ap_daemons_limit = server_limit;
2775     threads_per_child = DEFAULT_THREADS_PER_CHILD;
2776     max_workers = ap_daemons_limit * threads_per_child;
2777     ap_extended_status = 0;
2778
2779     return OK;
2780 }
2781
2782 static int event_check_config(apr_pool_t *p, apr_pool_t *plog,
2783                               apr_pool_t *ptemp, server_rec *s)
2784 {
2785     int startup = 0;
2786
2787     /* the reverse of pre_config, we want this only the first time around */
2788     if (retained->module_loads == 1) {
2789         startup = 1;
2790     }
2791
2792     if (server_limit > MAX_SERVER_LIMIT) {
2793         if (startup) {
2794             ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2795                          "WARNING: ServerLimit of %d exceeds compile-time "
2796                          "limit of", server_limit);
2797             ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2798                          " %d servers, decreasing to %d.",
2799                          MAX_SERVER_LIMIT, MAX_SERVER_LIMIT);
2800         } else {
2801             ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
2802                          "ServerLimit of %d exceeds compile-time limit "
2803                          "of %d, decreasing to match",
2804                          server_limit, MAX_SERVER_LIMIT);
2805         }
2806         server_limit = MAX_SERVER_LIMIT;
2807     }
2808     else if (server_limit < 1) {
2809         if (startup) {
2810             ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2811                          "WARNING: ServerLimit of %d not allowed, "
2812                          "increasing to 1.", server_limit);
2813         } else {
2814             ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
2815                          "ServerLimit of %d not allowed, increasing to 1",
2816                          server_limit);
2817         }
2818         server_limit = 1;
2819     }
2820
2821     /* you cannot change ServerLimit across a restart; ignore
2822      * any such attempts
2823      */
2824     if (!retained->first_server_limit) {
2825         retained->first_server_limit = server_limit;
2826     }
2827     else if (server_limit != retained->first_server_limit) {
2828         /* don't need a startup console version here */
2829         ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
2830                      "changing ServerLimit to %d from original value of %d "
2831                      "not allowed during restart",
2832                      server_limit, retained->first_server_limit);
2833         server_limit = retained->first_server_limit;
2834     }
2835
2836     if (thread_limit > MAX_THREAD_LIMIT) {
2837         if (startup) {
2838             ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2839                          "WARNING: ThreadLimit of %d exceeds compile-time "
2840                          "limit of", thread_limit);
2841             ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2842                          " %d threads, decreasing to %d.",
2843                          MAX_THREAD_LIMIT, MAX_THREAD_LIMIT);
2844         } else {
2845             ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
2846                          "ThreadLimit of %d exceeds compile-time limit "
2847                          "of %d, decreasing to match",
2848                          thread_limit, MAX_THREAD_LIMIT);
2849         }
2850         thread_limit = MAX_THREAD_LIMIT;
2851     }
2852     else if (thread_limit < 1) {
2853         if (startup) {
2854             ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2855                          "WARNING: ThreadLimit of %d not allowed, "
2856                          "increasing to 1.", thread_limit);
2857         } else {
2858             ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
2859                          "ThreadLimit of %d not allowed, increasing to 1",
2860                          thread_limit);
2861         }
2862         thread_limit = 1;
2863     }
2864
2865     /* you cannot change ThreadLimit across a restart; ignore
2866      * any such attempts
2867      */
2868     if (!retained->first_thread_limit) {
2869         retained->first_thread_limit = thread_limit;
2870     }
2871     else if (thread_limit != retained->first_thread_limit) {
2872         /* don't need a startup console version here */
2873         ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
2874                      "changing ThreadLimit to %d from original value of %d "
2875                      "not allowed during restart",
2876                      thread_limit, retained->first_thread_limit);
2877         thread_limit = retained->first_thread_limit;
2878     }
2879
2880     if (threads_per_child > thread_limit) {
2881         if (startup) {
2882             ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2883                          "WARNING: ThreadsPerChild of %d exceeds ThreadLimit "
2884                          "of", threads_per_child);
2885             ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2886                          " %d threads, decreasing to %d.",
2887                          thread_limit, thread_limit);
2888             ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2889                          " To increase, please see the ThreadLimit "
2890                          "directive.");
2891         } else {
2892             ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
2893                          "ThreadsPerChild of %d exceeds ThreadLimit "
2894                          "of %d, decreasing to match",
2895                          threads_per_child, thread_limit);
2896         }
2897         threads_per_child = thread_limit;
2898     }
2899     else if (threads_per_child < 1) {
2900         if (startup) {
2901             ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2902                          "WARNING: ThreadsPerChild of %d not allowed, "
2903                          "increasing to 1.", threads_per_child);
2904         } else {
2905             ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
2906                          "ThreadsPerChild of %d not allowed, increasing to 1",
2907                          threads_per_child);
2908         }
2909         threads_per_child = 1;
2910     }
2911
2912     if (max_workers < threads_per_child) {
2913         if (startup) {
2914             ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2915                          "WARNING: MaxRequestWorkers of %d is less than "
2916                          "ThreadsPerChild of", max_workers);
2917             ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2918                          " %d, increasing to %d.  MaxRequestWorkers must be at "
2919                          "least as large",
2920                          threads_per_child, threads_per_child);
2921             ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2922                          " as the number of threads in a single server.");
2923         } else {
2924             ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
2925                          "MaxRequestWorkers of %d is less than ThreadsPerChild "
2926                          "of %d, increasing to match",
2927                          max_workers, threads_per_child);
2928         }
2929         max_workers = threads_per_child;
2930     }
2931
2932     ap_daemons_limit = max_workers / threads_per_child;
2933
2934     if (max_workers % threads_per_child) {
2935         int tmp_max_workers = ap_daemons_limit * threads_per_child;
2936
2937         if (startup) {
2938             ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2939                          "WARNING: MaxRequestWorkers of %d is not an integer "
2940                          "multiple of", max_workers);
2941             ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2942                          " ThreadsPerChild of %d, decreasing to nearest "
2943                          "multiple %d,", threads_per_child,
2944                          tmp_max_workers);
2945             ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2946                          " for a maximum of %d servers.",
2947                          ap_daemons_limit);
2948         } else {
2949             ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
2950                          "MaxRequestWorkers of %d is not an integer multiple "
2951                          "of ThreadsPerChild of %d, decreasing to nearest "
2952                          "multiple %d", max_workers, threads_per_child,
2953                          tmp_max_workers);
2954         }
2955         max_workers = tmp_max_workers;
2956     }
2957
2958     if (ap_daemons_limit > server_limit) {
2959         if (startup) {
2960             ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2961                          "WARNING: MaxRequestWorkers of %d would require %d "
2962                          "servers and ", max_workers, ap_daemons_limit);
2963             ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2964                          " would exceed ServerLimit of %d, decreasing to %d.",
2965                          server_limit, server_limit * threads_per_child);
2966             ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2967                          " To increase, please see the ServerLimit "
2968                          "directive.");
2969         } else {
2970             ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
2971                          "MaxRequestWorkers of %d would require %d servers and "
2972                          "exceed ServerLimit of %d, decreasing to %d",
2973                          max_workers, ap_daemons_limit, server_limit,
2974                          server_limit * threads_per_child);
2975         }
2976         ap_daemons_limit = server_limit;
2977     }
2978
2979     /* ap_daemons_to_start > ap_daemons_limit checked in ap_mpm_run() */
2980     if (ap_daemons_to_start < 0) {
2981         if (startup) {
2982             ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2983                          "WARNING: StartServers of %d not allowed, "
2984                          "increasing to 1.", ap_daemons_to_start);
2985         } else {
2986             ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
2987                          "StartServers of %d not allowed, increasing to 1",
2988                          ap_daemons_to_start);
2989         }
2990         ap_daemons_to_start = 1;
2991     }
2992
2993     if (min_spare_threads < 1) {
2994         if (startup) {
2995             ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2996                          "WARNING: MinSpareThreads of %d not allowed, "
2997                          "increasing to 1", min_spare_threads);
2998             ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2999                          " to avoid almost certain server failure.");
3000             ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
3001                          " Please read the documentation.");
3002         } else {
3003             ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
3004                          "MinSpareThreads of %d not allowed, increasing to 1",
3005                          min_spare_threads);
3006         }
3007         min_spare_threads = 1;
3008     }
3009
3010     /* max_spare_threads < min_spare_threads + threads_per_child
3011      * checked in ap_mpm_run()
3012      */
3013
3014     return OK;
3015 }
3016
3017 static void event_hooks(apr_pool_t * p)
3018 {
3019     /* Our open_logs hook function must run before the core's, or stderr
3020      * will be redirected to a file, and the messages won't print to the
3021      * console.
3022      */
3023     static const char *const aszSucc[] = { "core.c", NULL };
3024     one_process = 0;
3025
3026     ap_hook_open_logs(event_open_logs, NULL, aszSucc, APR_HOOK_REALLY_FIRST);
3027     /* we need to set the MPM state before other pre-config hooks use MPM query
3028      * to retrieve it, so register as REALLY_FIRST
3029      */
3030     ap_hook_pre_config(event_pre_config, NULL, NULL, APR_HOOK_REALLY_FIRST);
3031     ap_hook_check_config(event_check_config, NULL, NULL, APR_HOOK_MIDDLE);
3032     ap_hook_mpm(event_run, NULL, NULL, APR_HOOK_MIDDLE);
3033     ap_hook_mpm_query(event_query, NULL, NULL, APR_HOOK_MIDDLE);
3034     ap_hook_mpm_register_timed_callback(event_register_timed_callback, NULL, NULL,
3035                                         APR_HOOK_MIDDLE);
3036     ap_hook_mpm_get_name(event_get_name, NULL, NULL, APR_HOOK_MIDDLE);
3037 }
3038
3039 static const char *set_daemons_to_start(cmd_parms *cmd, void *dummy,
3040                                         const char *arg)
3041 {
3042     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3043     if (err != NULL) {
3044         return err;
3045     }
3046
3047     ap_daemons_to_start = atoi(arg);
3048     return NULL;
3049 }
3050
3051 static const char *set_min_spare_threads(cmd_parms * cmd, void *dummy,
3052                                          const char *arg)
3053 {
3054     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3055     if (err != NULL) {
3056         return err;
3057     }
3058
3059     min_spare_threads = atoi(arg);
3060     return NULL;
3061 }
3062
3063 static const char *set_max_spare_threads(cmd_parms * cmd, void *dummy,
3064                                          const char *arg)
3065 {
3066     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3067     if (err != NULL) {
3068         return err;
3069     }
3070
3071     max_spare_threads = atoi(arg);
3072     return NULL;
3073 }
3074
3075 static const char *set_max_workers(cmd_parms * cmd, void *dummy,
3076                                    const char *arg)
3077 {
3078     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3079     if (err != NULL) {
3080         return err;
3081     }
3082     if (!strcasecmp(cmd->cmd->name, "MaxClients")) {
3083         ap_log_error(APLOG_MARK, APLOG_INFO, 0, NULL,
3084                      "MaxClients is deprecated, use MaxRequestWorkers "
3085                      "instead.");
3086     }
3087     max_workers = atoi(arg);
3088     return NULL;
3089 }
3090
3091 static const char *set_threads_per_child(cmd_parms * cmd, void *dummy,
3092                                          const char *arg)
3093 {
3094     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3095     if (err != NULL) {
3096         return err;
3097     }
3098
3099     threads_per_child = atoi(arg);
3100     return NULL;
3101 }
3102 static const char *set_server_limit (cmd_parms *cmd, void *dummy, const char *arg)
3103 {
3104     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3105     if (err != NULL) {
3106         return err;
3107     }
3108
3109     server_limit = atoi(arg);
3110     return NULL;
3111 }
3112
3113 static const char *set_thread_limit(cmd_parms * cmd, void *dummy,
3114                                     const char *arg)
3115 {
3116     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3117     if (err != NULL) {
3118         return err;
3119     }
3120
3121     thread_limit = atoi(arg);
3122     return NULL;
3123 }
3124
3125 static const char *set_worker_factor(cmd_parms * cmd, void *dummy,
3126                                      const char *arg)
3127 {
3128     double val;
3129     char *endptr;
3130     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3131     if (err != NULL) {
3132         return err;
3133     }
3134
3135     val = strtod(arg, &endptr);
3136     if (*endptr)
3137         return "error parsing value";
3138
3139     worker_factor = val * WORKER_FACTOR_SCALE;
3140     if (worker_factor == 0)
3141         worker_factor = 1;
3142     return NULL;
3143 }
3144
3145
3146 static const command_rec event_cmds[] = {
3147     LISTEN_COMMANDS,
3148     AP_INIT_TAKE1("StartServers", set_daemons_to_start, NULL, RSRC_CONF,
3149                   "Number of child processes launched at server startup"),
3150     AP_INIT_TAKE1("ServerLimit", set_server_limit, NULL, RSRC_CONF,
3151                   "Maximum number of child processes for this run of Apache"),
3152     AP_INIT_TAKE1("MinSpareThreads", set_min_spare_threads, NULL, RSRC_CONF,
3153                   "Minimum number of idle threads, to handle request spikes"),
3154     AP_INIT_TAKE1("MaxSpareThreads", set_max_spare_threads, NULL, RSRC_CONF,
3155                   "Maximum number of idle threads"),
3156     AP_INIT_TAKE1("MaxClients", set_max_workers, NULL, RSRC_CONF,
3157                   "Deprecated name of MaxRequestWorkers"),
3158     AP_INIT_TAKE1("MaxRequestWorkers", set_max_workers, NULL, RSRC_CONF,
3159                   "Maximum number of threads alive at the same time"),
3160     AP_INIT_TAKE1("ThreadsPerChild", set_threads_per_child, NULL, RSRC_CONF,
3161                   "Number of threads each child creates"),
3162     AP_INIT_TAKE1("ThreadLimit", set_thread_limit, NULL, RSRC_CONF,
3163                   "Maximum number of worker threads per child process for this "
3164                   "run of Apache - Upper limit for ThreadsPerChild"),
3165     AP_INIT_TAKE1("AsyncRequestWorkerFactor", set_worker_factor, NULL, RSRC_CONF,
3166                   "How many additional connects will be accepted per idle "
3167                   "worker thread"),
3168     AP_GRACEFUL_SHUTDOWN_TIMEOUT_COMMAND,
3169     {NULL}
3170 };
3171
3172 AP_DECLARE_MODULE(mpm_event) = {
3173     MPM20_MODULE_STUFF,
3174     NULL,                       /* hook to run before apache parses args */
3175     NULL,                       /* create per-directory config structure */
3176     NULL,                       /* merge per-directory config structures */
3177     NULL,                       /* create per-server config structure */
3178     NULL,                       /* merge per-server config structures */
3179     event_cmds,                 /* command apr_table_t */
3180     event_hooks                 /* register_hooks */
3181 };