]> granicus.if.org Git - apache/blob - server/mpm/event/event.c
Merge r1818804, r1818951, r1818958, r1818960, r1819027, r1819214, r1820035 from trunk:
[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  * significant 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 Listening 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 does not perform 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 #include <stdlib.h>
63
64 #if APR_HAVE_UNISTD_H
65 #include <unistd.h>
66 #endif
67 #if APR_HAVE_SYS_SOCKET_H
68 #include <sys/socket.h>
69 #endif
70 #if APR_HAVE_SYS_WAIT_H
71 #include <sys/wait.h>
72 #endif
73 #ifdef HAVE_SYS_PROCESSOR_H
74 #include <sys/processor.h>      /* for bindprocessor() */
75 #endif
76
77 #if !APR_HAS_THREADS
78 #error The Event MPM requires APR threads, but they are unavailable.
79 #endif
80
81 #include "ap_config.h"
82 #include "httpd.h"
83 #include "http_main.h"
84 #include "http_log.h"
85 #include "http_config.h"        /* for read_config */
86 #include "http_core.h"          /* for get_remote_host */
87 #include "http_connection.h"
88 #include "http_protocol.h"
89 #include "ap_mpm.h"
90 #include "mpm_common.h"
91 #include "ap_listen.h"
92 #include "scoreboard.h"
93 #include "fdqueue.h"
94 #include "mpm_default.h"
95 #include "http_vhost.h"
96 #include "unixd.h"
97 #include "apr_skiplist.h"
98
99 #include <signal.h>
100 #include <limits.h>             /* for INT_MAX */
101
102
103 /* Limit on the total --- clients will be locked out if more servers than
104  * this are needed.  It is intended solely to keep the server from crashing
105  * when things get out of hand.
106  *
107  * We keep a hard maximum number of servers, for two reasons --- first off,
108  * in case something goes seriously wrong, we want to stop the fork bomb
109  * short of actually crashing the machine we're running on by filling some
110  * kernel table.  Secondly, it keeps the size of the scoreboard file small
111  * enough that we can read the whole thing without worrying too much about
112  * the overhead.
113  */
114 #ifndef DEFAULT_SERVER_LIMIT
115 #define DEFAULT_SERVER_LIMIT 16
116 #endif
117
118 /* Admin can't tune ServerLimit beyond MAX_SERVER_LIMIT.  We want
119  * some sort of compile-time limit to help catch typos.
120  */
121 #ifndef MAX_SERVER_LIMIT
122 #define MAX_SERVER_LIMIT 20000
123 #endif
124
125 /* Limit on the threads per process.  Clients will be locked out if more than
126  * this are needed.
127  *
128  * We keep this for one reason it keeps the size of the scoreboard file small
129  * enough that we can read the whole thing without worrying too much about
130  * the overhead.
131  */
132 #ifndef DEFAULT_THREAD_LIMIT
133 #define DEFAULT_THREAD_LIMIT 64
134 #endif
135
136 /* Admin can't tune ThreadLimit beyond MAX_THREAD_LIMIT.  We want
137  * some sort of compile-time limit to help catch typos.
138  */
139 #ifndef MAX_THREAD_LIMIT
140 #define MAX_THREAD_LIMIT 100000
141 #endif
142
143 #define MPM_CHILD_PID(i) (ap_scoreboard_image->parent[i].pid)
144
145 #if !APR_VERSION_AT_LEAST(1,4,0)
146 #define apr_time_from_msec(x) (x * 1000)
147 #endif
148
149 #ifndef MAX_SECS_TO_LINGER
150 #define MAX_SECS_TO_LINGER 30
151 #endif
152 #define SECONDS_TO_LINGER  2
153
154 /*
155  * Actual definitions of config globals
156  */
157
158 #ifndef DEFAULT_WORKER_FACTOR
159 #define DEFAULT_WORKER_FACTOR 2
160 #endif
161 #define WORKER_FACTOR_SCALE   16  /* scale factor to allow fractional values */
162 static unsigned int worker_factor = DEFAULT_WORKER_FACTOR * WORKER_FACTOR_SCALE;
163     /* AsyncRequestWorkerFactor * 16 */
164
165 static int threads_per_child = 0;           /* ThreadsPerChild */
166 static int ap_daemons_to_start = 0;         /* StartServers */
167 static int min_spare_threads = 0;           /* MinSpareThreads */
168 static int max_spare_threads = 0;           /* MaxSpareThreads */
169 static int active_daemons_limit = 0;        /* MaxRequestWorkers / ThreadsPerChild */
170 static int active_daemons = 0;              /* workers that still active, i.e. are
171                                                not shutting down gracefully */
172 static int max_workers = 0;                 /* MaxRequestWorkers */
173 static int server_limit = 0;                /* ServerLimit */
174 static int thread_limit = 0;                /* ThreadLimit */
175 static int had_healthy_child = 0;
176 static int dying = 0;
177 static int workers_may_exit = 0;
178 static int start_thread_may_exit = 0;
179 static int listener_may_exit = 0;
180 static int listener_is_wakeable = 0;        /* Pollset supports APR_POLLSET_WAKEABLE */
181 static int num_listensocks = 0;
182 static apr_int32_t conns_this_child;        /* MaxConnectionsPerChild, only access
183                                                in listener thread */
184 static apr_uint32_t connection_count = 0;   /* Number of open connections */
185 static apr_uint32_t lingering_count = 0;    /* Number of connections in lingering close */
186 static apr_uint32_t suspended_count = 0;    /* Number of suspended connections */
187 static apr_uint32_t clogged_count = 0;      /* Number of threads processing ssl conns */
188 static apr_uint32_t threads_shutdown = 0;   /* Number of threads that have shutdown
189                                                early during graceful termination */
190 static int resource_shortage = 0;
191 static fd_queue_t *worker_queue;
192 static fd_queue_info_t *worker_queue_info;
193
194 static apr_thread_mutex_t *timeout_mutex;
195
196 module AP_MODULE_DECLARE_DATA mpm_event_module;
197
198 /* forward declare */
199 struct event_srv_cfg_s;
200 typedef struct event_srv_cfg_s event_srv_cfg;
201
202 static apr_pollfd_t *listener_pollfd;
203
204 /*
205  * The pollset for sockets that are in any of the timeout queues. Currently
206  * we use the timeout_mutex to make sure that connections are added/removed
207  * atomically to/from both event_pollset and a timeout queue. Otherwise
208  * some confusion can happen under high load if timeout queues and pollset
209  * get out of sync.
210  * XXX: It should be possible to make the lock unnecessary in many or even all
211  * XXX: cases.
212  */
213 static apr_pollset_t *event_pollset;
214
215 /*
216  * The chain of connections to be shutdown by a worker thread (deferred),
217  * linked list updated atomically.
218  */
219 static event_conn_state_t *volatile defer_linger_chain;
220
221 struct event_conn_state_t {
222     /** APR_RING of expiration timeouts */
223     APR_RING_ENTRY(event_conn_state_t) timeout_list;
224     /** the time when the entry was queued */
225     apr_time_t queue_timestamp;
226     /** connection record this struct refers to */
227     conn_rec *c;
228     /** request record (if any) this struct refers to */
229     request_rec *r;
230     /** server config this struct refers to */
231     event_srv_cfg *sc;
232     /** is the current conn_rec suspended?  (disassociated with
233      * a particular MPM thread; for suspend_/resume_connection
234      * hooks)
235      */
236     int suspended;
237     /** memory pool to allocate from */
238     apr_pool_t *p;
239     /** bucket allocator */
240     apr_bucket_alloc_t *bucket_alloc;
241     /** poll file descriptor information */
242     apr_pollfd_t pfd;
243     /** public parts of the connection state */
244     conn_state_t pub;
245     /** chaining in defer_linger_chain */
246     struct event_conn_state_t *chain;
247 };
248
249 APR_RING_HEAD(timeout_head_t, event_conn_state_t);
250
251 struct timeout_queue {
252     struct timeout_head_t head;
253     apr_interval_time_t timeout;
254     apr_uint32_t count;         /* for this queue */
255     apr_uint32_t *total;        /* for all chained/related queues */
256     struct timeout_queue *next; /* chaining */
257 };
258 /*
259  * Several timeout queues that use different timeouts, so that we always can
260  * simply append to the end.
261  *   write_completion_q uses vhost's TimeOut
262  *   keepalive_q        uses vhost's KeepAliveTimeOut
263  *   linger_q           uses MAX_SECS_TO_LINGER
264  *   short_linger_q     uses SECONDS_TO_LINGER
265  */
266 static struct timeout_queue *write_completion_q,
267                             *keepalive_q,
268                             *linger_q,
269                             *short_linger_q;
270 static volatile apr_time_t  queues_next_expiry;
271
272 /* Prevent extra poll/wakeup calls for timeouts close in the future (queues
273  * have the granularity of a second anyway).
274  * XXX: Wouldn't 0.5s (instead of 0.1s) be "enough"?
275  */
276 #define TIMEOUT_FUDGE_FACTOR apr_time_from_msec(100)
277
278 /*
279  * Macros for accessing struct timeout_queue.
280  * For TO_QUEUE_APPEND and TO_QUEUE_REMOVE, timeout_mutex must be held.
281  */
282 static void TO_QUEUE_APPEND(struct timeout_queue *q, event_conn_state_t *el)
283 {
284     apr_time_t q_expiry;
285     apr_time_t next_expiry;
286
287     APR_RING_INSERT_TAIL(&q->head, el, event_conn_state_t, timeout_list);
288     apr_atomic_inc32(q->total);
289     ++q->count;
290
291     /* Cheaply update the overall queues' next expiry according to the
292      * first entry of this queue (oldest), if necessary.
293      */
294     el = APR_RING_FIRST(&q->head);
295     q_expiry = el->queue_timestamp + q->timeout;
296     next_expiry = queues_next_expiry;
297     if (!next_expiry || next_expiry > q_expiry + TIMEOUT_FUDGE_FACTOR) {
298         queues_next_expiry = q_expiry;
299         /* Unblock the poll()ing listener for it to update its timeout. */
300         if (listener_is_wakeable) {
301             apr_pollset_wakeup(event_pollset);
302         }
303     }
304 }
305
306 static void TO_QUEUE_REMOVE(struct timeout_queue *q, event_conn_state_t *el)
307 {
308     APR_RING_REMOVE(el, timeout_list);
309     APR_RING_ELEM_INIT(el, timeout_list);
310     apr_atomic_dec32(q->total);
311     --q->count;
312 }
313
314 static struct timeout_queue *TO_QUEUE_MAKE(apr_pool_t *p, apr_time_t t,
315                                            struct timeout_queue *ref)
316 {
317     struct timeout_queue *q;
318                                            
319     q = apr_pcalloc(p, sizeof *q);
320     APR_RING_INIT(&q->head, event_conn_state_t, timeout_list);
321     q->total = (ref) ? ref->total : apr_pcalloc(p, sizeof *q->total);
322     q->timeout = t;
323
324     return q;
325 }
326
327 #define TO_QUEUE_ELEM_INIT(el) \
328     APR_RING_ELEM_INIT((el), timeout_list)
329
330 /* The structure used to pass unique initialization info to each thread */
331 typedef struct
332 {
333     int pslot;  /* process slot */
334     int tslot;  /* worker slot of the thread */
335 } proc_info;
336
337 /* Structure used to pass information to the thread responsible for
338  * creating the rest of the threads.
339  */
340 typedef struct
341 {
342     apr_thread_t **threads;
343     apr_thread_t *listener;
344     int child_num_arg;
345     apr_threadattr_t *threadattr;
346 } thread_starter;
347
348 typedef enum
349 {
350     PT_CSD,
351     PT_ACCEPT
352 } poll_type_e;
353
354 typedef struct
355 {
356     poll_type_e type;
357     void *baton;
358 } listener_poll_type;
359
360 /* data retained by event across load/unload of the module
361  * allocated on first call to pre-config hook; located on
362  * subsequent calls to pre-config hook
363  */
364 typedef struct event_retained_data {
365     ap_unixd_mpm_retained_data *mpm;
366
367     int first_server_limit;
368     int first_thread_limit;
369     int sick_child_detected;
370     int maxclients_reported;
371     /*
372      * The max child slot ever assigned, preserved across restarts.  Necessary
373      * to deal with MaxRequestWorkers changes across AP_SIG_GRACEFUL restarts.
374      * We use this value to optimize routines that have to scan the entire
375      * scoreboard.
376      */
377     int max_daemons_limit;
378
379     /*
380      * All running workers, active and shutting down, including those that
381      * may be left from before a graceful restart.
382      * Not kept up-to-date when shutdown is pending.
383      */
384     int total_daemons;
385
386     /*
387      * idle_spawn_rate is the number of children that will be spawned on the
388      * next maintenance cycle if there aren't enough idle servers.  It is
389      * maintained per listeners bucket, doubled up to MAX_SPAWN_RATE, and
390      * reset only when a cycle goes by without the need to spawn.
391      */
392     int *idle_spawn_rate;
393 #ifndef MAX_SPAWN_RATE
394 #define MAX_SPAWN_RATE        (32)
395 #endif
396     int hold_off_on_exponential_spawning;
397 } event_retained_data;
398 static event_retained_data *retained;
399  
400 typedef struct event_child_bucket {
401     ap_pod_t *pod;
402     ap_listen_rec *listeners;
403 } event_child_bucket;
404 static event_child_bucket *all_buckets, /* All listeners buckets */
405                           *my_bucket;   /* Current child bucket */
406
407 struct event_srv_cfg_s {
408     struct timeout_queue *wc_q,
409                          *ka_q;
410 };
411
412 #define ID_FROM_CHILD_THREAD(c, t)    ((c * thread_limit) + t)
413
414 /* The event MPM respects a couple of runtime flags that can aid
415  * in debugging. Setting the -DNO_DETACH flag will prevent the root process
416  * from detaching from its controlling terminal. Additionally, setting
417  * the -DONE_PROCESS flag (which implies -DNO_DETACH) will get you the
418  * child_main loop running in the process which originally started up.
419  * This gives you a pretty nice debugging environment.  (You'll get a SIGHUP
420  * early in standalone_main; just continue through.  This is the server
421  * trying to kill off any child processes which it might have lying
422  * around --- Apache doesn't keep track of their pids, it just sends
423  * SIGHUP to the process group, ignoring it in the root process.
424  * Continue through and you'll be fine.).
425  */
426
427 static int one_process = 0;
428
429 #ifdef DEBUG_SIGSTOP
430 int raise_sigstop_flags;
431 #endif
432
433 static apr_pool_t *pconf;       /* Pool for config stuff */
434 static apr_pool_t *pchild;      /* Pool for httpd child stuff */
435
436 static pid_t ap_my_pid;         /* Linux getpid() doesn't work except in main
437                                    thread. Use this instead */
438 static pid_t parent_pid;
439 static apr_os_thread_t *listener_os_thread;
440
441 /* The LISTENER_SIGNAL signal will be sent from the main thread to the
442  * listener thread to wake it up for graceful termination (what a child
443  * process from an old generation does when the admin does "apachectl
444  * graceful").  This signal will be blocked in all threads of a child
445  * process except for the listener thread.
446  */
447 #define LISTENER_SIGNAL     SIGHUP
448
449 /* An array of socket descriptors in use by each thread used to
450  * perform a non-graceful (forced) shutdown of the server.
451  */
452 static apr_socket_t **worker_sockets;
453
454 static void disable_listensocks(int process_slot)
455 {
456     int i;
457     for (i = 0; i < num_listensocks; i++) {
458         apr_pollset_remove(event_pollset, &listener_pollfd[i]);
459     }
460     ap_scoreboard_image->parent[process_slot].not_accepting = 1;
461 }
462
463 static void enable_listensocks(int process_slot)
464 {
465     int i;
466     if (listener_may_exit) {
467         return;
468     }
469     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(00457)
470                  "Accepting new connections again: "
471                  "%u active conns (%u lingering/%u clogged/%u suspended), "
472                  "%u idle workers",
473                  apr_atomic_read32(&connection_count),
474                  apr_atomic_read32(&lingering_count),
475                  apr_atomic_read32(&clogged_count),
476                  apr_atomic_read32(&suspended_count),
477                  ap_queue_info_get_idlers(worker_queue_info));
478     for (i = 0; i < num_listensocks; i++)
479         apr_pollset_add(event_pollset, &listener_pollfd[i]);
480     /*
481      * XXX: This is not yet optimal. If many workers suddenly become available,
482      * XXX: the parent may kill some processes off too soon.
483      */
484     ap_scoreboard_image->parent[process_slot].not_accepting = 0;
485 }
486
487 static void abort_socket_nonblocking(apr_socket_t *csd)
488 {
489     apr_status_t rv;
490     apr_socket_timeout_set(csd, 0);
491 #if defined(SOL_SOCKET) && defined(SO_LINGER)
492     /* This socket is over now, and we don't want to block nor linger
493      * anymore, so reset it. A normal close could still linger in the
494      * system, while RST is fast, nonblocking, and what the peer will
495      * get if it sends us further data anyway.
496      */
497     {
498         apr_os_sock_t osd = -1;
499         struct linger opt;
500         opt.l_onoff = 1;
501         opt.l_linger = 0; /* zero timeout is RST */
502         apr_os_sock_get(&osd, csd);
503         setsockopt(osd, SOL_SOCKET, SO_LINGER, (void *)&opt, sizeof opt);
504     }
505 #endif
506     rv = apr_socket_close(csd);
507     if (rv != APR_SUCCESS) {
508         ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf, APLOGNO(00468)
509                      "error closing socket");
510         AP_DEBUG_ASSERT(0);
511     }
512 }
513
514 static void close_worker_sockets(void)
515 {
516     int i;
517     for (i = 0; i < threads_per_child; i++) {
518         apr_socket_t *csd = worker_sockets[i];
519         if (csd) {
520             worker_sockets[i] = NULL;
521             abort_socket_nonblocking(csd);
522         }
523     }
524     for (;;) {
525         event_conn_state_t *cs = defer_linger_chain;
526         if (!cs) {
527             break;
528         }
529         if (apr_atomic_casptr((void *)&defer_linger_chain, cs->chain,
530                               cs) != cs) {
531             /* Race lost, try again */
532             continue;
533         }
534         cs->chain = NULL;
535         abort_socket_nonblocking(cs->pfd.desc.s);
536     }
537 }
538
539 static void wakeup_listener(void)
540 {
541     listener_may_exit = 1;
542     if (!listener_os_thread) {
543         /* XXX there is an obscure path that this doesn't handle perfectly:
544          *     right after listener thread is created but before
545          *     listener_os_thread is set, the first worker thread hits an
546          *     error and starts graceful termination
547          */
548         return;
549     }
550
551     /* Unblock the listener if it's poll()ing */
552     if (listener_is_wakeable) {
553         apr_pollset_wakeup(event_pollset);
554     }
555
556     /* unblock the listener if it's waiting for a worker */
557     ap_queue_info_term(worker_queue_info);
558
559     /*
560      * we should just be able to "kill(ap_my_pid, LISTENER_SIGNAL)" on all
561      * platforms and wake up the listener thread since it is the only thread
562      * with SIGHUP unblocked, but that doesn't work on Linux
563      */
564 #ifdef HAVE_PTHREAD_KILL
565     pthread_kill(*listener_os_thread, LISTENER_SIGNAL);
566 #else
567     kill(ap_my_pid, LISTENER_SIGNAL);
568 #endif
569 }
570
571 #define ST_INIT              0
572 #define ST_GRACEFUL          1
573 #define ST_UNGRACEFUL        2
574
575 static int terminate_mode = ST_INIT;
576
577 static void signal_threads(int mode)
578 {
579     if (terminate_mode == mode) {
580         return;
581     }
582     terminate_mode = mode;
583     retained->mpm->mpm_state = AP_MPMQ_STOPPING;
584
585     /* in case we weren't called from the listener thread, wake up the
586      * listener thread
587      */
588     wakeup_listener();
589
590     /* for ungraceful termination, let the workers exit now;
591      * for graceful termination, the listener thread will notify the
592      * workers to exit once it has stopped accepting new connections
593      */
594     if (mode == ST_UNGRACEFUL) {
595         workers_may_exit = 1;
596         ap_queue_interrupt_all(worker_queue);
597         close_worker_sockets(); /* forcefully kill all current connections */
598     }
599 }
600
601 static int event_query(int query_code, int *result, apr_status_t *rv)
602 {
603     *rv = APR_SUCCESS;
604     switch (query_code) {
605     case AP_MPMQ_MAX_DAEMON_USED:
606         *result = retained->max_daemons_limit;
607         break;
608     case AP_MPMQ_IS_THREADED:
609         *result = AP_MPMQ_STATIC;
610         break;
611     case AP_MPMQ_IS_FORKED:
612         *result = AP_MPMQ_DYNAMIC;
613         break;
614     case AP_MPMQ_IS_ASYNC:
615         *result = 1;
616         break;
617     case AP_MPMQ_HARD_LIMIT_DAEMONS:
618         *result = server_limit;
619         break;
620     case AP_MPMQ_HARD_LIMIT_THREADS:
621         *result = thread_limit;
622         break;
623     case AP_MPMQ_MAX_THREADS:
624         *result = threads_per_child;
625         break;
626     case AP_MPMQ_MIN_SPARE_DAEMONS:
627         *result = 0;
628         break;
629     case AP_MPMQ_MIN_SPARE_THREADS:
630         *result = min_spare_threads;
631         break;
632     case AP_MPMQ_MAX_SPARE_DAEMONS:
633         *result = 0;
634         break;
635     case AP_MPMQ_MAX_SPARE_THREADS:
636         *result = max_spare_threads;
637         break;
638     case AP_MPMQ_MAX_REQUESTS_DAEMON:
639         *result = ap_max_requests_per_child;
640         break;
641     case AP_MPMQ_MAX_DAEMONS:
642         *result = active_daemons_limit;
643         break;
644     case AP_MPMQ_MPM_STATE:
645         *result = retained->mpm->mpm_state;
646         break;
647     case AP_MPMQ_GENERATION:
648         *result = retained->mpm->my_generation;
649         break;
650     default:
651         *rv = APR_ENOTIMPL;
652         break;
653     }
654     return OK;
655 }
656
657 static void event_note_child_killed(int childnum, pid_t pid, ap_generation_t gen)
658 {
659     if (childnum != -1) { /* child had a scoreboard slot? */
660         ap_run_child_status(ap_server_conf,
661                             ap_scoreboard_image->parent[childnum].pid,
662                             ap_scoreboard_image->parent[childnum].generation,
663                             childnum, MPM_CHILD_EXITED);
664         ap_scoreboard_image->parent[childnum].pid = 0;
665     }
666     else {
667         ap_run_child_status(ap_server_conf, pid, gen, -1, MPM_CHILD_EXITED);
668     }
669 }
670
671 static void event_note_child_started(int slot, pid_t pid)
672 {
673     ap_scoreboard_image->parent[slot].pid = pid;
674     ap_run_child_status(ap_server_conf,
675                         ap_scoreboard_image->parent[slot].pid,
676                         retained->mpm->my_generation, slot, MPM_CHILD_STARTED);
677 }
678
679 static const char *event_get_name(void)
680 {
681     return "event";
682 }
683
684 /* a clean exit from a child with proper cleanup */
685 static void clean_child_exit(int code) __attribute__ ((noreturn));
686 static void clean_child_exit(int code)
687 {
688     retained->mpm->mpm_state = AP_MPMQ_STOPPING;
689     if (pchild) {
690         apr_pool_destroy(pchild);
691     }
692
693     if (one_process) {
694         event_note_child_killed(/* slot */ 0, 0, 0);
695     }
696
697     exit(code);
698 }
699
700 static void just_die(int sig)
701 {
702     clean_child_exit(0);
703 }
704
705 /*****************************************************************
706  * Connection structures and accounting...
707  */
708
709 static int child_fatal;
710
711 static apr_status_t decrement_connection_count(void *cs_)
712 {
713     event_conn_state_t *cs = cs_;
714     switch (cs->pub.state) {
715         case CONN_STATE_LINGER_NORMAL:
716         case CONN_STATE_LINGER_SHORT:
717             apr_atomic_dec32(&lingering_count);
718             break;
719         case CONN_STATE_SUSPENDED:
720             apr_atomic_dec32(&suspended_count);
721             break;
722         default:
723             break;
724     }
725     /* Unblock the listener if it's waiting for connection_count = 0 */
726     if (!apr_atomic_dec32(&connection_count)
727              && listener_is_wakeable && listener_may_exit) {
728         apr_pollset_wakeup(event_pollset);
729     }
730     return APR_SUCCESS;
731 }
732
733 static void notify_suspend(event_conn_state_t *cs)
734 {
735     ap_run_suspend_connection(cs->c, cs->r);
736     cs->suspended = 1;
737     cs->c->sbh = NULL;
738 }
739
740 static void notify_resume(event_conn_state_t *cs, ap_sb_handle_t *sbh)
741 {
742     cs->c->sbh = sbh;
743     cs->suspended = 0;
744     ap_run_resume_connection(cs->c, cs->r);
745 }
746
747 /*
748  * Close our side of the connection, flushing data to the client first.
749  * Pre-condition: cs is not in any timeout queue and not in the pollset,
750  *                timeout_mutex is not locked
751  * return: 0 if connection is fully closed,
752  *         1 if connection is lingering
753  * May only be called by worker thread.
754  */
755 static int start_lingering_close_blocking(event_conn_state_t *cs)
756 {
757     apr_status_t rv;
758     struct timeout_queue *q;
759     apr_socket_t *csd = cs->pfd.desc.s;
760
761     if (ap_start_lingering_close(cs->c)) {
762         notify_suspend(cs);
763         apr_socket_close(csd);
764         ap_push_pool(worker_queue_info, cs->p);
765         return 0;
766     }
767
768 #ifdef AP_DEBUG
769     {
770         rv = apr_socket_timeout_set(csd, 0);
771         AP_DEBUG_ASSERT(rv == APR_SUCCESS);
772     }
773 #else
774     apr_socket_timeout_set(csd, 0);
775 #endif
776
777     cs->queue_timestamp = apr_time_now();
778     /*
779      * If some module requested a shortened waiting period, only wait for
780      * 2s (SECONDS_TO_LINGER). This is useful for mitigating certain
781      * DoS attacks.
782      */
783     if (apr_table_get(cs->c->notes, "short-lingering-close")) {
784         q = short_linger_q;
785         cs->pub.state = CONN_STATE_LINGER_SHORT;
786     }
787     else {
788         q = linger_q;
789         cs->pub.state = CONN_STATE_LINGER_NORMAL;
790     }
791     apr_atomic_inc32(&lingering_count);
792     notify_suspend(cs);
793
794     cs->pfd.reqevents = (
795             cs->pub.sense == CONN_SENSE_WANT_WRITE ? APR_POLLOUT :
796                     APR_POLLIN) | APR_POLLHUP | APR_POLLERR;
797     cs->pub.sense = CONN_SENSE_DEFAULT;
798     apr_thread_mutex_lock(timeout_mutex);
799     TO_QUEUE_APPEND(q, cs);
800     rv = apr_pollset_add(event_pollset, &cs->pfd);
801     if (rv != APR_SUCCESS && !APR_STATUS_IS_EEXIST(rv)) {
802         TO_QUEUE_REMOVE(q, cs);
803         apr_thread_mutex_unlock(timeout_mutex);
804         ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf, APLOGNO(03092)
805                      "start_lingering_close: apr_pollset_add failure");
806         apr_socket_close(cs->pfd.desc.s);
807         ap_push_pool(worker_queue_info, cs->p);
808         return 0;
809     }
810     apr_thread_mutex_unlock(timeout_mutex);
811     return 1;
812 }
813
814 /*
815  * Defer flush and close of the connection by adding it to defer_linger_chain,
816  * for a worker to grab it and do the job (should that be blocking).
817  * Pre-condition: cs is not in any timeout queue and not in the pollset,
818  *                timeout_mutex is not locked
819  * return: 1 connection is alive (but aside and about to linger)
820  * May be called by listener thread.
821  */
822 static int start_lingering_close_nonblocking(event_conn_state_t *cs)
823 {
824     event_conn_state_t *chain;
825     for (;;) {
826         cs->chain = chain = defer_linger_chain;
827         if (apr_atomic_casptr((void *)&defer_linger_chain, cs,
828                               chain) != chain) {
829             /* Race lost, try again */
830             continue;
831         }
832         return 1;
833     }
834 }
835
836 /*
837  * forcibly close a lingering connection after the lingering period has
838  * expired
839  * Pre-condition: cs is not in any timeout queue and not in the pollset
840  * return: irrelevant (need same prototype as start_lingering_close)
841  */
842 static int stop_lingering_close(event_conn_state_t *cs)
843 {
844     apr_socket_t *csd = ap_get_conn_socket(cs->c);
845     ap_log_error(APLOG_MARK, APLOG_TRACE4, 0, ap_server_conf,
846                  "socket reached timeout in lingering-close state");
847     abort_socket_nonblocking(csd);
848     ap_push_pool(worker_queue_info, cs->p);
849     if (dying)
850         ap_queue_interrupt_one(worker_queue);
851     return 0;
852 }
853
854 /*
855  * This runs before any non-MPM cleanup code on the connection;
856  * if the connection is currently suspended as far as modules
857  * know, provide notification of resumption.
858  */
859 static apr_status_t ptrans_pre_cleanup(void *dummy)
860 {
861     event_conn_state_t *cs = dummy;
862
863     if (cs->suspended) {
864         notify_resume(cs, NULL);
865     }
866     return APR_SUCCESS;
867 }
868
869 /*
870  * event_pre_read_request() and event_request_cleanup() track the
871  * current r for a given connection.
872  */
873 static apr_status_t event_request_cleanup(void *dummy)
874 {
875     conn_rec *c = dummy;
876     event_conn_state_t *cs = ap_get_module_config(c->conn_config,
877                                                   &mpm_event_module);
878
879     cs->r = NULL;
880     return APR_SUCCESS;
881 }
882
883 static void event_pre_read_request(request_rec *r, conn_rec *c)
884 {
885     event_conn_state_t *cs = ap_get_module_config(c->conn_config,
886                                                   &mpm_event_module);
887
888     cs->r = r;
889     cs->sc = ap_get_module_config(ap_server_conf->module_config,
890                                   &mpm_event_module);
891     apr_pool_cleanup_register(r->pool, c, event_request_cleanup,
892                               apr_pool_cleanup_null);
893 }
894
895 /*
896  * event_post_read_request() tracks the current server config for a
897  * given request.
898  */
899 static int event_post_read_request(request_rec *r)
900 {
901     conn_rec *c = r->connection;
902     event_conn_state_t *cs = ap_get_module_config(c->conn_config,
903                                                   &mpm_event_module);
904
905     /* To preserve legacy behaviour (consistent with other MPMs), use
906      * the keepalive timeout from the base server (first on this IP:port)
907      * when none is explicitly configured on this server.
908      */
909     if (r->server->keep_alive_timeout_set) {
910         cs->sc = ap_get_module_config(r->server->module_config,
911                                       &mpm_event_module);
912     }
913     else {
914         cs->sc = ap_get_module_config(c->base_server->module_config,
915                                       &mpm_event_module);
916     }
917     return OK;
918 }
919
920 /*
921  * process one connection in the worker
922  */
923 static void process_socket(apr_thread_t *thd, apr_pool_t * p, apr_socket_t * sock,
924                           event_conn_state_t * cs, int my_child_num,
925                           int my_thread_num)
926 {
927     conn_rec *c;
928     long conn_id = ID_FROM_CHILD_THREAD(my_child_num, my_thread_num);
929     int rc;
930     ap_sb_handle_t *sbh;
931
932     /* XXX: This will cause unbounded mem usage for long lasting connections */
933     ap_create_sb_handle(&sbh, p, my_child_num, my_thread_num);
934
935     if (cs == NULL) {           /* This is a new connection */
936         listener_poll_type *pt = apr_pcalloc(p, sizeof(*pt));
937         cs = apr_pcalloc(p, sizeof(event_conn_state_t));
938         cs->bucket_alloc = apr_bucket_alloc_create(p);
939         c = ap_run_create_connection(p, ap_server_conf, sock,
940                                      conn_id, sbh, cs->bucket_alloc);
941         if (!c) {
942             ap_push_pool(worker_queue_info, p);
943             return;
944         }
945         apr_atomic_inc32(&connection_count);
946         apr_pool_cleanup_register(c->pool, cs, decrement_connection_count,
947                                   apr_pool_cleanup_null);
948         ap_set_module_config(c->conn_config, &mpm_event_module, cs);
949         c->current_thread = thd;
950         cs->c = c;
951         c->cs = &(cs->pub);
952         cs->p = p;
953         cs->sc = ap_get_module_config(ap_server_conf->module_config,
954                                       &mpm_event_module);
955         cs->pfd.desc_type = APR_POLL_SOCKET;
956         cs->pfd.reqevents = APR_POLLIN;
957         cs->pfd.desc.s = sock;
958         pt->type = PT_CSD;
959         pt->baton = cs;
960         cs->pfd.client_data = pt;
961         apr_pool_pre_cleanup_register(p, cs, ptrans_pre_cleanup);
962         TO_QUEUE_ELEM_INIT(cs);
963
964         ap_update_vhost_given_ip(c);
965
966         rc = ap_run_pre_connection(c, sock);
967         if (rc != OK && rc != DONE) {
968             ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(00469)
969                           "process_socket: connection aborted");
970             c->aborted = 1;
971         }
972
973         /**
974          * XXX If the platform does not have a usable way of bundling
975          * accept() with a socket readability check, like Win32,
976          * and there are measurable delays before the
977          * socket is readable due to the first data packet arriving,
978          * it might be better to create the cs on the listener thread
979          * with the state set to CONN_STATE_CHECK_REQUEST_LINE_READABLE
980          *
981          * FreeBSD users will want to enable the HTTP accept filter
982          * module in their kernel for the highest performance
983          * When the accept filter is active, sockets are kept in the
984          * kernel until a HTTP request is received.
985          */
986         cs->pub.state = CONN_STATE_READ_REQUEST_LINE;
987
988         cs->pub.sense = CONN_SENSE_DEFAULT;
989     }
990     else {
991         c = cs->c;
992         notify_resume(cs, sbh);
993         c->current_thread = thd;
994         /* Subsequent request on a conn, and thread number is part of ID */
995         c->id = conn_id;
996     }
997
998     rc = OK;
999     if (c->aborted || cs->pub.state == CONN_STATE_LINGER) {
1000         /* do lingering close below */
1001         cs->pub.state = CONN_STATE_LINGER;
1002     }
1003     else if (c->clogging_input_filters) {
1004         /* Since we have an input filter which 'clogs' the input stream,
1005          * like mod_ssl used to, lets just do the normal read from input
1006          * filters, like the Worker MPM does. Filters that need to write
1007          * where they would otherwise read, or read where they would
1008          * otherwise write, should set the sense appropriately.
1009          */
1010         apr_atomic_inc32(&clogged_count);
1011         rc = ap_run_process_connection(c);
1012         apr_atomic_dec32(&clogged_count);
1013         if (rc == DONE) {
1014             rc = OK;
1015         }
1016     }
1017     else if (cs->pub.state == CONN_STATE_READ_REQUEST_LINE) {
1018 read_request:
1019         rc = ap_run_process_connection(c);
1020         if (rc == DONE) {
1021             rc = OK;
1022         }
1023     }
1024     /*
1025      * The process_connection hooks above should set the connection state
1026      * appropriately upon return, for event MPM to either:
1027      * - do lingering close (CONN_STATE_LINGER),
1028      * - wait for readability of the next request with respect to the keepalive
1029      *   timeout (CONN_STATE_CHECK_REQUEST_LINE_READABLE),
1030      * - keep flushing the output filters stack in nonblocking mode, and then
1031      *   if required wait for read/write-ability of the underlying socket with
1032      *   respect to its own timeout (CONN_STATE_WRITE_COMPLETION); since write
1033      *   completion at some point may require reads (e.g. SSL_ERROR_WANT_READ),
1034      *   an output filter can set the sense to CONN_SENSE_WANT_READ at any time
1035      *   for event MPM to do the right thing,
1036      * - suspend the connection (SUSPENDED) such that it now interracts with
1037      *   the MPM through suspend/resume_connection() hooks, and/or registered
1038      *   poll callbacks (PT_USER), and/or registered timed callbacks triggered
1039      *   by timer events.
1040      * If a process_connection hook returns an error or no hook sets the state
1041      * to one of the above expected value, we forcibly close the connection w/
1042      * CONN_STATE_LINGER.  This covers the cases where no process_connection
1043      * hook executes (DECLINED), or one returns OK w/o touching the state (i.e.
1044      * CONN_STATE_READ_REQUEST_LINE remains after the call) which can happen
1045      * with third-party modules not updated to work specifically with event MPM
1046      * while this was expected to do lingering close unconditionally with
1047      * worker or prefork MPMs for instance.
1048      */
1049     if (rc != OK || (cs->pub.state != CONN_STATE_LINGER
1050                      && cs->pub.state != CONN_STATE_WRITE_COMPLETION
1051                      && cs->pub.state != CONN_STATE_CHECK_REQUEST_LINE_READABLE
1052                      && cs->pub.state != CONN_STATE_SUSPENDED)) {
1053         ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(10111)
1054                       "process_socket: connection processing %s: closing",
1055                       rc ? apr_psprintf(c->pool, "returned error %i", rc)
1056                          : apr_psprintf(c->pool, "unexpected state %i",
1057                                                  (int)cs->pub.state));
1058         cs->pub.state = CONN_STATE_LINGER;
1059     }
1060
1061     if (cs->pub.state == CONN_STATE_WRITE_COMPLETION) {
1062         ap_filter_t *output_filter = c->output_filters;
1063         apr_status_t rv;
1064         ap_update_child_status(sbh, SERVER_BUSY_WRITE, NULL);
1065         while (output_filter->next != NULL) {
1066             output_filter = output_filter->next;
1067         }
1068         rv = output_filter->frec->filter_func.out_func(output_filter, NULL);
1069         if (rv != APR_SUCCESS) {
1070             ap_log_cerror(APLOG_MARK, APLOG_DEBUG, rv, c, APLOGNO(00470)
1071                           "network write failure in core output filter");
1072             cs->pub.state = CONN_STATE_LINGER;
1073         }
1074         else if (c->data_in_output_filters) {
1075             /* Still in WRITE_COMPLETION_STATE:
1076              * Set a write timeout for this connection, and let the
1077              * event thread poll for writeability.
1078              */
1079             cs->queue_timestamp = apr_time_now();
1080             notify_suspend(cs);
1081
1082             if (cs->pub.sense == CONN_SENSE_WANT_READ) {
1083                 cs->pfd.reqevents = APR_POLLIN;
1084             }
1085             else {
1086                 cs->pfd.reqevents = APR_POLLOUT;
1087             }
1088             /* POLLHUP/ERR are usually returned event only (ignored here), but
1089              * some pollset backends may require them in reqevents to do the
1090              * right thing, so it shouldn't hurt.
1091              */
1092             cs->pfd.reqevents |= APR_POLLHUP | APR_POLLERR;
1093             cs->pub.sense = CONN_SENSE_DEFAULT;
1094
1095             apr_thread_mutex_lock(timeout_mutex);
1096             TO_QUEUE_APPEND(cs->sc->wc_q, cs);
1097             rc = apr_pollset_add(event_pollset, &cs->pfd);
1098             if (rc != APR_SUCCESS && !APR_STATUS_IS_EEXIST(rc)) {
1099                 TO_QUEUE_REMOVE(cs->sc->wc_q, cs);
1100                 apr_thread_mutex_unlock(timeout_mutex);
1101                 ap_log_error(APLOG_MARK, APLOG_ERR, rc, ap_server_conf, APLOGNO(03465)
1102                              "process_socket: apr_pollset_add failure for "
1103                              "write completion");
1104                 apr_socket_close(cs->pfd.desc.s);
1105                 ap_push_pool(worker_queue_info, cs->p);
1106             }
1107             else {
1108                 apr_thread_mutex_unlock(timeout_mutex);
1109             }
1110             return;
1111         }
1112         else if (c->keepalive != AP_CONN_KEEPALIVE || c->aborted ||
1113                  listener_may_exit) {
1114             cs->pub.state = CONN_STATE_LINGER;
1115         }
1116         else if (c->data_in_input_filters) {
1117             cs->pub.state = CONN_STATE_READ_REQUEST_LINE;
1118             goto read_request;
1119         }
1120         else {
1121             cs->pub.state = CONN_STATE_CHECK_REQUEST_LINE_READABLE;
1122         }
1123     }
1124
1125     if (cs->pub.state == CONN_STATE_LINGER) {
1126         start_lingering_close_blocking(cs);
1127     }
1128     else if (cs->pub.state == CONN_STATE_CHECK_REQUEST_LINE_READABLE) {
1129         /* It greatly simplifies the logic to use a single timeout value per q
1130          * because the new element can just be added to the end of the list and
1131          * it will stay sorted in expiration time sequence.  If brand new
1132          * sockets are sent to the event thread for a readability check, this
1133          * will be a slight behavior change - they use the non-keepalive
1134          * timeout today.  With a normal client, the socket will be readable in
1135          * a few milliseconds anyway.
1136          */
1137         cs->queue_timestamp = apr_time_now();
1138         notify_suspend(cs);
1139
1140         /* Add work to pollset. */
1141         cs->pfd.reqevents = APR_POLLIN;
1142         apr_thread_mutex_lock(timeout_mutex);
1143         TO_QUEUE_APPEND(cs->sc->ka_q, cs);
1144         rc = apr_pollset_add(event_pollset, &cs->pfd);
1145         if (rc != APR_SUCCESS && !APR_STATUS_IS_EEXIST(rc)) {
1146             TO_QUEUE_REMOVE(cs->sc->ka_q, cs);
1147             apr_thread_mutex_unlock(timeout_mutex);
1148             ap_log_error(APLOG_MARK, APLOG_ERR, rc, ap_server_conf, APLOGNO(03093)
1149                          "process_socket: apr_pollset_add failure for "
1150                          "keep alive");
1151             apr_socket_close(cs->pfd.desc.s);
1152             ap_push_pool(worker_queue_info, cs->p);
1153             return;
1154         }
1155         apr_thread_mutex_unlock(timeout_mutex);
1156     }
1157     else if (cs->pub.state == CONN_STATE_SUSPENDED) {
1158         apr_atomic_inc32(&suspended_count);
1159         notify_suspend(cs);
1160     }
1161 }
1162
1163 /* conns_this_child has gone to zero or below.  See if the admin coded
1164    "MaxConnectionsPerChild 0", and keep going in that case.  Doing it this way
1165    simplifies the hot path in worker_thread */
1166 static void check_infinite_requests(void)
1167 {
1168     if (ap_max_requests_per_child) {
1169         ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, ap_server_conf,
1170                      "Stopping process due to MaxConnectionsPerChild");
1171         signal_threads(ST_GRACEFUL);
1172     }
1173     else {
1174         /* keep going */
1175         conns_this_child = APR_INT32_MAX;
1176     }
1177 }
1178
1179 static void close_listeners(int process_slot, int *closed)
1180 {
1181     if (!*closed) {
1182         int i;
1183         disable_listensocks(process_slot);
1184         ap_close_listeners_ex(my_bucket->listeners);
1185         *closed = 1;
1186         dying = 1;
1187         ap_scoreboard_image->parent[process_slot].quiescing = 1;
1188         for (i = 0; i < threads_per_child; ++i) {
1189             ap_update_child_status_from_indexes(process_slot, i,
1190                                                 SERVER_GRACEFUL, NULL);
1191         }
1192         /* wake up the main thread */
1193         kill(ap_my_pid, SIGTERM);
1194
1195         ap_free_idle_pools(worker_queue_info);
1196         ap_queue_interrupt_all(worker_queue);
1197     }
1198 }
1199
1200 static void unblock_signal(int sig)
1201 {
1202     sigset_t sig_mask;
1203
1204     sigemptyset(&sig_mask);
1205     sigaddset(&sig_mask, sig);
1206 #if defined(SIGPROCMASK_SETS_THREAD_MASK)
1207     sigprocmask(SIG_UNBLOCK, &sig_mask, NULL);
1208 #else
1209     pthread_sigmask(SIG_UNBLOCK, &sig_mask, NULL);
1210 #endif
1211 }
1212
1213 static void dummy_signal_handler(int sig)
1214 {
1215     /* XXX If specifying SIG_IGN is guaranteed to unblock a syscall,
1216      *     then we don't need this goofy function.
1217      */
1218 }
1219
1220
1221 static apr_status_t init_pollset(apr_pool_t *p)
1222 {
1223     ap_listen_rec *lr;
1224     listener_poll_type *pt;
1225     int i = 0;
1226
1227     listener_pollfd = apr_palloc(p, sizeof(apr_pollfd_t) * num_listensocks);
1228     for (lr = my_bucket->listeners; lr != NULL; lr = lr->next, i++) {
1229         apr_pollfd_t *pfd;
1230         AP_DEBUG_ASSERT(i < num_listensocks);
1231         pfd = &listener_pollfd[i];
1232         pt = apr_pcalloc(p, sizeof(*pt));
1233         pfd->desc_type = APR_POLL_SOCKET;
1234         pfd->desc.s = lr->sd;
1235         pfd->reqevents = APR_POLLIN;
1236
1237         pt->type = PT_ACCEPT;
1238         pt->baton = lr;
1239
1240         pfd->client_data = pt;
1241
1242         apr_socket_opt_set(pfd->desc.s, APR_SO_NONBLOCK, 1);
1243         apr_pollset_add(event_pollset, pfd);
1244
1245         lr->accept_func = ap_unixd_accept;
1246     }
1247
1248     return APR_SUCCESS;
1249 }
1250
1251 static apr_status_t push_timer2worker(timer_event_t* te)
1252 {
1253     return ap_queue_push_timer(worker_queue, te);
1254 }
1255
1256 /*
1257  * Pre-condition: cs is neither in event_pollset nor a timeout queue
1258  * this function may only be called by the listener
1259  */
1260 static apr_status_t push2worker(event_conn_state_t *cs, apr_socket_t *csd,
1261                                 apr_pool_t *ptrans)
1262 {
1263     apr_status_t rc;
1264
1265     if (cs) {
1266         csd = cs->pfd.desc.s;
1267         ptrans = cs->p;
1268     }
1269     rc = ap_queue_push(worker_queue, csd, cs, ptrans);
1270     if (rc != APR_SUCCESS) {
1271         ap_log_error(APLOG_MARK, APLOG_CRIT, rc, ap_server_conf, APLOGNO(00471)
1272                      "push2worker: ap_queue_push failed");
1273         /* trash the connection; we couldn't queue the connected
1274          * socket to a worker
1275          */
1276         if (csd) {
1277             abort_socket_nonblocking(csd);
1278         }
1279         if (ptrans) {
1280             ap_push_pool(worker_queue_info, ptrans);
1281         }
1282         signal_threads(ST_GRACEFUL);
1283     }
1284
1285     return rc;
1286 }
1287
1288 /* get_worker:
1289  *     If *have_idle_worker_p == 0, reserve a worker thread, and set
1290  *     *have_idle_worker_p = 1.
1291  *     If *have_idle_worker_p is already 1, will do nothing.
1292  *     If blocking == 1, block if all workers are currently busy.
1293  *     If no worker was available immediately, will set *all_busy to 1.
1294  *     XXX: If there are no workers, we should not block immediately but
1295  *     XXX: close all keep-alive connections first.
1296  */
1297 static void get_worker(int *have_idle_worker_p, int blocking, int *all_busy)
1298 {
1299     apr_status_t rc;
1300
1301     if (*have_idle_worker_p) {
1302         /* already reserved a worker thread - must have hit a
1303          * transient error on a previous pass
1304          */
1305         return;
1306     }
1307
1308     if (blocking)
1309         rc = ap_queue_info_wait_for_idler(worker_queue_info, all_busy);
1310     else
1311         rc = ap_queue_info_try_get_idler(worker_queue_info);
1312
1313     if (rc == APR_SUCCESS || APR_STATUS_IS_EOF(rc)) {
1314         *have_idle_worker_p = 1;
1315     }
1316     else if (!blocking && rc == APR_EAGAIN) {
1317         *all_busy = 1;
1318     }
1319     else {
1320         ap_log_error(APLOG_MARK, APLOG_ERR, rc, ap_server_conf, APLOGNO(00472)
1321                      "ap_queue_info_wait_for_idler failed.  "
1322                      "Attempting to shutdown process gracefully");
1323         signal_threads(ST_GRACEFUL);
1324     }
1325 }
1326
1327 /* Structures to reuse */
1328 static APR_RING_HEAD(timer_free_ring_t, timer_event_t) timer_free_ring;
1329
1330 static apr_skiplist *timer_skiplist;
1331 static volatile apr_time_t timers_next_expiry;
1332
1333 /* Same goal as for TIMEOUT_FUDGE_FACTOR (avoid extra poll calls), but applied
1334  * to timers. Since their timeouts are custom (user defined), we can't be too
1335  * approximative here (hence using 0.01s).
1336  */
1337 #define EVENT_FUDGE_FACTOR apr_time_from_msec(10)
1338
1339 /* The following compare function is used by apr_skiplist_insert() to keep the
1340  * elements (timers) sorted and provide O(log n) complexity (this is also true
1341  * for apr_skiplist_{find,remove}(), but those are not used in MPM event where
1342  * inserted timers are not searched nor removed, but with apr_skiplist_pop()
1343  * which does use any compare function).  It is meant to return 0 when a == b,
1344  * <0 when a < b, and >0 when a > b.  However apr_skiplist_insert() will not
1345  * add duplicates (i.e. a == b), and apr_skiplist_add() is only available in
1346  * APR 1.6, yet multiple timers could possibly be created in the same micro-
1347  * second (duplicates with regard to apr_time_t); therefore we implement the
1348  * compare function to return +1 instead of 0 when compared timers are equal,
1349  * thus duplicates are still added after each other (in order of insertion).
1350  */
1351 static int timer_comp(void *a, void *b)
1352 {
1353     apr_time_t t1 = (apr_time_t) ((timer_event_t *)a)->when;
1354     apr_time_t t2 = (apr_time_t) ((timer_event_t *)b)->when;
1355     AP_DEBUG_ASSERT(t1);
1356     AP_DEBUG_ASSERT(t2);
1357     return ((t1 < t2) ? -1 : 1);
1358 }
1359
1360 static apr_thread_mutex_t *g_timer_skiplist_mtx;
1361
1362 static apr_status_t event_register_timed_callback(apr_time_t t,
1363                                                   ap_mpm_callback_fn_t *cbfn,
1364                                                   void *baton)
1365 {
1366     timer_event_t *te;
1367     /* oh yeah, and make locking smarter/fine grained. */
1368     apr_thread_mutex_lock(g_timer_skiplist_mtx);
1369
1370     if (!APR_RING_EMPTY(&timer_free_ring, timer_event_t, link)) {
1371         te = APR_RING_FIRST(&timer_free_ring);
1372         APR_RING_REMOVE(te, link);
1373     }
1374     else {
1375         te = apr_skiplist_alloc(timer_skiplist, sizeof(timer_event_t));
1376         APR_RING_ELEM_INIT(te, link);
1377     }
1378
1379     te->cbfunc = cbfn;
1380     te->baton = baton;
1381     /* XXXXX: optimize */
1382     te->when = t + apr_time_now();
1383
1384     { 
1385         apr_time_t next_expiry;
1386
1387         /* Okay, add sorted by when.. */
1388         apr_skiplist_insert(timer_skiplist, te);
1389
1390         /* Cheaply update the overall timers' next expiry according to
1391          * this event, if necessary.
1392          */
1393         next_expiry = timers_next_expiry;
1394         if (!next_expiry || next_expiry > te->when + EVENT_FUDGE_FACTOR) {
1395             timers_next_expiry = te->when;
1396             /* Unblock the poll()ing listener for it to update its timeout. */
1397             if (listener_is_wakeable) {
1398                 apr_pollset_wakeup(event_pollset);
1399             }
1400         }
1401     }
1402
1403     apr_thread_mutex_unlock(g_timer_skiplist_mtx);
1404
1405     return APR_SUCCESS;
1406 }
1407
1408
1409 /*
1410  * Close socket and clean up if remote closed its end while we were in
1411  * lingering close.
1412  * Only to be called in the listener thread;
1413  * Pre-condition: cs is in one of the linger queues and in the pollset
1414  */
1415 static void process_lingering_close(event_conn_state_t *cs, const apr_pollfd_t *pfd)
1416 {
1417     apr_socket_t *csd = ap_get_conn_socket(cs->c);
1418     char dummybuf[2048];
1419     apr_size_t nbytes;
1420     apr_status_t rv;
1421     struct timeout_queue *q;
1422     q = (cs->pub.state == CONN_STATE_LINGER_SHORT) ? short_linger_q : linger_q;
1423
1424     /* socket is already in non-blocking state */
1425     do {
1426         nbytes = sizeof(dummybuf);
1427         rv = apr_socket_recv(csd, dummybuf, &nbytes);
1428     } while (rv == APR_SUCCESS);
1429
1430     if (APR_STATUS_IS_EAGAIN(rv)) {
1431         return;
1432     }
1433
1434     apr_thread_mutex_lock(timeout_mutex);
1435     TO_QUEUE_REMOVE(q, cs);
1436     rv = apr_pollset_remove(event_pollset, pfd);
1437     apr_thread_mutex_unlock(timeout_mutex);
1438     AP_DEBUG_ASSERT(rv == APR_SUCCESS ||  APR_STATUS_IS_NOTFOUND(rv));
1439
1440     rv = apr_socket_close(csd);
1441     AP_DEBUG_ASSERT(rv == APR_SUCCESS);
1442
1443     ap_push_pool(worker_queue_info, cs->p);
1444     if (dying)
1445         ap_queue_interrupt_one(worker_queue);
1446 }
1447
1448 /* call 'func' for all elements of 'q' with timeout less than 'timeout_time'.
1449  * Pre-condition: timeout_mutex must already be locked
1450  * Post-condition: timeout_mutex will be locked again
1451  */
1452 static void process_timeout_queue(struct timeout_queue *q,
1453                                   apr_time_t timeout_time,
1454                                   int (*func)(event_conn_state_t *))
1455 {
1456     apr_uint32_t total = 0, count;
1457     event_conn_state_t *first, *cs, *last;
1458     struct timeout_head_t trash;
1459     struct timeout_queue *qp;
1460     apr_status_t rv;
1461
1462     if (!apr_atomic_read32(q->total)) {
1463         return;
1464     }
1465
1466     APR_RING_INIT(&trash, event_conn_state_t, timeout_list);
1467     for (qp = q; qp; qp = qp->next) {
1468         count = 0;
1469         cs = first = last = APR_RING_FIRST(&qp->head);
1470         while (cs != APR_RING_SENTINEL(&qp->head, event_conn_state_t,
1471                                        timeout_list)) {
1472             /* Trash the entry if:
1473              * - no timeout_time was given (asked for all), or
1474              * - it expired (according to the queue timeout), or
1475              * - the system clock skewed in the past: no entry should be
1476              *   registered above the given timeout_time (~now) + the queue
1477              *   timeout, we won't keep any here (eg. for centuries).
1478              *
1479              * Otherwise stop, no following entry will match thanks to the
1480              * single timeout per queue (entries are added to the end!).
1481              * This allows maintenance in O(1).
1482              */
1483             if (timeout_time
1484                     && cs->queue_timestamp + qp->timeout > timeout_time
1485                     && cs->queue_timestamp < timeout_time + qp->timeout) {
1486                 /* Since this is the next expiring of this queue, update the
1487                  * overall queues' next expiry if it's later than this one.
1488                  */
1489                 apr_time_t q_expiry = cs->queue_timestamp + qp->timeout;
1490                 apr_time_t next_expiry = queues_next_expiry;
1491                 if (!next_expiry || next_expiry > q_expiry) {
1492                     queues_next_expiry = q_expiry;
1493                 }
1494                 break;
1495             }
1496
1497             last = cs;
1498             rv = apr_pollset_remove(event_pollset, &cs->pfd);
1499             if (rv != APR_SUCCESS && !APR_STATUS_IS_NOTFOUND(rv)) {
1500                 ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, cs->c, APLOGNO(00473)
1501                               "apr_pollset_remove failed");
1502             }
1503             cs = APR_RING_NEXT(cs, timeout_list);
1504             count++;
1505         }
1506         if (!count)
1507             continue;
1508
1509         APR_RING_UNSPLICE(first, last, timeout_list);
1510         APR_RING_SPLICE_TAIL(&trash, first, last, event_conn_state_t,
1511                              timeout_list);
1512         AP_DEBUG_ASSERT(apr_atomic_read32(q->total) >= count);
1513         apr_atomic_sub32(q->total, count);
1514         qp->count -= count;
1515         total += count;
1516     }
1517     if (!total)
1518         return;
1519
1520     apr_thread_mutex_unlock(timeout_mutex);
1521     first = APR_RING_FIRST(&trash);
1522     do {
1523         cs = APR_RING_NEXT(first, timeout_list);
1524         TO_QUEUE_ELEM_INIT(first);
1525         func(first);
1526         first = cs;
1527     } while (--total);
1528     apr_thread_mutex_lock(timeout_mutex);
1529 }
1530
1531 static void process_keepalive_queue(apr_time_t timeout_time)
1532 {
1533     /* If all workers are busy, we kill older keep-alive connections so
1534      * that they may connect to another process.
1535      */
1536     if (!timeout_time) {
1537         ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, ap_server_conf,
1538                      "All workers are busy or dying, will close %u "
1539                      "keep-alive connections",
1540                      apr_atomic_read32(keepalive_q->total));
1541     }
1542     process_timeout_queue(keepalive_q, timeout_time,
1543                           start_lingering_close_nonblocking);
1544 }
1545
1546 static void * APR_THREAD_FUNC listener_thread(apr_thread_t * thd, void *dummy)
1547 {
1548     timer_event_t *te;
1549     apr_status_t rc;
1550     proc_info *ti = dummy;
1551     int process_slot = ti->pslot;
1552     struct process_score *ps = ap_get_scoreboard_process(process_slot);
1553     apr_pool_t *tpool = apr_thread_pool_get(thd);
1554     void *csd = NULL;
1555     apr_pool_t *ptrans;         /* Pool for per-transaction stuff */
1556     ap_listen_rec *lr;
1557     int have_idle_worker = 0;
1558     const apr_pollfd_t *out_pfd;
1559     apr_int32_t num = 0;
1560     apr_interval_time_t timeout_interval;
1561     apr_time_t timeout_time = 0, now, last_log;
1562     listener_poll_type *pt;
1563     int closed = 0, listeners_disabled = 0;
1564
1565     last_log = apr_time_now();
1566     free(ti);
1567
1568     rc = init_pollset(tpool);
1569     if (rc != APR_SUCCESS) {
1570         ap_log_error(APLOG_MARK, APLOG_ERR, rc, ap_server_conf,
1571                      "failed to initialize pollset, "
1572                      "attempting to shutdown process gracefully");
1573         signal_threads(ST_GRACEFUL);
1574         return NULL;
1575     }
1576
1577     /* Unblock the signal used to wake this thread up, and set a handler for
1578      * it.
1579      */
1580     unblock_signal(LISTENER_SIGNAL);
1581     apr_signal(LISTENER_SIGNAL, dummy_signal_handler);
1582
1583     for (;;) {
1584         int workers_were_busy = 0;
1585
1586         if (listener_may_exit) {
1587             close_listeners(process_slot, &closed);
1588             if (terminate_mode == ST_UNGRACEFUL
1589                 || apr_atomic_read32(&connection_count) == 0)
1590                 break;
1591         }
1592
1593         if (conns_this_child <= 0)
1594             check_infinite_requests();
1595
1596         now = apr_time_now();
1597         if (APLOGtrace6(ap_server_conf)) {
1598             /* trace log status every second */
1599             if (now - last_log > apr_time_from_sec(1)) {
1600                 last_log = now;
1601                 apr_thread_mutex_lock(timeout_mutex);
1602                 ap_log_error(APLOG_MARK, APLOG_TRACE6, 0, ap_server_conf,
1603                              "connections: %u (clogged: %u write-completion: %d "
1604                              "keep-alive: %d lingering: %d suspended: %u)",
1605                              apr_atomic_read32(&connection_count),
1606                              apr_atomic_read32(&clogged_count),
1607                              apr_atomic_read32(write_completion_q->total),
1608                              apr_atomic_read32(keepalive_q->total),
1609                              apr_atomic_read32(&lingering_count),
1610                              apr_atomic_read32(&suspended_count));
1611                 if (dying) {
1612                     ap_log_error(APLOG_MARK, APLOG_TRACE6, 0, ap_server_conf,
1613                                  "%u/%u workers shutdown",
1614                                  apr_atomic_read32(&threads_shutdown),
1615                                  threads_per_child);
1616                 }
1617                 apr_thread_mutex_unlock(timeout_mutex);
1618             }
1619         }
1620
1621         /* Start with an infinite poll() timeout and update it according to
1622          * the next expiring timer or queue entry. If there are none, either
1623          * the listener is wakeable and it can poll() indefinitely until a wake
1624          * up occurs, otherwise periodic checks (maintenance, shutdown, ...)
1625          * must be performed.
1626          */
1627         timeout_interval = -1;
1628
1629         /* Push expired timers to a worker, the first remaining one determines
1630          * the maximum time to poll() below, if any.
1631          */
1632         timeout_time = timers_next_expiry;
1633         if (timeout_time && timeout_time < now + EVENT_FUDGE_FACTOR) {
1634             apr_thread_mutex_lock(g_timer_skiplist_mtx);
1635             while ((te = apr_skiplist_peek(timer_skiplist))) {
1636                 if (te->when > now + EVENT_FUDGE_FACTOR) {
1637                     timers_next_expiry = te->when;
1638                     timeout_interval = te->when - now;
1639                     break;
1640                 }
1641                 apr_skiplist_pop(timer_skiplist, NULL);
1642                 push_timer2worker(te);
1643             }
1644             if (!te) {
1645                 timers_next_expiry = 0;
1646             }
1647             apr_thread_mutex_unlock(g_timer_skiplist_mtx);
1648         }
1649
1650         /* Same for queues, use their next expiry, if any. */
1651         timeout_time = queues_next_expiry;
1652         if (timeout_time
1653                 && (timeout_interval < 0
1654                     || timeout_time <= now
1655                     || timeout_interval > timeout_time - now)) {
1656             timeout_interval = timeout_time > now ? timeout_time - now : 1;
1657         }
1658
1659         /* When non-wakeable, don't wait more than 100 ms, in any case. */
1660 #define NON_WAKEABLE_POLL_TIMEOUT apr_time_from_msec(100)
1661         if (!listener_is_wakeable
1662                 && (timeout_interval < 0
1663                     || timeout_interval > NON_WAKEABLE_POLL_TIMEOUT)) {
1664             timeout_interval = NON_WAKEABLE_POLL_TIMEOUT;
1665         }
1666
1667         rc = apr_pollset_poll(event_pollset, timeout_interval, &num, &out_pfd);
1668         if (rc != APR_SUCCESS) {
1669             if (APR_STATUS_IS_EINTR(rc)) {
1670                 /* Woken up, if we are exiting we must fall through to kill
1671                  * kept-alive connections, otherwise we only need to update
1672                  * timeouts (logic is above, so restart the loop).
1673                  */
1674                 if (!listener_may_exit) {
1675                     continue;
1676                 }
1677                 timeout_time = 0;
1678             }
1679             else if (!APR_STATUS_IS_TIMEUP(rc)) {
1680                 ap_log_error(APLOG_MARK, APLOG_CRIT, rc, ap_server_conf,
1681                              "apr_pollset_poll failed.  Attempting to "
1682                              "shutdown process gracefully");
1683                 signal_threads(ST_GRACEFUL);
1684             }
1685             num = 0;
1686         }
1687
1688         if (listener_may_exit) {
1689             close_listeners(process_slot, &closed);
1690             if (terminate_mode == ST_UNGRACEFUL
1691                 || apr_atomic_read32(&connection_count) == 0)
1692                 break;
1693         }
1694
1695         while (num) {
1696             pt = (listener_poll_type *) out_pfd->client_data;
1697             if (pt->type == PT_CSD) {
1698                 /* one of the sockets is readable */
1699                 event_conn_state_t *cs = (event_conn_state_t *) pt->baton;
1700                 struct timeout_queue *remove_from_q = cs->sc->wc_q;
1701                 int blocking = 1;
1702
1703                 switch (cs->pub.state) {
1704                 case CONN_STATE_CHECK_REQUEST_LINE_READABLE:
1705                     cs->pub.state = CONN_STATE_READ_REQUEST_LINE;
1706                     remove_from_q = cs->sc->ka_q;
1707                     /* don't wait for a worker for a keepalive request */
1708                     blocking = 0;
1709                     /* FALL THROUGH */
1710                 case CONN_STATE_WRITE_COMPLETION:
1711                     get_worker(&have_idle_worker, blocking,
1712                                &workers_were_busy);
1713                     apr_thread_mutex_lock(timeout_mutex);
1714                     TO_QUEUE_REMOVE(remove_from_q, cs);
1715                     rc = apr_pollset_remove(event_pollset, &cs->pfd);
1716                     apr_thread_mutex_unlock(timeout_mutex);
1717
1718                     /*
1719                      * Some of the pollset backends, like KQueue or Epoll
1720                      * automagically remove the FD if the socket is closed,
1721                      * therefore, we can accept _SUCCESS or _NOTFOUND,
1722                      * and we still want to keep going
1723                      */
1724                     if (rc != APR_SUCCESS && !APR_STATUS_IS_NOTFOUND(rc)) {
1725                         ap_log_error(APLOG_MARK, APLOG_ERR, rc, ap_server_conf,
1726                                      APLOGNO(03094) "pollset remove failed");
1727                         start_lingering_close_nonblocking(cs);
1728                         break;
1729                     }
1730
1731                     /* If we didn't get a worker immediately for a keep-alive
1732                      * request, we close the connection, so that the client can
1733                      * re-connect to a different process.
1734                      */
1735                     if (!have_idle_worker) {
1736                         start_lingering_close_nonblocking(cs);
1737                     }
1738                     else if (push2worker(cs, NULL, NULL) == APR_SUCCESS) {
1739                         have_idle_worker = 0;
1740                     }
1741                     break;
1742
1743                 case CONN_STATE_LINGER_NORMAL:
1744                 case CONN_STATE_LINGER_SHORT:
1745                     process_lingering_close(cs, out_pfd);
1746                     break;
1747
1748                 default:
1749                     ap_log_error(APLOG_MARK, APLOG_CRIT, rc,
1750                                  ap_server_conf, APLOGNO(03096)
1751                                  "event_loop: unexpected state %d",
1752                                  cs->pub.state);
1753                     ap_assert(0);
1754                 }
1755             }
1756             else if (pt->type == PT_ACCEPT) {
1757                 /* A Listener Socket is ready for an accept() */
1758                 if (workers_were_busy) {
1759                     if (!listeners_disabled)
1760                         disable_listensocks(process_slot);
1761                     listeners_disabled = 1;
1762                     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
1763                                  "All workers busy, not accepting new conns "
1764                                  "in this process");
1765                 }
1766                 else if (  (int)apr_atomic_read32(&connection_count)
1767                            - (int)apr_atomic_read32(&lingering_count)
1768                          > threads_per_child
1769                            + ap_queue_info_get_idlers(worker_queue_info) *
1770                              worker_factor / WORKER_FACTOR_SCALE)
1771                 {
1772                     if (!listeners_disabled)
1773                         disable_listensocks(process_slot);
1774                     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
1775                                  "Too many open connections (%u), "
1776                                  "not accepting new conns in this process",
1777                                  apr_atomic_read32(&connection_count));
1778                     ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, ap_server_conf,
1779                                  "Idle workers: %u",
1780                                  ap_queue_info_get_idlers(worker_queue_info));
1781                     listeners_disabled = 1;
1782                 }
1783                 else if (listeners_disabled) {
1784                     listeners_disabled = 0;
1785                     enable_listensocks(process_slot);
1786                 }
1787                 if (!listeners_disabled) {
1788                     lr = (ap_listen_rec *) pt->baton;
1789                     ap_pop_pool(&ptrans, worker_queue_info);
1790
1791                     if (ptrans == NULL) {
1792                         /* create a new transaction pool for each accepted socket */
1793                         apr_allocator_t *allocator;
1794
1795                         apr_allocator_create(&allocator);
1796                         apr_allocator_max_free_set(allocator,
1797                                                    ap_max_mem_free);
1798                         apr_pool_create_ex(&ptrans, pconf, NULL, allocator);
1799                         apr_allocator_owner_set(allocator, ptrans);
1800                         if (ptrans == NULL) {
1801                             ap_log_error(APLOG_MARK, APLOG_CRIT, rc,
1802                                          ap_server_conf, APLOGNO(03097)
1803                                          "Failed to create transaction pool");
1804                             signal_threads(ST_GRACEFUL);
1805                             return NULL;
1806                         }
1807                     }
1808                     apr_pool_tag(ptrans, "transaction");
1809
1810                     get_worker(&have_idle_worker, 1, &workers_were_busy);
1811                     rc = lr->accept_func(&csd, lr, ptrans);
1812
1813                     /* later we trash rv and rely on csd to indicate
1814                      * success/failure
1815                      */
1816                     AP_DEBUG_ASSERT(rc == APR_SUCCESS || !csd);
1817
1818                     if (rc == APR_EGENERAL) {
1819                         /* E[NM]FILE, ENOMEM, etc */
1820                         resource_shortage = 1;
1821                         signal_threads(ST_GRACEFUL);
1822                     }
1823
1824                     if (csd != NULL) {
1825                         conns_this_child--;
1826                         if (push2worker(NULL, csd, ptrans) == APR_SUCCESS) {
1827                             have_idle_worker = 0;
1828                         }
1829                     }
1830                     else {
1831                         ap_push_pool(worker_queue_info, ptrans);
1832                     }
1833                 }
1834             }               /* if:else on pt->type */
1835             out_pfd++;
1836             num--;
1837         }                   /* while for processing poll */
1838
1839         /* XXX possible optimization: stash the current time for use as
1840          * r->request_time for new requests
1841          */
1842         /* We process the timeout queues here only when their overall next
1843          * expiry (read once above) is over. This happens accurately since
1844          * adding to the queues (in workers) can only decrease this expiry,
1845          * while latest ones are only taken into account here (in listener)
1846          * during queues' processing, with the lock held. This works both
1847          * with and without wake-ability.
1848          */
1849         if (timeout_time && timeout_time < (now = apr_time_now())) {
1850             timeout_time = now + TIMEOUT_FUDGE_FACTOR;
1851
1852             /* handle timed out sockets */
1853             apr_thread_mutex_lock(timeout_mutex);
1854
1855             /* Processing all the queues below will recompute this. */
1856             queues_next_expiry = 0;
1857
1858             /* Step 1: keepalive timeouts */
1859             if (workers_were_busy || dying) {
1860                 process_keepalive_queue(0); /* kill'em all \m/ */
1861             }
1862             else {
1863                 process_keepalive_queue(timeout_time);
1864             }
1865             /* Step 2: write completion timeouts */
1866             process_timeout_queue(write_completion_q, timeout_time,
1867                                   start_lingering_close_nonblocking);
1868             /* Step 3: (normal) lingering close completion timeouts */
1869             process_timeout_queue(linger_q, timeout_time,
1870                                   stop_lingering_close);
1871             /* Step 4: (short) lingering close completion timeouts */
1872             process_timeout_queue(short_linger_q, timeout_time,
1873                                   stop_lingering_close);
1874
1875             apr_thread_mutex_unlock(timeout_mutex);
1876
1877             ps->keep_alive = apr_atomic_read32(keepalive_q->total);
1878             ps->write_completion = apr_atomic_read32(write_completion_q->total);
1879             ps->connections = apr_atomic_read32(&connection_count);
1880             ps->suspended = apr_atomic_read32(&suspended_count);
1881             ps->lingering_close = apr_atomic_read32(&lingering_count);
1882         }
1883         else if ((workers_were_busy || dying)
1884                  && apr_atomic_read32(keepalive_q->total)) {
1885             apr_thread_mutex_lock(timeout_mutex);
1886             process_keepalive_queue(0); /* kill'em all \m/ */
1887             apr_thread_mutex_unlock(timeout_mutex);
1888             ps->keep_alive = 0;
1889         }
1890
1891         /* If there are some lingering closes to defer (to a worker), schedule
1892          * them now. We might wakeup a worker spuriously if another one empties
1893          * defer_linger_chain in the meantime, but there also may be no active
1894          * or all busy workers for an undefined time.  In any case a deferred
1895          * lingering close can't starve if we do that here since the chain is
1896          * filled only above in the listener and it's emptied only in the
1897          * worker(s); thus a NULL here means it will stay so while the listener
1898          * waits (possibly indefinitely) in poll().
1899          */
1900         if (defer_linger_chain) {
1901             get_worker(&have_idle_worker, 0, &workers_were_busy);
1902             if (have_idle_worker
1903                     && defer_linger_chain /* re-test */
1904                     && push2worker(NULL, NULL, NULL) == APR_SUCCESS) {
1905                 have_idle_worker = 0;
1906             }
1907         }
1908
1909         if (listeners_disabled && !workers_were_busy
1910             && (int)apr_atomic_read32(&connection_count)
1911                - (int)apr_atomic_read32(&lingering_count)
1912                < ((int)ap_queue_info_get_idlers(worker_queue_info) - 1)
1913                  * worker_factor / WORKER_FACTOR_SCALE + threads_per_child)
1914         {
1915             listeners_disabled = 0;
1916             enable_listensocks(process_slot);
1917         }
1918         /*
1919          * XXX: do we need to set some timeout that re-enables the listensocks
1920          * XXX: in case no other event occurs?
1921          */
1922     }     /* listener main loop */
1923
1924     close_listeners(process_slot, &closed);
1925     ap_queue_term(worker_queue);
1926
1927     apr_thread_exit(thd, APR_SUCCESS);
1928     return NULL;
1929 }
1930
1931 /*
1932  * During graceful shutdown, if there are more running worker threads than
1933  * open connections, exit one worker thread.
1934  *
1935  * return 1 if thread should exit, 0 if it should continue running.
1936  */
1937 static int worker_thread_should_exit_early(void)
1938 {
1939     for (;;) {
1940         apr_uint32_t conns = apr_atomic_read32(&connection_count);
1941         apr_uint32_t dead = apr_atomic_read32(&threads_shutdown);
1942         apr_uint32_t newdead;
1943
1944         AP_DEBUG_ASSERT(dead <= threads_per_child);
1945         if (conns >= threads_per_child - dead)
1946             return 0;
1947
1948         newdead = dead + 1;
1949         if (apr_atomic_cas32(&threads_shutdown, newdead, dead) == dead) {
1950             /*
1951              * No other thread has exited in the mean time, safe to exit
1952              * this one.
1953              */
1954             return 1;
1955         }
1956     }
1957 }
1958
1959 /* XXX For ungraceful termination/restart, we definitely don't want to
1960  *     wait for active connections to finish but we may want to wait
1961  *     for idle workers to get out of the queue code and release mutexes,
1962  *     since those mutexes are cleaned up pretty soon and some systems
1963  *     may not react favorably (i.e., segfault) if operations are attempted
1964  *     on cleaned-up mutexes.
1965  */
1966 static void *APR_THREAD_FUNC worker_thread(apr_thread_t * thd, void *dummy)
1967 {
1968     proc_info *ti = dummy;
1969     int process_slot = ti->pslot;
1970     int thread_slot = ti->tslot;
1971     apr_socket_t *csd = NULL;
1972     event_conn_state_t *cs;
1973     apr_pool_t *ptrans;         /* Pool for per-transaction stuff */
1974     apr_status_t rv;
1975     int is_idle = 0;
1976     timer_event_t *te = NULL;
1977
1978     free(ti);
1979
1980     ap_scoreboard_image->servers[process_slot][thread_slot].pid = ap_my_pid;
1981     ap_scoreboard_image->servers[process_slot][thread_slot].tid = apr_os_thread_current();
1982     ap_scoreboard_image->servers[process_slot][thread_slot].generation = retained->mpm->my_generation;
1983     ap_update_child_status_from_indexes(process_slot, thread_slot,
1984                                         SERVER_STARTING, NULL);
1985
1986     while (!workers_may_exit) {
1987         if (!is_idle) {
1988             rv = ap_queue_info_set_idle(worker_queue_info, NULL);
1989             if (rv != APR_SUCCESS) {
1990                 ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
1991                              "ap_queue_info_set_idle failed. Attempting to "
1992                              "shutdown process gracefully.");
1993                 signal_threads(ST_GRACEFUL);
1994                 break;
1995             }
1996             is_idle = 1;
1997         }
1998
1999         ap_update_child_status_from_indexes(process_slot, thread_slot,
2000                                             dying ? SERVER_GRACEFUL
2001                                                   : SERVER_READY, NULL);
2002       worker_pop:
2003         if (workers_may_exit) {
2004             break;
2005         }
2006         if (dying && worker_thread_should_exit_early()) {
2007             break;
2008         }
2009
2010         te = NULL;
2011         rv = ap_queue_pop_something(worker_queue, &csd, &cs, &ptrans, &te);
2012
2013         if (rv != APR_SUCCESS) {
2014             /* We get APR_EOF during a graceful shutdown once all the
2015              * connections accepted by this server process have been handled.
2016              */
2017             if (APR_STATUS_IS_EOF(rv)) {
2018                 break;
2019             }
2020             /* We get APR_EINTR whenever ap_queue_pop() has been interrupted
2021              * from an explicit call to ap_queue_interrupt_all(). This allows
2022              * us to unblock threads stuck in ap_queue_pop() when a shutdown
2023              * is pending.
2024              *
2025              * If workers_may_exit is set and this is ungraceful termination/
2026              * restart, we are bound to get an error on some systems (e.g.,
2027              * AIX, which sanity-checks mutex operations) since the queue
2028              * may have already been cleaned up.  Don't log the "error" if
2029              * workers_may_exit is set.
2030              */
2031             else if (APR_STATUS_IS_EINTR(rv)) {
2032                 goto worker_pop;
2033             }
2034             /* We got some other error. */
2035             else if (!workers_may_exit) {
2036                 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
2037                              APLOGNO(03099) "ap_queue_pop failed");
2038             }
2039             continue;
2040         }
2041         if (te != NULL) {
2042             te->cbfunc(te->baton);
2043
2044             {
2045                 apr_thread_mutex_lock(g_timer_skiplist_mtx);
2046                 APR_RING_INSERT_TAIL(&timer_free_ring, te, timer_event_t, link);
2047                 apr_thread_mutex_unlock(g_timer_skiplist_mtx);
2048             }
2049         }
2050         else {
2051             is_idle = 0;
2052             if (csd != NULL) {
2053                 worker_sockets[thread_slot] = csd;
2054                 process_socket(thd, ptrans, csd, cs, process_slot, thread_slot);
2055                 worker_sockets[thread_slot] = NULL;
2056             }
2057         }
2058
2059         /* If there are deferred lingering closes, handle them now. */
2060         while (!workers_may_exit) {
2061             cs = defer_linger_chain;
2062             if (!cs) {
2063                 break;
2064             }
2065             if (apr_atomic_casptr((void *)&defer_linger_chain, cs->chain,
2066                                   cs) != cs) {
2067                 /* Race lost, try again */
2068                 continue;
2069             }
2070             cs->chain = NULL;
2071
2072             worker_sockets[thread_slot] = csd = cs->pfd.desc.s;
2073 #ifdef AP_DEBUG
2074             rv = apr_socket_timeout_set(csd, SECONDS_TO_LINGER);
2075             AP_DEBUG_ASSERT(rv == APR_SUCCESS);
2076 #else
2077             apr_socket_timeout_set(csd, SECONDS_TO_LINGER);
2078 #endif
2079             cs->pub.state = CONN_STATE_LINGER;
2080             process_socket(thd, cs->p, csd, cs, process_slot, thread_slot);
2081             worker_sockets[thread_slot] = NULL;
2082         }
2083     }
2084
2085     ap_update_child_status_from_indexes(process_slot, thread_slot,
2086                                         dying ? SERVER_DEAD
2087                                               : SERVER_GRACEFUL, NULL);
2088
2089     apr_thread_exit(thd, APR_SUCCESS);
2090     return NULL;
2091 }
2092
2093 static int check_signal(int signum)
2094 {
2095     switch (signum) {
2096     case SIGTERM:
2097     case SIGINT:
2098         return 1;
2099     }
2100     return 0;
2101 }
2102
2103
2104
2105 static void create_listener_thread(thread_starter * ts)
2106 {
2107     int my_child_num = ts->child_num_arg;
2108     apr_threadattr_t *thread_attr = ts->threadattr;
2109     proc_info *my_info;
2110     apr_status_t rv;
2111
2112     my_info = (proc_info *) ap_malloc(sizeof(proc_info));
2113     my_info->pslot = my_child_num;
2114     my_info->tslot = -1;      /* listener thread doesn't have a thread slot */
2115     rv = apr_thread_create(&ts->listener, thread_attr, listener_thread,
2116                            my_info, pchild);
2117     if (rv != APR_SUCCESS) {
2118         ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf, APLOGNO(00474)
2119                      "apr_thread_create: unable to create listener thread");
2120         /* let the parent decide how bad this really is */
2121         clean_child_exit(APEXIT_CHILDSICK);
2122     }
2123     apr_os_thread_get(&listener_os_thread, ts->listener);
2124 }
2125
2126 /* XXX under some circumstances not understood, children can get stuck
2127  *     in start_threads forever trying to take over slots which will
2128  *     never be cleaned up; for now there is an APLOG_DEBUG message issued
2129  *     every so often when this condition occurs
2130  */
2131 static void *APR_THREAD_FUNC start_threads(apr_thread_t * thd, void *dummy)
2132 {
2133     thread_starter *ts = dummy;
2134     apr_thread_t **threads = ts->threads;
2135     apr_threadattr_t *thread_attr = ts->threadattr;
2136     int my_child_num = ts->child_num_arg;
2137     proc_info *my_info;
2138     apr_status_t rv;
2139     int i;
2140     int threads_created = 0;
2141     int listener_started = 0;
2142     int loops;
2143     int prev_threads_created;
2144     int max_recycled_pools = -1;
2145     int good_methods[] = {APR_POLLSET_KQUEUE, APR_POLLSET_PORT, APR_POLLSET_EPOLL};
2146     /* XXX don't we need more to handle K-A or lingering close? */
2147     const apr_uint32_t pollset_size = threads_per_child * 2;
2148
2149     /* We must create the fd queues before we start up the listener
2150      * and worker threads. */
2151     worker_queue = apr_pcalloc(pchild, sizeof(*worker_queue));
2152     rv = ap_queue_init(worker_queue, threads_per_child, pchild);
2153     if (rv != APR_SUCCESS) {
2154         ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf, APLOGNO(03100)
2155                      "ap_queue_init() failed");
2156         clean_child_exit(APEXIT_CHILDFATAL);
2157     }
2158
2159     if (ap_max_mem_free != APR_ALLOCATOR_MAX_FREE_UNLIMITED) {
2160         /* If we want to conserve memory, let's not keep an unlimited number of
2161          * pools & allocators.
2162          * XXX: This should probably be a separate config directive
2163          */
2164         max_recycled_pools = threads_per_child * 3 / 4 ;
2165     }
2166     rv = ap_queue_info_create(&worker_queue_info, pchild,
2167                               threads_per_child, max_recycled_pools);
2168     if (rv != APR_SUCCESS) {
2169         ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf, APLOGNO(03101)
2170                      "ap_queue_info_create() failed");
2171         clean_child_exit(APEXIT_CHILDFATAL);
2172     }
2173
2174     /* Create the timeout mutex and main pollset before the listener
2175      * thread starts.
2176      */
2177     rv = apr_thread_mutex_create(&timeout_mutex, APR_THREAD_MUTEX_DEFAULT,
2178                                  pchild);
2179     if (rv != APR_SUCCESS) {
2180         ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf, APLOGNO(03102)
2181                      "creation of the timeout mutex failed.");
2182         clean_child_exit(APEXIT_CHILDFATAL);
2183     }
2184
2185     /* Create the main pollset */
2186     for (i = 0; i < sizeof(good_methods) / sizeof(good_methods[0]); i++) {
2187         apr_uint32_t flags = APR_POLLSET_THREADSAFE | APR_POLLSET_NOCOPY |
2188                              APR_POLLSET_NODEFAULT | APR_POLLSET_WAKEABLE;
2189         rv = apr_pollset_create_ex(&event_pollset, pollset_size, pchild, flags,
2190                                    good_methods[i]);
2191         if (rv == APR_SUCCESS) {
2192             listener_is_wakeable = 1;
2193             break;
2194         }
2195         flags &= ~APR_POLLSET_WAKEABLE;
2196         rv = apr_pollset_create_ex(&event_pollset, pollset_size, pchild, flags,
2197                                    good_methods[i]);
2198         if (rv == APR_SUCCESS) {
2199             break;
2200         }
2201     }
2202     if (rv != APR_SUCCESS) {
2203         rv = apr_pollset_create(&event_pollset, pollset_size, pchild,
2204                                 APR_POLLSET_THREADSAFE | APR_POLLSET_NOCOPY);
2205     }
2206     if (rv != APR_SUCCESS) {
2207         ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf, APLOGNO(03103)
2208                      "apr_pollset_create with Thread Safety failed.");
2209         clean_child_exit(APEXIT_CHILDFATAL);
2210     }
2211
2212     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02471)
2213                  "start_threads: Using %s (%swakeable)",
2214                  apr_pollset_method_name(event_pollset),
2215                  listener_is_wakeable ? "" : "not ");
2216     worker_sockets = apr_pcalloc(pchild, threads_per_child
2217                                  * sizeof(apr_socket_t *));
2218
2219     loops = prev_threads_created = 0;
2220     while (1) {
2221         /* threads_per_child does not include the listener thread */
2222         for (i = 0; i < threads_per_child; i++) {
2223             int status =
2224                 ap_scoreboard_image->servers[my_child_num][i].status;
2225
2226             if (status != SERVER_DEAD) {
2227                 continue;
2228             }
2229
2230             my_info = (proc_info *) ap_malloc(sizeof(proc_info));
2231             my_info->pslot = my_child_num;
2232             my_info->tslot = i;
2233
2234             /* We are creating threads right now */
2235             ap_update_child_status_from_indexes(my_child_num, i,
2236                                                 SERVER_STARTING, NULL);
2237             /* We let each thread update its own scoreboard entry.  This is
2238              * done because it lets us deal with tid better.
2239              */
2240             rv = apr_thread_create(&threads[i], thread_attr,
2241                                    worker_thread, my_info, pchild);
2242             if (rv != APR_SUCCESS) {
2243                 ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
2244                              APLOGNO(03104)
2245                              "apr_thread_create: unable to create worker thread");
2246                 /* let the parent decide how bad this really is */
2247                 clean_child_exit(APEXIT_CHILDSICK);
2248             }
2249             threads_created++;
2250         }
2251
2252         /* Start the listener only when there are workers available */
2253         if (!listener_started && threads_created) {
2254             create_listener_thread(ts);
2255             listener_started = 1;
2256         }
2257
2258
2259         if (start_thread_may_exit || threads_created == threads_per_child) {
2260             break;
2261         }
2262         /* wait for previous generation to clean up an entry */
2263         apr_sleep(apr_time_from_sec(1));
2264         ++loops;
2265         if (loops % 120 == 0) { /* every couple of minutes */
2266             if (prev_threads_created == threads_created) {
2267                 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
2268                              "child %" APR_PID_T_FMT " isn't taking over "
2269                              "slots very quickly (%d of %d)",
2270                              ap_my_pid, threads_created,
2271                              threads_per_child);
2272             }
2273             prev_threads_created = threads_created;
2274         }
2275     }
2276
2277     /* What state should this child_main process be listed as in the
2278      * scoreboard...?
2279      *  ap_update_child_status_from_indexes(my_child_num, i, SERVER_STARTING,
2280      *                                      (request_rec *) NULL);
2281      *
2282      *  This state should be listed separately in the scoreboard, in some kind
2283      *  of process_status, not mixed in with the worker threads' status.
2284      *  "life_status" is almost right, but it's in the worker's structure, and
2285      *  the name could be clearer.   gla
2286      */
2287     apr_thread_exit(thd, APR_SUCCESS);
2288     return NULL;
2289 }
2290
2291 static void join_workers(apr_thread_t * listener, apr_thread_t ** threads)
2292 {
2293     int i;
2294     apr_status_t rv, thread_rv;
2295
2296     if (listener) {
2297         int iter;
2298
2299         /* deal with a rare timing window which affects waking up the
2300          * listener thread...  if the signal sent to the listener thread
2301          * is delivered between the time it verifies that the
2302          * listener_may_exit flag is clear and the time it enters a
2303          * blocking syscall, the signal didn't do any good...  work around
2304          * that by sleeping briefly and sending it again
2305          */
2306
2307         iter = 0;
2308         while (iter < 10 && !dying) {
2309             /* listener has not stopped accepting yet */
2310             apr_sleep(apr_time_make(0, 500000));
2311             wakeup_listener();
2312             ++iter;
2313         }
2314         if (iter >= 10) {
2315             ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(00475)
2316                          "the listener thread didn't stop accepting");
2317         }
2318         else {
2319             rv = apr_thread_join(&thread_rv, listener);
2320             if (rv != APR_SUCCESS) {
2321                 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf, APLOGNO(00476)
2322                              "apr_thread_join: unable to join listener thread");
2323             }
2324         }
2325     }
2326
2327     for (i = 0; i < threads_per_child; i++) {
2328         if (threads[i]) {       /* if we ever created this thread */
2329             rv = apr_thread_join(&thread_rv, threads[i]);
2330             if (rv != APR_SUCCESS) {
2331                 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf, APLOGNO(00477)
2332                              "apr_thread_join: unable to join worker "
2333                              "thread %d", i);
2334             }
2335         }
2336     }
2337 }
2338
2339 static void join_start_thread(apr_thread_t * start_thread_id)
2340 {
2341     apr_status_t rv, thread_rv;
2342
2343     start_thread_may_exit = 1;  /* tell it to give up in case it is still
2344                                  * trying to take over slots from a
2345                                  * previous generation
2346                                  */
2347     rv = apr_thread_join(&thread_rv, start_thread_id);
2348     if (rv != APR_SUCCESS) {
2349         ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf, APLOGNO(00478)
2350                      "apr_thread_join: unable to join the start " "thread");
2351     }
2352 }
2353
2354 static void child_main(int child_num_arg, int child_bucket)
2355 {
2356     apr_thread_t **threads;
2357     apr_status_t rv;
2358     thread_starter *ts;
2359     apr_threadattr_t *thread_attr;
2360     apr_thread_t *start_thread_id;
2361     int i;
2362
2363     /* for benefit of any hooks that run as this child initializes */
2364     retained->mpm->mpm_state = AP_MPMQ_STARTING;
2365
2366     ap_my_pid = getpid();
2367     ap_fatal_signal_child_setup(ap_server_conf);
2368     apr_pool_create(&pchild, pconf);
2369
2370     /* close unused listeners and pods */
2371     for (i = 0; i < retained->mpm->num_buckets; i++) {
2372         if (i != child_bucket) {
2373             ap_close_listeners_ex(all_buckets[i].listeners);
2374             ap_mpm_podx_close(all_buckets[i].pod);
2375         }
2376     }
2377
2378     /*stuff to do before we switch id's, so we have permissions. */
2379     ap_reopen_scoreboard(pchild, NULL, 0);
2380
2381     if (ap_run_drop_privileges(pchild, ap_server_conf)) {
2382         clean_child_exit(APEXIT_CHILDFATAL);
2383     }
2384
2385     apr_thread_mutex_create(&g_timer_skiplist_mtx, APR_THREAD_MUTEX_DEFAULT, pchild);
2386     APR_RING_INIT(&timer_free_ring, timer_event_t, link);
2387     apr_skiplist_init(&timer_skiplist, pchild);
2388     apr_skiplist_set_compare(timer_skiplist, timer_comp, timer_comp);
2389     ap_run_child_init(pchild, ap_server_conf);
2390
2391     /* done with init critical section */
2392
2393     /* Just use the standard apr_setup_signal_thread to block all signals
2394      * from being received.  The child processes no longer use signals for
2395      * any communication with the parent process.
2396      */
2397     rv = apr_setup_signal_thread();
2398     if (rv != APR_SUCCESS) {
2399         ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf, APLOGNO(00479)
2400                      "Couldn't initialize signal thread");
2401         clean_child_exit(APEXIT_CHILDFATAL);
2402     }
2403
2404     if (ap_max_requests_per_child) {
2405         conns_this_child = ap_max_requests_per_child;
2406     }
2407     else {
2408         /* coding a value of zero means infinity */
2409         conns_this_child = APR_INT32_MAX;
2410     }
2411
2412     /* Setup worker threads */
2413
2414     /* clear the storage; we may not create all our threads immediately,
2415      * and we want a 0 entry to indicate a thread which was not created
2416      */
2417     threads = ap_calloc(threads_per_child, sizeof(apr_thread_t *));
2418     ts = apr_palloc(pchild, sizeof(*ts));
2419
2420     apr_threadattr_create(&thread_attr, pchild);
2421     /* 0 means PTHREAD_CREATE_JOINABLE */
2422     apr_threadattr_detach_set(thread_attr, 0);
2423
2424     if (ap_thread_stacksize != 0) {
2425         rv = apr_threadattr_stacksize_set(thread_attr, ap_thread_stacksize);
2426         if (rv != APR_SUCCESS && rv != APR_ENOTIMPL) {
2427             ap_log_error(APLOG_MARK, APLOG_WARNING, rv, ap_server_conf, APLOGNO(02436)
2428                          "WARNING: ThreadStackSize of %" APR_SIZE_T_FMT " is "
2429                          "inappropriate, using default", 
2430                          ap_thread_stacksize);
2431         }
2432     }
2433
2434     ts->threads = threads;
2435     ts->listener = NULL;
2436     ts->child_num_arg = child_num_arg;
2437     ts->threadattr = thread_attr;
2438
2439     rv = apr_thread_create(&start_thread_id, thread_attr, start_threads,
2440                            ts, pchild);
2441     if (rv != APR_SUCCESS) {
2442         ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf, APLOGNO(00480)
2443                      "apr_thread_create: unable to create worker thread");
2444         /* let the parent decide how bad this really is */
2445         clean_child_exit(APEXIT_CHILDSICK);
2446     }
2447
2448     retained->mpm->mpm_state = AP_MPMQ_RUNNING;
2449
2450     /* If we are only running in one_process mode, we will want to
2451      * still handle signals. */
2452     if (one_process) {
2453         /* Block until we get a terminating signal. */
2454         apr_signal_thread(check_signal);
2455         /* make sure the start thread has finished; signal_threads()
2456          * and join_workers() depend on that
2457          */
2458         /* XXX join_start_thread() won't be awakened if one of our
2459          *     threads encounters a critical error and attempts to
2460          *     shutdown this child
2461          */
2462         join_start_thread(start_thread_id);
2463
2464         /* helps us terminate a little more quickly than the dispatch of the
2465          * signal thread; beats the Pipe of Death and the browsers
2466          */
2467         signal_threads(ST_UNGRACEFUL);
2468
2469         /* A terminating signal was received. Now join each of the
2470          * workers to clean them up.
2471          *   If the worker already exited, then the join frees
2472          *   their resources and returns.
2473          *   If the worker hasn't exited, then this blocks until
2474          *   they have (then cleans up).
2475          */
2476         join_workers(ts->listener, threads);
2477     }
2478     else {                      /* !one_process */
2479         /* remove SIGTERM from the set of blocked signals...  if one of
2480          * the other threads in the process needs to take us down
2481          * (e.g., for MaxConnectionsPerChild) it will send us SIGTERM
2482          */
2483         unblock_signal(SIGTERM);
2484         apr_signal(SIGTERM, dummy_signal_handler);
2485         /* Watch for any messages from the parent over the POD */
2486         while (1) {
2487             rv = ap_mpm_podx_check(my_bucket->pod);
2488             if (rv == AP_MPM_PODX_NORESTART) {
2489                 /* see if termination was triggered while we slept */
2490                 switch (terminate_mode) {
2491                 case ST_GRACEFUL:
2492                     rv = AP_MPM_PODX_GRACEFUL;
2493                     break;
2494                 case ST_UNGRACEFUL:
2495                     rv = AP_MPM_PODX_RESTART;
2496                     break;
2497                 }
2498             }
2499             if (rv == AP_MPM_PODX_GRACEFUL || rv == AP_MPM_PODX_RESTART) {
2500                 /* make sure the start thread has finished;
2501                  * signal_threads() and join_workers depend on that
2502                  */
2503                 join_start_thread(start_thread_id);
2504                 signal_threads(rv ==
2505                                AP_MPM_PODX_GRACEFUL ? ST_GRACEFUL : ST_UNGRACEFUL);
2506                 break;
2507             }
2508         }
2509
2510         /* A terminating signal was received. Now join each of the
2511          * workers to clean them up.
2512          *   If the worker already exited, then the join frees
2513          *   their resources and returns.
2514          *   If the worker hasn't exited, then this blocks until
2515          *   they have (then cleans up).
2516          */
2517         join_workers(ts->listener, threads);
2518     }
2519
2520     free(threads);
2521
2522     clean_child_exit(resource_shortage ? APEXIT_CHILDSICK : 0);
2523 }
2524
2525 static int make_child(server_rec * s, int slot, int bucket)
2526 {
2527     int pid;
2528
2529     if (slot + 1 > retained->max_daemons_limit) {
2530         retained->max_daemons_limit = slot + 1;
2531     }
2532
2533     if (ap_scoreboard_image->parent[slot].pid != 0) {
2534         /* XXX replace with assert or remove ? */
2535         ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, APLOGNO(03455)
2536                  "BUG: Scoreboard slot %d should be empty but is "
2537                  "in use by pid %" APR_PID_T_FMT,
2538                  slot, ap_scoreboard_image->parent[slot].pid);
2539         return -1;
2540     }
2541
2542     if (one_process) {
2543         my_bucket = &all_buckets[0];
2544
2545         event_note_child_started(slot, getpid());
2546         child_main(slot, 0);
2547         /* NOTREACHED */
2548         ap_assert(0);
2549         return -1;
2550     }
2551
2552     if ((pid = fork()) == -1) {
2553         ap_log_error(APLOG_MARK, APLOG_ERR, errno, s, APLOGNO(00481)
2554                      "fork: Unable to fork new process");
2555
2556         /* fork didn't succeed.  There's no need to touch the scoreboard;
2557          * if we were trying to replace a failed child process, then
2558          * server_main_loop() marked its workers SERVER_DEAD, and if
2559          * we were trying to replace a child process that exited normally,
2560          * its worker_thread()s left SERVER_DEAD or SERVER_GRACEFUL behind.
2561          */
2562
2563         /* In case system resources are maxxed out, we don't want
2564            Apache running away with the CPU trying to fork over and
2565            over and over again. */
2566         apr_sleep(apr_time_from_sec(10));
2567
2568         return -1;
2569     }
2570
2571     if (!pid) {
2572         my_bucket = &all_buckets[bucket];
2573
2574 #ifdef HAVE_BINDPROCESSOR
2575         /* By default, AIX binds to a single processor.  This bit unbinds
2576          * children which will then bind to another CPU.
2577          */
2578         int status = bindprocessor(BINDPROCESS, (int) getpid(),
2579                                    PROCESSOR_CLASS_ANY);
2580         if (status != OK)
2581             ap_log_error(APLOG_MARK, APLOG_DEBUG, errno,
2582                          ap_server_conf, APLOGNO(00482)
2583                          "processor unbind failed");
2584 #endif
2585         RAISE_SIGSTOP(MAKE_CHILD);
2586
2587         apr_signal(SIGTERM, just_die);
2588         child_main(slot, bucket);
2589         /* NOTREACHED */
2590         ap_assert(0);
2591         return -1;
2592     }
2593
2594     ap_scoreboard_image->parent[slot].quiescing = 0;
2595     ap_scoreboard_image->parent[slot].not_accepting = 0;
2596     ap_scoreboard_image->parent[slot].bucket = bucket;
2597     event_note_child_started(slot, pid);
2598     active_daemons++;
2599     retained->total_daemons++;
2600     return 0;
2601 }
2602
2603 /* start up a bunch of children */
2604 static void startup_children(int number_to_start)
2605 {
2606     int i;
2607
2608     for (i = 0; number_to_start && i < server_limit; ++i) {
2609         if (ap_scoreboard_image->parent[i].pid != 0) {
2610             continue;
2611         }
2612         if (make_child(ap_server_conf, i, i % retained->mpm->num_buckets) < 0) {
2613             break;
2614         }
2615         --number_to_start;
2616     }
2617 }
2618
2619 static void perform_idle_server_maintenance(int child_bucket, int num_buckets)
2620 {
2621     int i, j;
2622     int idle_thread_count = 0;
2623     worker_score *ws;
2624     process_score *ps;
2625     int free_length = 0;
2626     int free_slots[MAX_SPAWN_RATE];
2627     int last_non_dead = -1;
2628     int active_thread_count = 0;
2629
2630     for (i = 0; i < server_limit; ++i) {
2631         /* Initialization to satisfy the compiler. It doesn't know
2632          * that threads_per_child is always > 0 */
2633         int status = SERVER_DEAD;
2634         int child_threads_active = 0;
2635
2636         if (i >= retained->max_daemons_limit &&
2637             free_length == retained->idle_spawn_rate[child_bucket]) {
2638             /* short cut if all active processes have been examined and
2639              * enough empty scoreboard slots have been found
2640              */
2641
2642             break;
2643         }
2644         ps = &ap_scoreboard_image->parent[i];
2645         if (ps->pid != 0) {
2646             for (j = 0; j < threads_per_child; j++) {
2647                 ws = &ap_scoreboard_image->servers[i][j];
2648                 status = ws->status;
2649
2650                 /* We consider a starting server as idle because we started it
2651                  * at least a cycle ago, and if it still hasn't finished starting
2652                  * then we're just going to swamp things worse by forking more.
2653                  * So we hopefully won't need to fork more if we count it.
2654                  * This depends on the ordering of SERVER_READY and SERVER_STARTING.
2655                  */
2656                 if (status <= SERVER_READY && !ps->quiescing && !ps->not_accepting
2657                     && ps->generation == retained->mpm->my_generation
2658                     && ps->bucket == child_bucket)
2659                 {
2660                     ++idle_thread_count;
2661                 }
2662                 if (status >= SERVER_READY && status < SERVER_GRACEFUL) {
2663                     ++child_threads_active;
2664                 }
2665             }
2666             last_non_dead = i;
2667         }
2668         active_thread_count += child_threads_active;
2669         if (!ps->pid && free_length < retained->idle_spawn_rate[child_bucket])
2670             free_slots[free_length++] = i;
2671         else if (child_threads_active == threads_per_child)
2672             had_healthy_child = 1;
2673     }
2674
2675     if (retained->sick_child_detected) {
2676         if (had_healthy_child) {
2677             /* Assume this is a transient error, even though it may not be.  Leave
2678              * the server up in case it is able to serve some requests or the
2679              * problem will be resolved.
2680              */
2681             retained->sick_child_detected = 0;
2682         }
2683         else {
2684             /* looks like a basket case, as no child ever fully initialized; give up.
2685              */
2686             retained->mpm->shutdown_pending = 1;
2687             child_fatal = 1;
2688             ap_log_error(APLOG_MARK, APLOG_ALERT, 0,
2689                          ap_server_conf, APLOGNO(02324)
2690                          "A resource shortage or other unrecoverable failure "
2691                          "was encountered before any child process initialized "
2692                          "successfully... httpd is exiting!");
2693             /* the child already logged the failure details */
2694             return;
2695         }
2696     }
2697
2698     retained->max_daemons_limit = last_non_dead + 1;
2699
2700     if (idle_thread_count > max_spare_threads / num_buckets)
2701     {
2702         /*
2703          * Child processes that we ask to shut down won't die immediately
2704          * but may stay around for a long time when they finish their
2705          * requests. If the server load changes many times, many such
2706          * gracefully finishing processes may accumulate, filling up the
2707          * scoreboard. To avoid running out of scoreboard entries, we
2708          * don't shut down more processes when the total number of processes
2709          * is high.
2710          *
2711          * XXX It would be nice if we could
2712          * XXX - kill processes without keepalive connections first
2713          * XXX - tell children to stop accepting new connections, and
2714          * XXX   depending on server load, later be able to resurrect them
2715          *       or kill them
2716          */
2717         if (retained->total_daemons <= active_daemons_limit &&
2718             retained->total_daemons < server_limit) {
2719             /* Kill off one child */
2720             ap_mpm_podx_signal(all_buckets[child_bucket].pod,
2721                                AP_MPM_PODX_GRACEFUL);
2722             retained->idle_spawn_rate[child_bucket] = 1;
2723             active_daemons--;
2724         } else {
2725             ap_log_error(APLOG_MARK, APLOG_TRACE5, 0, ap_server_conf,
2726                          "Not shutting down child: total daemons %d / "
2727                          "active limit %d / ServerLimit %d",
2728                          retained->total_daemons, active_daemons_limit,
2729                          server_limit);
2730         }
2731     }
2732     else if (idle_thread_count < min_spare_threads / num_buckets) {
2733         if (active_thread_count >= max_workers) {
2734             if (!retained->maxclients_reported) {
2735                 /* only report this condition once */
2736                 ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, APLOGNO(00484)
2737                              "server reached MaxRequestWorkers setting, "
2738                              "consider raising the MaxRequestWorkers "
2739                              "setting");
2740                 retained->maxclients_reported = 1;
2741             }
2742             retained->idle_spawn_rate[child_bucket] = 1;
2743         }
2744         else if (free_length == 0) { /* scoreboard is full, can't fork */
2745             ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, APLOGNO(03490)
2746                          "scoreboard is full, not at MaxRequestWorkers."
2747                          "Increase ServerLimit.");
2748             retained->idle_spawn_rate[child_bucket] = 1;
2749         }
2750         else {
2751             if (free_length > retained->idle_spawn_rate[child_bucket]) {
2752                 free_length = retained->idle_spawn_rate[child_bucket];
2753             }
2754             if (retained->idle_spawn_rate[child_bucket] >= 8) {
2755                 ap_log_error(APLOG_MARK, APLOG_INFO, 0, ap_server_conf, APLOGNO(00486)
2756                              "server seems busy, (you may need "
2757                              "to increase StartServers, ThreadsPerChild "
2758                              "or Min/MaxSpareThreads), "
2759                              "spawning %d children, there are around %d idle "
2760                              "threads, %d active children, and %d children "
2761                              "that are shutting down", free_length,
2762                              idle_thread_count, active_daemons,
2763                              retained->total_daemons);
2764             }
2765             for (i = 0; i < free_length; ++i) {
2766                 ap_log_error(APLOG_MARK, APLOG_TRACE5, 0, ap_server_conf,
2767                              "Spawning new child: slot %d active / "
2768                              "total daemons: %d/%d",
2769                              free_slots[i], active_daemons,
2770                              retained->total_daemons);
2771                 make_child(ap_server_conf, free_slots[i], child_bucket);
2772             }
2773             /* the next time around we want to spawn twice as many if this
2774              * wasn't good enough, but not if we've just done a graceful
2775              */
2776             if (retained->hold_off_on_exponential_spawning) {
2777                 --retained->hold_off_on_exponential_spawning;
2778             }
2779             else if (retained->idle_spawn_rate[child_bucket]
2780                      < MAX_SPAWN_RATE / num_buckets) {
2781                 retained->idle_spawn_rate[child_bucket] *= 2;
2782             }
2783         }
2784     }
2785     else {
2786         retained->idle_spawn_rate[child_bucket] = 1;
2787     }
2788 }
2789
2790 static void server_main_loop(int remaining_children_to_start, int num_buckets)
2791 {
2792     int child_slot;
2793     apr_exit_why_e exitwhy;
2794     int status, processed_status;
2795     apr_proc_t pid;
2796     int i;
2797
2798     while (!retained->mpm->restart_pending && !retained->mpm->shutdown_pending) {
2799         ap_wait_or_timeout(&exitwhy, &status, &pid, pconf, ap_server_conf);
2800
2801         if (pid.pid != -1) {
2802             processed_status = ap_process_child_status(&pid, exitwhy, status);
2803             child_slot = ap_find_child_by_pid(&pid);
2804             if (processed_status == APEXIT_CHILDFATAL) {
2805                 /* fix race condition found in PR 39311
2806                  * A child created at the same time as a graceful happens 
2807                  * can find the lock missing and create a fatal error.
2808                  * It is not fatal for the last generation to be in this state.
2809                  */
2810                 if (child_slot < 0
2811                     || ap_get_scoreboard_process(child_slot)->generation
2812                        == retained->mpm->my_generation) {
2813                     retained->mpm->shutdown_pending = 1;
2814                     child_fatal = 1;
2815                     /*
2816                      * total_daemons counting will be off now, but as we
2817                      * are shutting down, that is not an issue anymore.
2818                      */
2819                     return;
2820                 }
2821                 else {
2822                     ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ap_server_conf, APLOGNO(00487)
2823                                  "Ignoring fatal error in child of previous "
2824                                  "generation (pid %ld).",
2825                                  (long)pid.pid);
2826                     retained->sick_child_detected = 1;
2827                 }
2828             }
2829             else if (processed_status == APEXIT_CHILDSICK) {
2830                 /* tell perform_idle_server_maintenance to check into this
2831                  * on the next timer pop
2832                  */
2833                 retained->sick_child_detected = 1;
2834             }
2835             /* non-fatal death... note that it's gone in the scoreboard. */
2836             if (child_slot >= 0) {
2837                 process_score *ps;
2838
2839                 for (i = 0; i < threads_per_child; i++)
2840                     ap_update_child_status_from_indexes(child_slot, i,
2841                                                         SERVER_DEAD, NULL);
2842
2843                 event_note_child_killed(child_slot, 0, 0);
2844                 ps = &ap_scoreboard_image->parent[child_slot];
2845                 if (!ps->quiescing)
2846                     active_daemons--;
2847                 ps->quiescing = 0;
2848                 /* NOTE: We don't dec in the (child_slot < 0) case! */
2849                 retained->total_daemons--;
2850                 if (processed_status == APEXIT_CHILDSICK) {
2851                     /* resource shortage, minimize the fork rate */
2852                     retained->idle_spawn_rate[ps->bucket] = 1;
2853                 }
2854                 else if (remaining_children_to_start) {
2855                     /* we're still doing a 1-for-1 replacement of dead
2856                      * children with new children
2857                      */
2858                     make_child(ap_server_conf, child_slot, ps->bucket);
2859                     --remaining_children_to_start;
2860                 }
2861             }
2862 #if APR_HAS_OTHER_CHILD
2863             else if (apr_proc_other_child_alert(&pid, APR_OC_REASON_DEATH,
2864                                                 status) == 0) {
2865                 /* handled */
2866             }
2867 #endif
2868             else if (retained->mpm->was_graceful) {
2869                 /* Great, we've probably just lost a slot in the
2870                  * scoreboard.  Somehow we don't know about this child.
2871                  */
2872                 ap_log_error(APLOG_MARK, APLOG_WARNING, 0,
2873                              ap_server_conf, APLOGNO(00488)
2874                              "long lost child came home! (pid %ld)",
2875                              (long) pid.pid);
2876             }
2877             /* Don't perform idle maintenance when a child dies,
2878              * only do it when there's a timeout.  Remember only a
2879              * finite number of children can die, and it's pretty
2880              * pathological for a lot to die suddenly.
2881              */
2882             continue;
2883         }
2884         else if (remaining_children_to_start) {
2885             /* we hit a 1 second timeout in which none of the previous
2886              * generation of children needed to be reaped... so assume
2887              * they're all done, and pick up the slack if any is left.
2888              */
2889             startup_children(remaining_children_to_start);
2890             remaining_children_to_start = 0;
2891             /* In any event we really shouldn't do the code below because
2892              * few of the servers we just started are in the IDLE state
2893              * yet, so we'd mistakenly create an extra server.
2894              */
2895             continue;
2896         }
2897
2898         for (i = 0; i < num_buckets; i++) {
2899             perform_idle_server_maintenance(i, num_buckets);
2900         }
2901     }
2902 }
2903
2904 static int event_run(apr_pool_t * _pconf, apr_pool_t * plog, server_rec * s)
2905 {
2906     int num_buckets = retained->mpm->num_buckets;
2907     int remaining_children_to_start;
2908     int i;
2909
2910     ap_log_pid(pconf, ap_pid_fname);
2911
2912     if (!retained->mpm->was_graceful) {
2913         if (ap_run_pre_mpm(s->process->pool, SB_SHARED) != OK) {
2914             retained->mpm->mpm_state = AP_MPMQ_STOPPING;
2915             return !OK;
2916         }
2917         /* fix the generation number in the global score; we just got a new,
2918          * cleared scoreboard
2919          */
2920         ap_scoreboard_image->global->running_generation = retained->mpm->my_generation;
2921     }
2922
2923     ap_unixd_mpm_set_signals(pconf, one_process);
2924
2925     /* Don't thrash since num_buckets depends on the
2926      * system and the number of online CPU cores...
2927      */
2928     if (active_daemons_limit < num_buckets)
2929         active_daemons_limit = num_buckets;
2930     if (ap_daemons_to_start < num_buckets)
2931         ap_daemons_to_start = num_buckets;
2932     /* We want to create as much children at a time as the number of buckets,
2933      * so to optimally accept connections (evenly distributed across buckets).
2934      * Thus min_spare_threads should at least maintain num_buckets children,
2935      * and max_spare_threads allow num_buckets more children w/o triggering
2936      * immediately (e.g. num_buckets idle threads margin, one per bucket).
2937      */
2938     if (min_spare_threads < threads_per_child * (num_buckets - 1) + num_buckets)
2939         min_spare_threads = threads_per_child * (num_buckets - 1) + num_buckets;
2940     if (max_spare_threads < min_spare_threads + (threads_per_child + 1) * num_buckets)
2941         max_spare_threads = min_spare_threads + (threads_per_child + 1) * num_buckets;
2942
2943     /* If we're doing a graceful_restart then we're going to see a lot
2944      * of children exiting immediately when we get into the main loop
2945      * below (because we just sent them AP_SIG_GRACEFUL).  This happens pretty
2946      * rapidly... and for each one that exits we may start a new one, until
2947      * there are at least min_spare_threads idle threads, counting across
2948      * all children.  But we may be permitted to start more children than
2949      * that, so we'll just keep track of how many we're
2950      * supposed to start up without the 1 second penalty between each fork.
2951      */
2952     remaining_children_to_start = ap_daemons_to_start;
2953     if (remaining_children_to_start > active_daemons_limit) {
2954         remaining_children_to_start = active_daemons_limit;
2955     }
2956     if (!retained->mpm->was_graceful) {
2957         startup_children(remaining_children_to_start);
2958         remaining_children_to_start = 0;
2959     }
2960     else {
2961         /* give the system some time to recover before kicking into
2962          * exponential mode */
2963         retained->hold_off_on_exponential_spawning = 10;
2964     }
2965
2966     ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, APLOGNO(00489)
2967                  "%s configured -- resuming normal operations",
2968                  ap_get_server_description());
2969     ap_log_error(APLOG_MARK, APLOG_INFO, 0, ap_server_conf, APLOGNO(00490)
2970                  "Server built: %s", ap_get_server_built());
2971     ap_log_command_line(plog, s);
2972     ap_log_mpm_common(s);
2973
2974     retained->mpm->mpm_state = AP_MPMQ_RUNNING;
2975
2976     server_main_loop(remaining_children_to_start, num_buckets);
2977     retained->mpm->mpm_state = AP_MPMQ_STOPPING;
2978
2979     if (retained->mpm->shutdown_pending && retained->mpm->is_ungraceful) {
2980         /* Time to shut down:
2981          * Kill child processes, tell them to call child_exit, etc...
2982          */
2983         for (i = 0; i < num_buckets; i++) {
2984             ap_mpm_podx_killpg(all_buckets[i].pod, active_daemons_limit,
2985                                AP_MPM_PODX_RESTART);
2986         }
2987         ap_reclaim_child_processes(1, /* Start with SIGTERM */
2988                                    event_note_child_killed);
2989
2990         if (!child_fatal) {
2991             /* cleanup pid file on normal shutdown */
2992             ap_remove_pid(pconf, ap_pid_fname);
2993             ap_log_error(APLOG_MARK, APLOG_NOTICE, 0,
2994                          ap_server_conf, APLOGNO(00491) "caught SIGTERM, shutting down");
2995         }
2996
2997         return DONE;
2998     }
2999
3000     if (retained->mpm->shutdown_pending) {
3001         /* Time to gracefully shut down:
3002          * Kill child processes, tell them to call child_exit, etc...
3003          */
3004         int active_children;
3005         int index;
3006         apr_time_t cutoff = 0;
3007
3008         /* Close our listeners, and then ask our children to do same */
3009         ap_close_listeners();
3010         for (i = 0; i < num_buckets; i++) {
3011             ap_mpm_podx_killpg(all_buckets[i].pod, active_daemons_limit,
3012                                AP_MPM_PODX_GRACEFUL);
3013         }
3014         ap_relieve_child_processes(event_note_child_killed);
3015
3016         if (!child_fatal) {
3017             /* cleanup pid file on normal shutdown */
3018             ap_remove_pid(pconf, ap_pid_fname);
3019             ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, APLOGNO(00492)
3020                          "caught " AP_SIG_GRACEFUL_STOP_STRING
3021                          ", shutting down gracefully");
3022         }
3023
3024         if (ap_graceful_shutdown_timeout) {
3025             cutoff = apr_time_now() +
3026                      apr_time_from_sec(ap_graceful_shutdown_timeout);
3027         }
3028
3029         /* Don't really exit until each child has finished */
3030         retained->mpm->shutdown_pending = 0;
3031         do {
3032             /* Pause for a second */
3033             apr_sleep(apr_time_from_sec(1));
3034
3035             /* Relieve any children which have now exited */
3036             ap_relieve_child_processes(event_note_child_killed);
3037
3038             active_children = 0;
3039             for (index = 0; index < retained->max_daemons_limit; ++index) {
3040                 if (ap_mpm_safe_kill(MPM_CHILD_PID(index), 0) == APR_SUCCESS) {
3041                     active_children = 1;
3042                     /* Having just one child is enough to stay around */
3043                     break;
3044                 }
3045             }
3046         } while (!retained->mpm->shutdown_pending && active_children &&
3047                  (!ap_graceful_shutdown_timeout || apr_time_now() < cutoff));
3048
3049         /* We might be here because we received SIGTERM, either
3050          * way, try and make sure that all of our processes are
3051          * really dead.
3052          */
3053         for (i = 0; i < num_buckets; i++) {
3054             ap_mpm_podx_killpg(all_buckets[i].pod, active_daemons_limit,
3055                                AP_MPM_PODX_RESTART);
3056         }
3057         ap_reclaim_child_processes(1, event_note_child_killed);
3058
3059         return DONE;
3060     }
3061
3062     /* we've been told to restart */
3063     if (one_process) {
3064         /* not worth thinking about */
3065         return DONE;
3066     }
3067
3068     /* advance to the next generation */
3069     /* XXX: we really need to make sure this new generation number isn't in
3070      * use by any of the children.
3071      */
3072     ++retained->mpm->my_generation;
3073     ap_scoreboard_image->global->running_generation = retained->mpm->my_generation;
3074
3075     if (!retained->mpm->is_ungraceful) {
3076         ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, APLOGNO(00493)
3077                      AP_SIG_GRACEFUL_STRING
3078                      " received.  Doing graceful restart");
3079         /* wake up the children...time to die.  But we'll have more soon */
3080         for (i = 0; i < num_buckets; i++) {
3081             ap_mpm_podx_killpg(all_buckets[i].pod, active_daemons_limit,
3082                                AP_MPM_PODX_GRACEFUL);
3083         }
3084
3085         /* This is mostly for debugging... so that we know what is still
3086          * gracefully dealing with existing request.
3087          */
3088
3089     }
3090     else {
3091         /* Kill 'em all.  Since the child acts the same on the parents SIGTERM
3092          * and a SIGHUP, we may as well use the same signal, because some user
3093          * pthreads are stealing signals from us left and right.
3094          */
3095         for (i = 0; i < num_buckets; i++) {
3096             ap_mpm_podx_killpg(all_buckets[i].pod, active_daemons_limit,
3097                                AP_MPM_PODX_RESTART);
3098         }
3099
3100         ap_reclaim_child_processes(1,  /* Start with SIGTERM */
3101                                    event_note_child_killed);
3102         ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, APLOGNO(00494)
3103                      "SIGHUP received.  Attempting to restart");
3104     }
3105
3106     active_daemons = 0;
3107
3108     return OK;
3109 }
3110
3111 static void setup_slave_conn(conn_rec *c, void *csd) 
3112 {
3113     event_conn_state_t *mcs;
3114     event_conn_state_t *cs;
3115     
3116     mcs = ap_get_module_config(c->master->conn_config, &mpm_event_module);
3117     
3118     cs = apr_pcalloc(c->pool, sizeof(*cs));
3119     cs->c = c;
3120     cs->r = NULL;
3121     cs->sc = mcs->sc;
3122     cs->suspended = 0;
3123     cs->p = c->pool;
3124     cs->bucket_alloc = c->bucket_alloc;
3125     cs->pfd = mcs->pfd;
3126     cs->pub = mcs->pub;
3127     cs->pub.state = CONN_STATE_READ_REQUEST_LINE;
3128     cs->pub.sense = CONN_SENSE_DEFAULT;
3129     
3130     c->cs = &(cs->pub);
3131     ap_set_module_config(c->conn_config, &mpm_event_module, cs);
3132 }
3133
3134 static int event_pre_connection(conn_rec *c, void *csd)
3135 {
3136     if (c->master && (!c->cs || c->cs == c->master->cs)) {
3137         setup_slave_conn(c, csd);
3138     }
3139     return OK;
3140 }
3141
3142 static int event_protocol_switch(conn_rec *c, request_rec *r, server_rec *s,
3143                                  const char *protocol)
3144 {
3145     if (!r && s) {
3146         /* connection based switching of protocol, set the correct server
3147          * configuration, so that timeouts, keepalives and such are used
3148          * for the server that the connection was switched on.
3149          * Normally, we set this on post_read_request, but on a protocol
3150          * other than http/1.1, this might never happen.
3151          */
3152         event_conn_state_t *cs;
3153         
3154         cs = ap_get_module_config(c->conn_config, &mpm_event_module);
3155         cs->sc = ap_get_module_config(s->module_config, &mpm_event_module);
3156     }
3157     return DECLINED;
3158 }
3159
3160 /* This really should be a post_config hook, but the error log is already
3161  * redirected by that point, so we need to do this in the open_logs phase.
3162  */
3163 static int event_open_logs(apr_pool_t * p, apr_pool_t * plog,
3164                            apr_pool_t * ptemp, server_rec * s)
3165 {
3166     int startup = 0;
3167     int level_flags = 0;
3168     int num_buckets = 0;
3169     ap_listen_rec **listen_buckets;
3170     apr_status_t rv;
3171     int i;
3172
3173     pconf = p;
3174
3175     /* the reverse of pre_config, we want this only the first time around */
3176     if (retained->mpm->module_loads == 1) {
3177         startup = 1;
3178         level_flags |= APLOG_STARTUP;
3179     }
3180
3181     if ((num_listensocks = ap_setup_listeners(ap_server_conf)) < 1) {
3182         ap_log_error(APLOG_MARK, APLOG_ALERT | level_flags, 0,
3183                      (startup ? NULL : s),
3184                      "no listening sockets available, shutting down");
3185         return !OK;
3186     }
3187
3188     if (one_process) {
3189         num_buckets = 1;
3190     }
3191     else if (retained->mpm->was_graceful) {
3192         /* Preserve the number of buckets on graceful restarts. */
3193         num_buckets = retained->mpm->num_buckets;
3194     }
3195     if ((rv = ap_duplicate_listeners(pconf, ap_server_conf,
3196                                      &listen_buckets, &num_buckets))) {
3197         ap_log_error(APLOG_MARK, APLOG_CRIT | level_flags, rv,
3198                      (startup ? NULL : s),
3199                      "could not duplicate listeners");
3200         return !OK;
3201     }
3202
3203     all_buckets = apr_pcalloc(pconf, num_buckets * sizeof(*all_buckets));
3204     for (i = 0; i < num_buckets; i++) {
3205         if (!one_process && /* no POD in one_process mode */
3206                 (rv = ap_mpm_podx_open(pconf, &all_buckets[i].pod))) {
3207             ap_log_error(APLOG_MARK, APLOG_CRIT | level_flags, rv,
3208                          (startup ? NULL : s),
3209                          "could not open pipe-of-death");
3210             return !OK;
3211         }
3212         all_buckets[i].listeners = listen_buckets[i];
3213     }
3214
3215     if (retained->mpm->max_buckets < num_buckets) {
3216         int new_max, *new_ptr;
3217         new_max = retained->mpm->max_buckets * 2;
3218         if (new_max < num_buckets) {
3219             new_max = num_buckets;
3220         }
3221         new_ptr = (int *)apr_palloc(ap_pglobal, new_max * sizeof(int));
3222         memcpy(new_ptr, retained->idle_spawn_rate,
3223                retained->mpm->num_buckets * sizeof(int));
3224         retained->idle_spawn_rate = new_ptr;
3225         retained->mpm->max_buckets = new_max;
3226     }
3227     if (retained->mpm->num_buckets < num_buckets) {
3228         int rate_max = 1;
3229         /* If new buckets are added, set their idle spawn rate to
3230          * the highest so far, so that they get filled as quickly
3231          * as the existing ones.
3232          */
3233         for (i = 0; i < retained->mpm->num_buckets; i++) {
3234             if (rate_max < retained->idle_spawn_rate[i]) {
3235                 rate_max = retained->idle_spawn_rate[i];
3236             }
3237         }
3238         for (/* up to date i */; i < num_buckets; i++) {
3239             retained->idle_spawn_rate[i] = rate_max;
3240         }
3241     }
3242     retained->mpm->num_buckets = num_buckets;
3243
3244     /* for skiplist */
3245     srand((unsigned int)apr_time_now());
3246     return OK;
3247 }
3248
3249 static int event_pre_config(apr_pool_t * pconf, apr_pool_t * plog,
3250                             apr_pool_t * ptemp)
3251 {
3252     int no_detach, debug, foreground;
3253     apr_status_t rv;
3254     const char *userdata_key = "mpm_event_module";
3255     int test_atomics = 0;
3256
3257     debug = ap_exists_config_define("DEBUG");
3258
3259     if (debug) {
3260         foreground = one_process = 1;
3261         no_detach = 0;
3262     }
3263     else {
3264         one_process = ap_exists_config_define("ONE_PROCESS");
3265         no_detach = ap_exists_config_define("NO_DETACH");
3266         foreground = ap_exists_config_define("FOREGROUND");
3267     }
3268
3269     retained = ap_retained_data_get(userdata_key);
3270     if (!retained) {
3271         retained = ap_retained_data_create(userdata_key, sizeof(*retained));
3272         retained->mpm = ap_unixd_mpm_get_retained_data();
3273         retained->max_daemons_limit = -1;
3274         if (retained->mpm->module_loads) {
3275             test_atomics = 1;
3276         }
3277     }
3278     retained->mpm->mpm_state = AP_MPMQ_STARTING;
3279     if (retained->mpm->baton != retained) {
3280         retained->mpm->was_graceful = 0;
3281         retained->mpm->baton = retained;
3282     }
3283     ++retained->mpm->module_loads;
3284
3285     /* test once for correct operation of fdqueue */
3286     if (test_atomics || retained->mpm->module_loads == 2) {
3287         static apr_uint32_t foo1, foo2;
3288
3289         apr_atomic_set32(&foo1, 100);
3290         foo2 = apr_atomic_add32(&foo1, -10);
3291         if (foo2 != 100 || foo1 != 90) {
3292             ap_log_error(APLOG_MARK, APLOG_CRIT, 0, NULL, APLOGNO(02405)
3293                          "atomics not working as expected - add32 of negative number");
3294             return HTTP_INTERNAL_SERVER_ERROR;
3295         }
3296     }
3297
3298     /* sigh, want this only the second time around */
3299     if (retained->mpm->module_loads == 2) {
3300         rv = apr_pollset_create(&event_pollset, 1, plog,
3301                                 APR_POLLSET_THREADSAFE | APR_POLLSET_NOCOPY);
3302         if (rv != APR_SUCCESS) {
3303             ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL, APLOGNO(00495)
3304                          "Couldn't create a Thread Safe Pollset. "
3305                          "Is it supported on your platform?"
3306                          "Also check system or user limits!");
3307             return HTTP_INTERNAL_SERVER_ERROR;
3308         }
3309         apr_pollset_destroy(event_pollset);
3310
3311         if (!one_process && !foreground) {
3312             /* before we detach, setup crash handlers to log to errorlog */
3313             ap_fatal_signal_setup(ap_server_conf, pconf);
3314             rv = apr_proc_detach(no_detach ? APR_PROC_DETACH_FOREGROUND
3315                                  : APR_PROC_DETACH_DAEMONIZE);
3316             if (rv != APR_SUCCESS) {
3317                 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL, APLOGNO(00496)
3318                              "apr_proc_detach failed");
3319                 return HTTP_INTERNAL_SERVER_ERROR;
3320             }
3321         }
3322     }
3323
3324     parent_pid = ap_my_pid = getpid();
3325
3326     ap_listen_pre_config();
3327     ap_daemons_to_start = DEFAULT_START_DAEMON;
3328     min_spare_threads = DEFAULT_MIN_FREE_DAEMON * DEFAULT_THREADS_PER_CHILD;
3329     max_spare_threads = DEFAULT_MAX_FREE_DAEMON * DEFAULT_THREADS_PER_CHILD;
3330     server_limit = DEFAULT_SERVER_LIMIT;
3331     thread_limit = DEFAULT_THREAD_LIMIT;
3332     active_daemons_limit = server_limit;
3333     threads_per_child = DEFAULT_THREADS_PER_CHILD;
3334     max_workers = active_daemons_limit * threads_per_child;
3335     defer_linger_chain = NULL;
3336     had_healthy_child = 0;
3337     ap_extended_status = 0;
3338
3339     return OK;
3340 }
3341
3342 static int event_post_config(apr_pool_t *pconf, apr_pool_t *plog,
3343                              apr_pool_t *ptemp, server_rec *s)
3344 {
3345     struct {
3346         struct timeout_queue *tail, *q;
3347         apr_hash_t *hash;
3348     } wc, ka;
3349
3350     /* Not needed in pre_config stage */
3351     if (ap_state_query(AP_SQ_MAIN_STATE) == AP_SQ_MS_CREATE_PRE_CONFIG) {
3352         return OK;
3353     }
3354
3355     wc.tail = ka.tail = NULL;
3356     wc.hash = apr_hash_make(ptemp);
3357     ka.hash = apr_hash_make(ptemp);
3358
3359     linger_q = TO_QUEUE_MAKE(pconf, apr_time_from_sec(MAX_SECS_TO_LINGER),
3360                              NULL);
3361     short_linger_q = TO_QUEUE_MAKE(pconf, apr_time_from_sec(SECONDS_TO_LINGER),
3362                                    NULL);
3363
3364     for (; s; s = s->next) {
3365         event_srv_cfg *sc = apr_pcalloc(pconf, sizeof *sc);
3366
3367         ap_set_module_config(s->module_config, &mpm_event_module, sc);
3368         if (!wc.tail) {
3369             /* The main server uses the global queues */
3370             wc.q = TO_QUEUE_MAKE(pconf, s->timeout, NULL);
3371             apr_hash_set(wc.hash, &s->timeout, sizeof s->timeout, wc.q);
3372             wc.tail = write_completion_q = wc.q;
3373
3374             ka.q = TO_QUEUE_MAKE(pconf, s->keep_alive_timeout, NULL);
3375             apr_hash_set(ka.hash, &s->keep_alive_timeout,
3376                          sizeof s->keep_alive_timeout, ka.q);
3377             ka.tail = keepalive_q = ka.q;
3378         }
3379         else {
3380             /* The vhosts use any existing queue with the same timeout,
3381              * or their own queue(s) if there isn't */
3382             wc.q = apr_hash_get(wc.hash, &s->timeout, sizeof s->timeout);
3383             if (!wc.q) {
3384                 wc.q = TO_QUEUE_MAKE(pconf, s->timeout, wc.tail);
3385                 apr_hash_set(wc.hash, &s->timeout, sizeof s->timeout, wc.q);
3386                 wc.tail = wc.tail->next = wc.q;
3387             }
3388
3389             ka.q = apr_hash_get(ka.hash, &s->keep_alive_timeout,
3390                                 sizeof s->keep_alive_timeout);
3391             if (!ka.q) {
3392                 ka.q = TO_QUEUE_MAKE(pconf, s->keep_alive_timeout, ka.tail);
3393                 apr_hash_set(ka.hash, &s->keep_alive_timeout,
3394                              sizeof s->keep_alive_timeout, ka.q);
3395                 ka.tail = ka.tail->next = ka.q;
3396             }
3397         }
3398         sc->wc_q = wc.q;
3399         sc->ka_q = ka.q;
3400     }
3401
3402     return OK;
3403 }
3404
3405 static int event_check_config(apr_pool_t *p, apr_pool_t *plog,
3406                               apr_pool_t *ptemp, server_rec *s)
3407 {
3408     int startup = 0;
3409
3410     /* the reverse of pre_config, we want this only the first time around */
3411     if (retained->mpm->module_loads == 1) {
3412         startup = 1;
3413     }
3414
3415     if (server_limit > MAX_SERVER_LIMIT) {
3416         if (startup) {
3417             ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00497)
3418                          "WARNING: ServerLimit of %d exceeds compile-time "
3419                          "limit of %d servers, decreasing to %d.",
3420                          server_limit, MAX_SERVER_LIMIT, MAX_SERVER_LIMIT);
3421         } else {
3422             ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00498)
3423                          "ServerLimit of %d exceeds compile-time limit "
3424                          "of %d, decreasing to match",
3425                          server_limit, MAX_SERVER_LIMIT);
3426         }
3427         server_limit = MAX_SERVER_LIMIT;
3428     }
3429     else if (server_limit < 1) {
3430         if (startup) {
3431             ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00499)
3432                          "WARNING: ServerLimit of %d not allowed, "
3433                          "increasing to 1.", server_limit);
3434         } else {
3435             ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00500)
3436                          "ServerLimit of %d not allowed, increasing to 1",
3437                          server_limit);
3438         }
3439         server_limit = 1;
3440     }
3441
3442     /* you cannot change ServerLimit across a restart; ignore
3443      * any such attempts
3444      */
3445     if (!retained->first_server_limit) {
3446         retained->first_server_limit = server_limit;
3447     }
3448     else if (server_limit != retained->first_server_limit) {
3449         /* don't need a startup console version here */
3450         ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00501)
3451                      "changing ServerLimit to %d from original value of %d "
3452                      "not allowed during restart",
3453                      server_limit, retained->first_server_limit);
3454         server_limit = retained->first_server_limit;
3455     }
3456
3457     if (thread_limit > MAX_THREAD_LIMIT) {
3458         if (startup) {
3459             ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00502)
3460                          "WARNING: ThreadLimit of %d exceeds compile-time "
3461                          "limit of %d threads, decreasing to %d.",
3462                          thread_limit, MAX_THREAD_LIMIT, MAX_THREAD_LIMIT);
3463         } else {
3464             ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00503)
3465                          "ThreadLimit of %d exceeds compile-time limit "
3466                          "of %d, decreasing to match",
3467                          thread_limit, MAX_THREAD_LIMIT);
3468         }
3469         thread_limit = MAX_THREAD_LIMIT;
3470     }
3471     else if (thread_limit < 1) {
3472         if (startup) {
3473             ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00504)
3474                          "WARNING: ThreadLimit of %d not allowed, "
3475                          "increasing to 1.", thread_limit);
3476         } else {
3477             ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00505)
3478                          "ThreadLimit of %d not allowed, increasing to 1",
3479                          thread_limit);
3480         }
3481         thread_limit = 1;
3482     }
3483
3484     /* you cannot change ThreadLimit across a restart; ignore
3485      * any such attempts
3486      */
3487     if (!retained->first_thread_limit) {
3488         retained->first_thread_limit = thread_limit;
3489     }
3490     else if (thread_limit != retained->first_thread_limit) {
3491         /* don't need a startup console version here */
3492         ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00506)
3493                      "changing ThreadLimit to %d from original value of %d "
3494                      "not allowed during restart",
3495                      thread_limit, retained->first_thread_limit);
3496         thread_limit = retained->first_thread_limit;
3497     }
3498
3499     if (threads_per_child > thread_limit) {
3500         if (startup) {
3501             ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00507)
3502                          "WARNING: ThreadsPerChild of %d exceeds ThreadLimit "
3503                          "of %d threads, decreasing to %d. "
3504                          "To increase, please see the ThreadLimit directive.",
3505                          threads_per_child, thread_limit, thread_limit);
3506         } else {
3507             ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00508)
3508                          "ThreadsPerChild of %d exceeds ThreadLimit "
3509                          "of %d, decreasing to match",
3510                          threads_per_child, thread_limit);
3511         }
3512         threads_per_child = thread_limit;
3513     }
3514     else if (threads_per_child < 1) {
3515         if (startup) {
3516             ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00509)
3517                          "WARNING: ThreadsPerChild of %d not allowed, "
3518                          "increasing to 1.", threads_per_child);
3519         } else {
3520             ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00510)
3521                          "ThreadsPerChild of %d not allowed, increasing to 1",
3522                          threads_per_child);
3523         }
3524         threads_per_child = 1;
3525     }
3526
3527     if (max_workers < threads_per_child) {
3528         if (startup) {
3529             ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00511)
3530                          "WARNING: MaxRequestWorkers of %d is less than "
3531                          "ThreadsPerChild of %d, increasing to %d. "
3532                          "MaxRequestWorkers must be at least as large "
3533                          "as the number of threads in a single server.",
3534                          max_workers, threads_per_child, threads_per_child);
3535         } else {
3536             ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00512)
3537                          "MaxRequestWorkers of %d is less than ThreadsPerChild "
3538                          "of %d, increasing to match",
3539                          max_workers, threads_per_child);
3540         }
3541         max_workers = threads_per_child;
3542     }
3543
3544     active_daemons_limit = max_workers / threads_per_child;
3545
3546     if (max_workers % threads_per_child) {
3547         int tmp_max_workers = active_daemons_limit * threads_per_child;
3548
3549         if (startup) {
3550             ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00513)
3551                          "WARNING: MaxRequestWorkers of %d is not an integer "
3552                          "multiple of ThreadsPerChild of %d, decreasing to nearest "
3553                          "multiple %d, for a maximum of %d servers.",
3554                          max_workers, threads_per_child, tmp_max_workers,
3555                          active_daemons_limit);
3556         } else {
3557             ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00514)
3558                          "MaxRequestWorkers of %d is not an integer multiple "
3559                          "of ThreadsPerChild of %d, decreasing to nearest "
3560                          "multiple %d", max_workers, threads_per_child,
3561                          tmp_max_workers);
3562         }
3563         max_workers = tmp_max_workers;
3564     }
3565
3566     if (active_daemons_limit > server_limit) {
3567         if (startup) {
3568             ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00515)
3569                          "WARNING: MaxRequestWorkers of %d would require %d servers "
3570                          "and would exceed ServerLimit of %d, decreasing to %d. "
3571                          "To increase, please see the ServerLimit directive.",
3572                          max_workers, active_daemons_limit, server_limit,
3573                          server_limit * threads_per_child);
3574         } else {
3575             ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00516)
3576                          "MaxRequestWorkers of %d would require %d servers and "
3577                          "exceed ServerLimit of %d, decreasing to %d",
3578                          max_workers, active_daemons_limit, server_limit,
3579                          server_limit * threads_per_child);
3580         }
3581         active_daemons_limit = server_limit;
3582     }
3583
3584     /* ap_daemons_to_start > active_daemons_limit checked in ap_mpm_run() */
3585     if (ap_daemons_to_start < 1) {
3586         if (startup) {
3587             ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00517)
3588                          "WARNING: StartServers of %d not allowed, "
3589                          "increasing to 1.", ap_daemons_to_start);
3590         } else {
3591             ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00518)
3592                          "StartServers of %d not allowed, increasing to 1",
3593                          ap_daemons_to_start);
3594         }
3595         ap_daemons_to_start = 1;
3596     }
3597
3598     if (min_spare_threads < 1) {
3599         if (startup) {
3600             ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00519)
3601                          "WARNING: MinSpareThreads of %d not allowed, "
3602                          "increasing to 1 to avoid almost certain server "
3603                          "failure. Please read the documentation.",
3604                          min_spare_threads);
3605         } else {
3606             ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00520)
3607                          "MinSpareThreads of %d not allowed, increasing to 1",
3608                          min_spare_threads);
3609         }
3610         min_spare_threads = 1;
3611     }
3612
3613     /* max_spare_threads < min_spare_threads + threads_per_child
3614      * checked in ap_mpm_run()
3615      */
3616
3617     return OK;
3618 }
3619
3620 static void event_hooks(apr_pool_t * p)
3621 {
3622     /* Our open_logs hook function must run before the core's, or stderr
3623      * will be redirected to a file, and the messages won't print to the
3624      * console.
3625      */
3626     static const char *const aszSucc[] = { "core.c", NULL };
3627     one_process = 0;
3628
3629     ap_hook_open_logs(event_open_logs, NULL, aszSucc, APR_HOOK_REALLY_FIRST);
3630     /* we need to set the MPM state before other pre-config hooks use MPM query
3631      * to retrieve it, so register as REALLY_FIRST
3632      */
3633     ap_hook_pre_config(event_pre_config, NULL, NULL, APR_HOOK_REALLY_FIRST);
3634     ap_hook_post_config(event_post_config, NULL, NULL, APR_HOOK_MIDDLE);
3635     ap_hook_check_config(event_check_config, NULL, NULL, APR_HOOK_MIDDLE);
3636     ap_hook_mpm(event_run, NULL, NULL, APR_HOOK_MIDDLE);
3637     ap_hook_mpm_query(event_query, NULL, NULL, APR_HOOK_MIDDLE);
3638     ap_hook_mpm_register_timed_callback(event_register_timed_callback, NULL, NULL,
3639                                         APR_HOOK_MIDDLE);
3640     ap_hook_pre_read_request(event_pre_read_request, NULL, NULL, APR_HOOK_MIDDLE);
3641     ap_hook_post_read_request(event_post_read_request, NULL, NULL, APR_HOOK_MIDDLE);
3642     ap_hook_mpm_get_name(event_get_name, NULL, NULL, APR_HOOK_MIDDLE);
3643
3644     ap_hook_pre_connection(event_pre_connection, NULL, NULL, APR_HOOK_REALLY_FIRST);
3645     ap_hook_protocol_switch(event_protocol_switch, NULL, NULL, APR_HOOK_REALLY_FIRST);
3646 }
3647
3648 static const char *set_daemons_to_start(cmd_parms *cmd, void *dummy,
3649                                         const char *arg)
3650 {
3651     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3652     if (err != NULL) {
3653         return err;
3654     }
3655
3656     ap_daemons_to_start = atoi(arg);
3657     return NULL;
3658 }
3659
3660 static const char *set_min_spare_threads(cmd_parms * cmd, void *dummy,
3661                                          const char *arg)
3662 {
3663     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3664     if (err != NULL) {
3665         return err;
3666     }
3667
3668     min_spare_threads = atoi(arg);
3669     return NULL;
3670 }
3671
3672 static const char *set_max_spare_threads(cmd_parms * cmd, void *dummy,
3673                                          const char *arg)
3674 {
3675     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3676     if (err != NULL) {
3677         return err;
3678     }
3679
3680     max_spare_threads = atoi(arg);
3681     return NULL;
3682 }
3683
3684 static const char *set_max_workers(cmd_parms * cmd, void *dummy,
3685                                    const char *arg)
3686 {
3687     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3688     if (err != NULL) {
3689         return err;
3690     }
3691     if (!strcasecmp(cmd->cmd->name, "MaxClients")) {
3692         ap_log_error(APLOG_MARK, APLOG_INFO, 0, NULL, APLOGNO(00521)
3693                      "MaxClients is deprecated, use MaxRequestWorkers "
3694                      "instead.");
3695     }
3696     max_workers = atoi(arg);
3697     return NULL;
3698 }
3699
3700 static const char *set_threads_per_child(cmd_parms * cmd, void *dummy,
3701                                          const char *arg)
3702 {
3703     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3704     if (err != NULL) {
3705         return err;
3706     }
3707
3708     threads_per_child = atoi(arg);
3709     return NULL;
3710 }
3711 static const char *set_server_limit (cmd_parms *cmd, void *dummy, const char *arg)
3712 {
3713     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3714     if (err != NULL) {
3715         return err;
3716     }
3717
3718     server_limit = atoi(arg);
3719     return NULL;
3720 }
3721
3722 static const char *set_thread_limit(cmd_parms * cmd, void *dummy,
3723                                     const char *arg)
3724 {
3725     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3726     if (err != NULL) {
3727         return err;
3728     }
3729
3730     thread_limit = atoi(arg);
3731     return NULL;
3732 }
3733
3734 static const char *set_worker_factor(cmd_parms * cmd, void *dummy,
3735                                      const char *arg)
3736 {
3737     double val;
3738     char *endptr;
3739     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3740     if (err != NULL) {
3741         return err;
3742     }
3743
3744     val = strtod(arg, &endptr);
3745     if (*endptr)
3746         return "error parsing value";
3747
3748     if (val <= 0)
3749         return "AsyncRequestWorkerFactor argument must be a positive number";
3750
3751     worker_factor = val * WORKER_FACTOR_SCALE;
3752     if (worker_factor == 0)
3753         worker_factor = 1;
3754     return NULL;
3755 }
3756
3757
3758 static const command_rec event_cmds[] = {
3759     LISTEN_COMMANDS,
3760     AP_INIT_TAKE1("StartServers", set_daemons_to_start, NULL, RSRC_CONF,
3761                   "Number of child processes launched at server startup"),
3762     AP_INIT_TAKE1("ServerLimit", set_server_limit, NULL, RSRC_CONF,
3763                   "Maximum number of child processes for this run of Apache"),
3764     AP_INIT_TAKE1("MinSpareThreads", set_min_spare_threads, NULL, RSRC_CONF,
3765                   "Minimum number of idle threads, to handle request spikes"),
3766     AP_INIT_TAKE1("MaxSpareThreads", set_max_spare_threads, NULL, RSRC_CONF,
3767                   "Maximum number of idle threads"),
3768     AP_INIT_TAKE1("MaxClients", set_max_workers, NULL, RSRC_CONF,
3769                   "Deprecated name of MaxRequestWorkers"),
3770     AP_INIT_TAKE1("MaxRequestWorkers", set_max_workers, NULL, RSRC_CONF,
3771                   "Maximum number of threads alive at the same time"),
3772     AP_INIT_TAKE1("ThreadsPerChild", set_threads_per_child, NULL, RSRC_CONF,
3773                   "Number of threads each child creates"),
3774     AP_INIT_TAKE1("ThreadLimit", set_thread_limit, NULL, RSRC_CONF,
3775                   "Maximum number of worker threads per child process for this "
3776                   "run of Apache - Upper limit for ThreadsPerChild"),
3777     AP_INIT_TAKE1("AsyncRequestWorkerFactor", set_worker_factor, NULL, RSRC_CONF,
3778                   "How many additional connects will be accepted per idle "
3779                   "worker thread"),
3780     AP_GRACEFUL_SHUTDOWN_TIMEOUT_COMMAND,
3781     {NULL}
3782 };
3783
3784 AP_DECLARE_MODULE(mpm_event) = {
3785     MPM20_MODULE_STUFF,
3786     NULL,                       /* hook to run before apache parses args */
3787     NULL,                       /* create per-directory config structure */
3788     NULL,                       /* merge per-directory config structures */
3789     NULL,                       /* create per-server config structure */
3790     NULL,                       /* merge per-server config structures */
3791     event_cmds,                 /* command apr_table_t */
3792     event_hooks                 /* register_hooks */
3793 };