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