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