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