]> granicus.if.org Git - apache/blob - server/mpm/worker/worker.c
Implement apr_proc_detach changes and allow -DNO_DETACH in the multi-process
[apache] / server / mpm / worker / worker.c
1 /* ====================================================================
2  * The Apache Software License, Version 1.1
3  *
4  * Copyright (c) 2000-2001 The Apache Software Foundation.  All rights
5  * reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  *
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in
16  *    the documentation and/or other materials provided with the
17  *    distribution.
18  *
19  * 3. The end-user documentation included with the redistribution,
20  *    if any, must include the following acknowledgment:
21  *       "This product includes software developed by the
22  *        Apache Software Foundation (http://www.apache.org/)."
23  *    Alternately, this acknowledgment may appear in the software itself,
24  *    if and wherever such third-party acknowledgments normally appear.
25  *
26  * 4. The names "Apache" and "Apache Software Foundation" must
27  *    not be used to endorse or promote products derived from this
28  *    software without prior written permission. For written
29  *    permission, please contact apache@apache.org.
30  *
31  * 5. Products derived from this software may not be called "Apache",
32  *    nor may "Apache" appear in their name, without prior written
33  *    permission of the Apache Software Foundation.
34  *
35  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
36  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
37  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
38  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
39  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
42  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
43  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
44  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
45  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
46  * SUCH DAMAGE.
47  * ====================================================================
48  *
49  * This software consists of voluntary contributions made by many
50  * individuals on behalf of the Apache Software Foundation.  For more
51  * information on the Apache Software Foundation, please see
52  * <http://www.apache.org/>.
53  *
54  * Portions of this software are based upon public domain software
55  * originally written at the National Center for Supercomputing Applications,
56  * University of Illinois, Urbana-Champaign.
57  */
58
59 /* The purpose of this MPM is to fix the design flaws in the threaded
60  * model.  Because of the way that pthreads and mutex locks interact,
61  * it is basically impossible to cleanly gracefully shutdown a child
62  * process if multiple threads are all blocked in accept.  This model
63  * fixes those problems.
64  */
65
66 #include "apr.h"
67 #include "apr_portable.h"
68 #include "apr_strings.h"
69 #include "apr_file_io.h"
70 #include "apr_thread_proc.h"
71 #include "apr_signal.h"
72 #include "apr_thread_mutex.h"
73 #include "apr_proc_mutex.h"
74 #define APR_WANT_STRFUNC
75 #include "apr_want.h"
76
77 #if APR_HAVE_UNISTD_H
78 #include <unistd.h>
79 #endif
80 #if APR_HAVE_SYS_SOCKET_H
81 #include <sys/socket.h>
82 #endif
83 #if APR_HAVE_SYS_WAIT_H
84 #include <sys/wait.h> 
85 #endif
86 #ifdef HAVE_SYS_PROCESSOR_H
87 #include <sys/processor.h> /* for bindprocessor() */
88 #endif
89
90 #if !APR_HAS_THREADS
91 #error The Worker MPM requires APR threads, but they are unavailable.
92 #endif
93
94 #define CORE_PRIVATE 
95  
96 #include "ap_config.h"
97 #include "httpd.h" 
98 #include "http_main.h" 
99 #include "http_log.h" 
100 #include "http_config.h"        /* for read_config */ 
101 #include "http_core.h"          /* for get_remote_host */ 
102 #include "http_connection.h"
103 #include "ap_mpm.h"
104 #include "pod.h"
105 #include "mpm_common.h"
106 #include "ap_listen.h"
107 #include "scoreboard.h" 
108 #include "fdqueue.h"
109 #include "mpm_default.h"
110
111 #include <signal.h>
112 #include <limits.h>             /* for INT_MAX */
113
114 /* Limit on the total --- clients will be locked out if more servers than
115  * this are needed.  It is intended solely to keep the server from crashing
116  * when things get out of hand.
117  *
118  * We keep a hard maximum number of servers, for two reasons --- first off,
119  * in case something goes seriously wrong, we want to stop the fork bomb
120  * short of actually crashing the machine we're running on by filling some
121  * kernel table.  Secondly, it keeps the size of the scoreboard file small
122  * enough that we can read the whole thing without worrying too much about
123  * the overhead.
124  */
125 #ifndef DEFAULT_SERVER_LIMIT
126 #define DEFAULT_SERVER_LIMIT 16
127 #endif
128
129 /* Admin can't tune ServerLimit beyond MAX_SERVER_LIMIT.  We want
130  * some sort of compile-time limit to help catch typos.
131  */
132 #ifndef MAX_SERVER_LIMIT
133 #define MAX_SERVER_LIMIT 20000
134 #endif
135
136 /* Limit on the threads per process.  Clients will be locked out if more than
137  * this  * server_limit are needed.
138  *
139  * We keep this for one reason it keeps the size of the scoreboard file small
140  * enough that we can read the whole thing without worrying too much about
141  * the overhead.
142  */
143 #ifndef DEFAULT_THREAD_LIMIT
144 #define DEFAULT_THREAD_LIMIT 64 
145 #endif
146
147 /* Admin can't tune ThreadLimit beyond MAX_THREAD_LIMIT.  We want
148  * some sort of compile-time limit to help catch typos.
149  */
150 #ifndef MAX_THREAD_LIMIT
151 #define MAX_THREAD_LIMIT 20000
152 #endif
153
154 /*
155  * Actual definitions of config globals
156  */
157
158 int ap_threads_per_child = 0;         /* Worker threads per child */
159 static int ap_daemons_to_start = 0;
160 static int min_spare_threads = 0;
161 static int max_spare_threads = 0;
162 static int ap_daemons_limit = 0;
163 static int server_limit = DEFAULT_SERVER_LIMIT;
164 static int first_server_limit;
165 static int thread_limit = DEFAULT_THREAD_LIMIT;
166 static int first_thread_limit;
167 static int changed_limit_at_restart;
168 static int dying = 0;
169 static int workers_may_exit = 0;
170 static int requests_this_child;
171 static int num_listensocks = 0;
172 static int resource_shortage = 0;
173 static fd_queue_t *worker_queue;
174
175 /* The structure used to pass unique initialization info to each thread */
176 typedef struct {
177     int pid;
178     int tid;
179     int sd;
180 } proc_info;
181
182 /* Structure used to pass information to the thread responsible for 
183  * creating the rest of the threads.
184  */
185 typedef struct {
186     apr_thread_t **threads;
187     int child_num_arg;
188     apr_threadattr_t *threadattr;
189 } thread_starter;
190
191 #define ID_FROM_CHILD_THREAD(c, t)    ((c * thread_limit) + t)
192
193 /*
194  * The max child slot ever assigned, preserved across restarts.  Necessary
195  * to deal with MaxClients changes across AP_SIG_GRACEFUL restarts.  We 
196  * use this value to optimize routines that have to scan the entire 
197  * scoreboard.
198  */
199 int ap_max_daemons_limit = -1;
200
201 static ap_pod_t *pod;
202
203 /* *Non*-shared http_main globals... */
204
205 server_rec *ap_server_conf;
206
207 /* The worker MPM respects a couple of runtime flags that can aid
208  * in debugging. Setting the -DNO_DETACH flag will prevent the root process
209  * from detaching from its controlling terminal. Additionally, setting
210  * the -DONE_PROCESS flag (which implies -DNO_DETACH) will get you the
211  * child_main loop running in the process which originally started up.
212  * This gives you a pretty nice debugging environment.  (You'll get a SIGHUP
213  * early in standalone_main; just continue through.  This is the server
214  * trying to kill off any child processes which it might have lying
215  * around --- Apache doesn't keep track of their pids, it just sends
216  * SIGHUP to the process group, ignoring it in the root process.
217  * Continue through and you'll be fine.).
218  */
219
220 static int one_process = 0;
221
222 #ifdef DEBUG_SIGSTOP
223 int raise_sigstop_flags;
224 #endif
225
226 static apr_pool_t *pconf;                 /* Pool for config stuff */
227 static apr_pool_t *pchild;                /* Pool for httpd child stuff */
228
229 static pid_t ap_my_pid; /* Linux getpid() doesn't work except in main 
230                            thread. Use this instead */
231 static pid_t parent_pid;
232 /* Keep track of the number of worker threads currently active */
233 static int worker_thread_count;
234 static apr_thread_mutex_t *worker_thread_count_mutex;
235
236 /* Locks for accept serialization */
237 static apr_proc_mutex_t *accept_mutex;
238
239 #ifdef SINGLE_LISTEN_UNSERIALIZED_ACCEPT
240 #define SAFE_ACCEPT(stmt) (ap_listeners->next ? (stmt) : APR_SUCCESS)
241 #else
242 #define SAFE_ACCEPT(stmt) (stmt)
243 #endif
244
245 static void signal_workers(void)
246 {
247     workers_may_exit = 1;
248     /* XXX: This will happen naturally on a graceful, and we don't care 
249      * otherwise.
250     ap_queue_signal_all_wakeup(worker_queue); */
251     ap_queue_interrupt_all(worker_queue);
252 }
253
254 AP_DECLARE(apr_status_t) ap_mpm_query(int query_code, int *result)
255 {
256     switch(query_code){
257         case AP_MPMQ_MAX_DAEMON_USED:
258             *result = ap_max_daemons_limit;
259             return APR_SUCCESS;
260         case AP_MPMQ_IS_THREADED:
261             *result = AP_MPMQ_STATIC;
262             return APR_SUCCESS;
263         case AP_MPMQ_IS_FORKED:
264             *result = AP_MPMQ_DYNAMIC;
265             return APR_SUCCESS;
266         case AP_MPMQ_HARD_LIMIT_DAEMONS:
267             *result = server_limit;
268             return APR_SUCCESS;
269         case AP_MPMQ_HARD_LIMIT_THREADS:
270             *result = thread_limit;
271             return APR_SUCCESS;
272         case AP_MPMQ_MAX_THREADS:
273             *result = ap_threads_per_child;
274             return APR_SUCCESS;
275         case AP_MPMQ_MIN_SPARE_DAEMONS:
276             *result = 0;
277             return APR_SUCCESS;
278         case AP_MPMQ_MIN_SPARE_THREADS:    
279             *result = min_spare_threads;
280             return APR_SUCCESS;
281         case AP_MPMQ_MAX_SPARE_DAEMONS:
282             *result = 0;
283             return APR_SUCCESS;
284         case AP_MPMQ_MAX_SPARE_THREADS:
285             *result = max_spare_threads;
286             return APR_SUCCESS;
287         case AP_MPMQ_MAX_REQUESTS_DAEMON:
288             *result = ap_max_requests_per_child;
289             return APR_SUCCESS;
290         case AP_MPMQ_MAX_DAEMONS:
291             *result = ap_daemons_limit;
292             return APR_SUCCESS;
293     }
294     return APR_ENOTIMPL;
295 }
296
297 /* a clean exit from a child with proper cleanup */ 
298 static void clean_child_exit(int code) __attribute__ ((noreturn));
299 static void clean_child_exit(int code)
300 {
301     if (pchild) {
302         apr_pool_destroy(pchild);
303     }
304     exit(code);
305 }
306
307 /* handle all varieties of core dumping signals */
308 static void sig_coredump(int sig)
309 {
310     apr_filepath_set(ap_coredump_dir, pconf);
311     apr_signal(sig, SIG_DFL);
312     if (ap_my_pid == parent_pid) {
313         ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE,
314                      0, ap_server_conf,
315                      "seg fault or similar nasty error detected "
316                      "in the parent process");
317         
318         /* XXX we can probably add some rudimentary cleanup code here,
319          * like getting rid of the pid file.  If any additional bad stuff
320          * happens, we are protected from recursive errors taking down the
321          * system since this function is no longer the signal handler   GLA
322          */
323     }
324     kill(ap_my_pid, sig);
325     /* At this point we've got sig blocked, because we're still inside
326      * the signal handler.  When we leave the signal handler it will
327      * be unblocked, and we'll take the signal... and coredump or whatever
328      * is appropriate for this particular Unix.  In addition the parent
329      * will see the real signal we received -- whereas if we called
330      * abort() here, the parent would only see SIGABRT.
331      */
332 }
333
334 static void just_die(int sig)
335 {
336     clean_child_exit(0);
337 }
338
339 /*****************************************************************
340  * Connection structures and accounting...
341  */
342
343 /* volatile just in case */
344 static int volatile shutdown_pending;
345 static int volatile restart_pending;
346 static int volatile is_graceful;
347 static volatile int child_fatal;
348 ap_generation_t volatile ap_my_generation;
349
350 /*
351  * ap_start_shutdown() and ap_start_restart(), below, are a first stab at
352  * functions to initiate shutdown or restart without relying on signals. 
353  * Previously this was initiated in sig_term() and restart() signal handlers, 
354  * but we want to be able to start a shutdown/restart from other sources --
355  * e.g. on Win32, from the service manager. Now the service manager can
356  * call ap_start_shutdown() or ap_start_restart() as appropiate.  Note that
357  * these functions can also be called by the child processes, since global
358  * variables are no longer used to pass on the required action to the parent.
359  *
360  * These should only be called from the parent process itself, since the
361  * parent process will use the shutdown_pending and restart_pending variables
362  * to determine whether to shutdown or restart. The child process should
363  * call signal_parent() directly to tell the parent to die -- this will
364  * cause neither of those variable to be set, which the parent will
365  * assume means something serious is wrong (which it will be, for the
366  * child to force an exit) and so do an exit anyway.
367  */
368
369 static void ap_start_shutdown(void)
370 {
371     if (shutdown_pending == 1) {
372         /* Um, is this _probably_ not an error, if the user has
373          * tried to do a shutdown twice quickly, so we won't
374          * worry about reporting it.
375          */
376         return;
377     }
378     shutdown_pending = 1;
379 }
380
381 /* do a graceful restart if graceful == 1 */
382 static void ap_start_restart(int graceful)
383 {
384
385     if (restart_pending == 1) {
386         /* Probably not an error - don't bother reporting it */
387         return;
388     }
389     restart_pending = 1;
390     is_graceful = graceful;
391     if (is_graceful) {
392         apr_pool_cleanup_kill(pconf, NULL, ap_cleanup_scoreboard);
393     }
394 }
395
396 static void sig_term(int sig)
397 {
398     ap_start_shutdown();
399 }
400
401 static void restart(int sig)
402 {
403     ap_start_restart(sig == AP_SIG_GRACEFUL);
404 }
405
406 static void set_signals(void)
407 {
408 #ifndef NO_USE_SIGACTION
409     struct sigaction sa;
410
411     sigemptyset(&sa.sa_mask);
412     sa.sa_flags = 0;
413
414     if (!one_process) {
415         sa.sa_handler = sig_coredump;
416 #if defined(SA_ONESHOT)
417         sa.sa_flags = SA_ONESHOT;
418 #elif defined(SA_RESETHAND)
419         sa.sa_flags = SA_RESETHAND;
420 #endif
421         if (sigaction(SIGSEGV, &sa, NULL) < 0)
422             ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, 
423                          "sigaction(SIGSEGV)");
424 #ifdef SIGBUS
425         if (sigaction(SIGBUS, &sa, NULL) < 0)
426             ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, 
427                          "sigaction(SIGBUS)");
428 #endif
429 #ifdef SIGABORT
430         if (sigaction(SIGABORT, &sa, NULL) < 0)
431             ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, 
432                          "sigaction(SIGABORT)");
433 #endif
434 #ifdef SIGABRT
435         if (sigaction(SIGABRT, &sa, NULL) < 0)
436             ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, 
437                          "sigaction(SIGABRT)");
438 #endif
439 #ifdef SIGILL
440         if (sigaction(SIGILL, &sa, NULL) < 0)
441             ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, 
442                          "sigaction(SIGILL)");
443 #endif
444         sa.sa_flags = 0;
445     }
446     sa.sa_handler = sig_term;
447     if (sigaction(SIGTERM, &sa, NULL) < 0)
448         ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, 
449                      "sigaction(SIGTERM)");
450 #ifdef SIGINT
451     if (sigaction(SIGINT, &sa, NULL) < 0)
452         ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, 
453                      "sigaction(SIGINT)");
454 #endif
455 #ifdef SIGXCPU
456     sa.sa_handler = SIG_DFL;
457     if (sigaction(SIGXCPU, &sa, NULL) < 0)
458         ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, 
459                      "sigaction(SIGXCPU)");
460 #endif
461 #ifdef SIGXFSZ
462     sa.sa_handler = SIG_DFL;
463     if (sigaction(SIGXFSZ, &sa, NULL) < 0)
464         ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, 
465                      "sigaction(SIGXFSZ)");
466 #endif
467 #ifdef SIGPIPE
468     sa.sa_handler = SIG_IGN;
469     if (sigaction(SIGPIPE, &sa, NULL) < 0)
470         ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, 
471                      "sigaction(SIGPIPE)");
472 #endif
473
474     /* we want to ignore HUPs and AP_SIG_GRACEFUL while we're busy 
475      * processing one */
476     sigaddset(&sa.sa_mask, SIGHUP);
477     sigaddset(&sa.sa_mask, AP_SIG_GRACEFUL);
478     sa.sa_handler = restart;
479     if (sigaction(SIGHUP, &sa, NULL) < 0)
480         ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, 
481                      "sigaction(SIGHUP)");
482     if (sigaction(AP_SIG_GRACEFUL, &sa, NULL) < 0)
483         ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, 
484                      "sigaction(" AP_SIG_GRACEFUL_STRING ")");
485 #else
486     if (!one_process) {
487         apr_signal(SIGSEGV, sig_coredump);
488 #ifdef SIGBUS
489         apr_signal(SIGBUS, sig_coredump);
490 #endif /* SIGBUS */
491 #ifdef SIGABORT
492         apr_signal(SIGABORT, sig_coredump);
493 #endif /* SIGABORT */
494 #ifdef SIGABRT
495         apr_signal(SIGABRT, sig_coredump);
496 #endif /* SIGABRT */
497 #ifdef SIGILL
498         apr_signal(SIGILL, sig_coredump);
499 #endif /* SIGILL */
500 #ifdef SIGXCPU
501         apr_signal(SIGXCPU, SIG_DFL);
502 #endif /* SIGXCPU */
503 #ifdef SIGXFSZ
504         apr_signal(SIGXFSZ, SIG_DFL);
505 #endif /* SIGXFSZ */
506     }
507
508     apr_signal(SIGTERM, sig_term);
509 #ifdef SIGHUP
510     apr_signal(SIGHUP, restart);
511 #endif /* SIGHUP */
512 #ifdef AP_SIG_GRACEFUL
513     apr_signal(AP_SIG_GRACEFUL, restart);
514 #endif /* AP_SIG_GRACEFUL */
515 #ifdef SIGPIPE
516     apr_signal(SIGPIPE, SIG_IGN);
517 #endif /* SIGPIPE */
518
519 #endif
520 }
521
522 /*****************************************************************
523  * Here follows a long bunch of generic server bookkeeping stuff...
524  */
525
526 int ap_graceful_stop_signalled(void)
527     /* XXX this is really a bad confusing obsolete name
528      * maybe it should be ap_mpm_process_exiting?
529      */
530 {
531     return workers_may_exit;
532 }
533
534 /*****************************************************************
535  * Child process main loop.
536  */
537
538 static void process_socket(apr_pool_t *p, apr_socket_t *sock, int my_child_num,
539                            int my_thread_num)
540 {
541     conn_rec *current_conn;
542     long conn_id = ID_FROM_CHILD_THREAD(my_child_num, my_thread_num);
543     int csd;
544     ap_sb_handle_t *sbh;
545
546     ap_create_sb_handle(&sbh, p, my_child_num, my_thread_num);
547     apr_os_sock_get(&csd, sock);
548
549     if (csd >= FD_SETSIZE) {
550         ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, NULL,
551                      "new file descriptor %d is too large; you probably need "
552                      "to rebuild Apache with a larger FD_SETSIZE "
553                      "(currently %d)", 
554                      csd, FD_SETSIZE);
555         apr_socket_close(sock);
556         return;
557     }
558
559     current_conn = ap_run_create_connection(p, ap_server_conf, sock, conn_id, sbh);
560     if (current_conn) {
561         ap_process_connection(current_conn, sock);
562         ap_lingering_close(current_conn);
563     }
564 }
565
566 /* requests_this_child has gone to zero or below.  See if the admin coded
567    "MaxRequestsPerChild 0", and keep going in that case.  Doing it this way
568    simplifies the hot path in worker_thread */
569 static void check_infinite_requests(void)
570 {
571     if (ap_max_requests_per_child) {
572         signal_workers();
573     }
574     else {
575         /* wow! if you're executing this code, you may have set a record.
576          * either this child process has served over 2 billion requests, or
577          * you're running a threaded 2.0 on a 16 bit machine.  
578          *
579          * I'll buy pizza and beers at Apachecon for the first person to do
580          * the former without cheating (dorking with INT_MAX, or running with
581          * uncommitted performance patches, for example).    
582          *
583          * for the latter case, you probably deserve a beer too.   Greg Ames
584          */
585             
586         requests_this_child = INT_MAX;      /* keep going */ 
587     }
588 }
589
590 static void *listener_thread(apr_thread_t *thd, void * dummy)
591 {
592     proc_info * ti = dummy;
593     int process_slot = ti->pid;
594     int thread_slot = ti->tid;
595     apr_pool_t *tpool = apr_thread_pool_get(thd);
596     void *csd = NULL;
597     apr_pool_t *ptrans;                /* Pool for per-transaction stuff */
598     apr_pool_t *recycled_pool = NULL;
599     int n;
600     apr_pollfd_t *pollset;
601     apr_status_t rv;
602     ap_listen_rec *lr, *last_lr = ap_listeners;
603
604     free(ti);
605
606     apr_thread_mutex_lock(worker_thread_count_mutex);
607     worker_thread_count++;
608     apr_thread_mutex_unlock(worker_thread_count_mutex);
609
610     apr_poll_setup(&pollset, num_listensocks, tpool);
611     for(lr = ap_listeners ; lr != NULL ; lr = lr->next)
612         apr_poll_socket_add(pollset, lr->sd, APR_POLLIN);
613
614     /* TODO: Switch to a system where threads reuse the results from earlier
615        poll calls - manoj */
616     while (1) {
617         /* TODO: requests_this_child should be synchronized - aaron */
618         if (requests_this_child <= 0) {
619             check_infinite_requests();
620         }
621         if (workers_may_exit) break;
622
623         if ((rv = SAFE_ACCEPT(apr_proc_mutex_lock(accept_mutex)))
624             != APR_SUCCESS) {
625             ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
626                          "apr_proc_mutex_lock failed. Attempting to shutdown "
627                          "process gracefully.");
628             signal_workers();
629         }
630
631         if (!ap_listeners->next) {
632             /* Only one listener, so skip the poll */
633             lr = ap_listeners;
634         }
635         else {
636             while (!workers_may_exit) {
637                 apr_status_t ret;
638                 apr_int16_t event;
639
640                 ret = apr_poll(pollset, &n, -1);
641                 if (ret != APR_SUCCESS) {
642                     if (APR_STATUS_IS_EINTR(ret)) {
643                         continue;
644                     }
645
646                     /* apr_poll() will only return errors in catastrophic
647                      * circumstances. Let's try exiting gracefully, for now. */
648                     ap_log_error(APLOG_MARK, APLOG_ERR, ret, (const server_rec *)
649                                  ap_server_conf, "apr_poll: (listen)");
650                     signal_workers();
651                 }
652
653                 if (workers_may_exit) break;
654
655                 /* find a listener */
656                 lr = last_lr;
657                 do {
658                     lr = lr->next;
659                     if (lr == NULL) {
660                         lr = ap_listeners;
661                     }
662                     /* XXX: Should we check for POLLERR? */
663                     apr_poll_revents_get(&event, lr->sd, pollset);
664                     if (event & APR_POLLIN) {
665                         last_lr = lr;
666                         goto got_fd;
667                     }
668                 } while (lr != last_lr);
669             }
670         }
671     got_fd:
672         if (!workers_may_exit) {
673             /* create a new transaction pool for each accepted socket */
674             if (recycled_pool == NULL) {
675                 apr_pool_create_ex(&ptrans, NULL, NULL, APR_POOL_FNEW_ALLOCATOR);
676             }
677             else {
678                 ptrans = recycled_pool;
679             }
680             apr_pool_tag(ptrans, "transaction");
681             rv = lr->accept_func(&csd, lr, ptrans);
682
683             /* If we were interrupted for whatever reason, just start
684              * the main loop over again. (The worker MPM still uses
685              * signals in the one_process case.) */
686             if (APR_STATUS_IS_EINTR(rv)) {
687                 continue;
688             }
689             if (rv == APR_EGENERAL) {
690                 /* E[NM]FILE, ENOMEM, etc */
691                 resource_shortage = 1;
692                 signal_workers();
693             }
694             if ((rv = SAFE_ACCEPT(apr_proc_mutex_unlock(accept_mutex)))
695                 != APR_SUCCESS) {
696                 ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
697                              "apr_proc_mutex_lock failed. Attempting to "
698                              "shutdown process gracefully.");
699                 signal_workers();
700             }
701             if (csd != NULL) {
702                 rv = ap_queue_push(worker_queue, csd, ptrans,
703                                    &recycled_pool);
704                 if (rv) {
705                     /* trash the connection; we couldn't queue the connected
706                      * socket to a worker 
707                      */
708                     apr_socket_close(csd);
709                     ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
710                                  "ap_queue_push failed");
711                 }
712             }
713         }
714         else {
715             if ((rv = SAFE_ACCEPT(apr_proc_mutex_unlock(accept_mutex)))
716                 != APR_SUCCESS) {
717                 ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
718                              "apr_proc_mutex_unlock failed. Attempting to "
719                              "shutdown process gracefully.");
720                 signal_workers();
721             }
722             break;
723         }
724     }
725
726     ap_update_child_status_from_indexes(process_slot, thread_slot, 
727                                         (dying) ? SERVER_DEAD : SERVER_GRACEFUL,
728                                         (request_rec *) NULL);
729     dying = 1;
730     ap_scoreboard_image->parent[process_slot].quiescing = 1;
731     kill(ap_my_pid, SIGTERM);
732
733     apr_thread_exit(thd, APR_SUCCESS);
734     return NULL;
735 }
736
737 static void * APR_THREAD_FUNC worker_thread(apr_thread_t *thd, void * dummy)
738 {
739     proc_info * ti = dummy;
740     int process_slot = ti->pid;
741     int thread_slot = ti->tid;
742     apr_socket_t *csd = NULL;
743     apr_pool_t *last_ptrans = NULL;
744     apr_pool_t *ptrans;                /* Pool for per-transaction stuff */
745     apr_status_t rv;
746
747     free(ti);
748
749     ap_update_child_status_from_indexes(process_slot, thread_slot, SERVER_STARTING, NULL);
750     while (!workers_may_exit) {
751         ap_update_child_status_from_indexes(process_slot, thread_slot, SERVER_READY, NULL);
752         rv = ap_queue_pop(worker_queue, &csd, &ptrans, last_ptrans);
753         last_ptrans = NULL;
754
755         /* We get APR_EINTR whenever ap_queue_pop() has been interrupted
756          * from an explicit call to ap_queue_interrupt_all(). This allows
757          * us to unblock threads stuck in ap_queue_pop() when a shutdown
758          * is pending. */
759         if (rv == APR_EINTR || !csd) {
760             continue;
761         }
762         process_socket(ptrans, csd, process_slot, thread_slot);
763         requests_this_child--; /* FIXME: should be synchronized - aaron */
764         apr_pool_clear(ptrans);
765         last_ptrans = ptrans;
766     }
767
768     ap_update_child_status_from_indexes(process_slot, thread_slot,
769         (dying) ? SERVER_DEAD : SERVER_GRACEFUL, (request_rec *) NULL);
770     apr_thread_mutex_lock(worker_thread_count_mutex);
771     worker_thread_count--;
772     apr_thread_mutex_unlock(worker_thread_count_mutex);
773
774     apr_thread_exit(thd, APR_SUCCESS);
775     return NULL;
776 }
777
778 static int check_signal(int signum)
779 {
780     switch (signum) {
781     case SIGTERM:
782     case SIGINT:
783         return 1;
784     }
785     return 0;
786 }
787
788 static void * APR_THREAD_FUNC start_threads(apr_thread_t *thd, void *dummy)
789 {
790     thread_starter *ts = dummy;
791     apr_thread_t **threads = ts->threads;
792     apr_threadattr_t *thread_attr = ts->threadattr;
793     int child_num_arg = ts->child_num_arg;
794     int my_child_num = child_num_arg;
795     proc_info *my_info = NULL;
796     apr_status_t rv;
797     int i = 0;
798     int threads_created = 0;
799     apr_thread_t *listener;
800
801     /* We must create the fd queues before we start up the listener
802      * and worker threads. */
803     worker_queue = apr_pcalloc(pchild, sizeof(*worker_queue));
804     rv = ap_queue_init(worker_queue, ap_threads_per_child, pchild);
805     if (rv != APR_SUCCESS) {
806         ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
807                      "ap_queue_init() failed");
808         clean_child_exit(APEXIT_CHILDFATAL);
809     }
810
811     my_info = (proc_info *)malloc(sizeof(proc_info));
812     my_info->pid = my_child_num;
813     my_info->tid = i;
814     my_info->sd = 0;
815     rv = apr_thread_create(&listener, thread_attr, listener_thread,
816                            my_info, pchild);
817     if (rv != APR_SUCCESS) {
818         ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
819                      "apr_thread_create: unable to create worker thread");
820         /* In case system resources are maxxed out, we don't want
821          * Apache running away with the CPU trying to fork over and
822          * over and over again if we exit.
823          * XXX Jeff doesn't see how Apache is going to try to fork again since
824          * the exit code is APEXIT_CHILDFATAL
825          */
826         apr_sleep(10 * APR_USEC_PER_SEC);
827         clean_child_exit(APEXIT_CHILDFATAL);
828     }
829     while (1) {
830         /* ap_threads_per_child does not include the listener thread */
831         for (i = 0; i < ap_threads_per_child; i++) {
832             int status = ap_scoreboard_image->servers[child_num_arg][i].status;
833
834             if (status != SERVER_GRACEFUL && status != SERVER_DEAD) {
835                 continue;
836             }
837
838             my_info = (proc_info *)malloc(sizeof(proc_info));
839             if (my_info == NULL) {
840                 ap_log_error(APLOG_MARK, APLOG_ALERT, errno, ap_server_conf,
841                              "malloc: out of memory");
842                 clean_child_exit(APEXIT_CHILDFATAL);
843             }
844             my_info->pid = my_child_num;
845             my_info->tid = i;
846             my_info->sd = 0;
847         
848             /* We are creating threads right now */
849             ap_update_child_status_from_indexes(my_child_num, i,
850                                                 SERVER_STARTING, NULL);
851             /* We let each thread update its own scoreboard entry.  This is
852              * done because it lets us deal with tid better.
853              */
854             rv = apr_thread_create(&threads[i], thread_attr, 
855                                    worker_thread, my_info, pchild);
856             if (rv != APR_SUCCESS) {
857                 ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
858                     "apr_thread_create: unable to create worker thread");
859                 /* In case system resources are maxxed out, we don't want
860                    Apache running away with the CPU trying to fork over and
861                    over and over again if we exit. */
862                 apr_sleep(10 * APR_USEC_PER_SEC);
863                 clean_child_exit(APEXIT_CHILDFATAL);
864             }
865             threads_created++;
866         }
867         if (workers_may_exit || threads_created == ap_threads_per_child) {
868             break;
869         }
870         /* wait for previous generation to clean up an entry */
871         apr_sleep(1 * APR_USEC_PER_SEC);
872     }
873     
874     /* What state should this child_main process be listed as in the 
875      * scoreboard...?
876      *  ap_update_child_status_from_indexes(my_child_num, i, SERVER_STARTING, 
877      *                                      (request_rec *) NULL);
878      * 
879      *  This state should be listed separately in the scoreboard, in some kind
880      *  of process_status, not mixed in with the worker threads' status.   
881      *  "life_status" is almost right, but it's in the worker's structure, and 
882      *  the name could be clearer.   gla
883      */
884     apr_thread_exit(thd, APR_SUCCESS);
885     return NULL;
886 }
887
888 static void child_main(int child_num_arg)
889 {
890     apr_thread_t **threads;
891     int i;
892     apr_status_t rv;
893     thread_starter *ts;
894     apr_threadattr_t *thread_attr;
895     apr_thread_t *start_thread_id;
896
897     ap_my_pid = getpid();
898     apr_pool_create(&pchild, pconf);
899
900     /*stuff to do before we switch id's, so we have permissions.*/
901     ap_reopen_scoreboard(pchild, NULL, 0);
902
903     rv = SAFE_ACCEPT(apr_proc_mutex_child_init(&accept_mutex, ap_lock_fname,
904                                                pchild));
905     if (rv != APR_SUCCESS) {
906         ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
907                      "Couldn't initialize cross-process lock in child");
908         clean_child_exit(APEXIT_CHILDFATAL);
909     }
910
911     if (unixd_setup_child()) {
912         clean_child_exit(APEXIT_CHILDFATAL);
913     }
914
915     ap_run_child_init(pchild, ap_server_conf);
916
917     /* done with init critical section */
918
919     /* Just use the standard apr_setup_signal_thread to block all signals
920      * from being received.  The child processes no longer use signals for
921      * any communication with the parent process.
922      */
923     rv = apr_setup_signal_thread();
924     if (rv != APR_SUCCESS) {
925         ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
926                      "Couldn't initialize signal thread");
927         clean_child_exit(APEXIT_CHILDFATAL);
928     }
929
930     if (ap_max_requests_per_child) {
931         requests_this_child = ap_max_requests_per_child;
932     }
933     else {
934         /* coding a value of zero means infinity */
935         requests_this_child = INT_MAX;
936     }
937     
938     /* Setup worker threads */
939
940     /* clear the storage; we may not create all our threads immediately, 
941      * and we want a 0 entry to indicate a thread which was not created
942      */
943     threads = (apr_thread_t **)calloc(1, 
944                                 sizeof(apr_thread_t *) * ap_threads_per_child);
945     if (threads == NULL) {
946         ap_log_error(APLOG_MARK, APLOG_ALERT, errno, ap_server_conf,
947                      "malloc: out of memory");
948         clean_child_exit(APEXIT_CHILDFATAL);
949     }
950     worker_thread_count = 0;
951     apr_thread_mutex_create(&worker_thread_count_mutex,
952                             APR_THREAD_MUTEX_DEFAULT, pchild);
953
954     ts = (thread_starter *)apr_palloc(pchild, sizeof(*ts));
955
956     apr_threadattr_create(&thread_attr, pchild);
957     /* 0 means PTHREAD_CREATE_JOINABLE */
958     apr_threadattr_detach_set(thread_attr, 0);
959
960     ts->threads = threads;
961     ts->child_num_arg = child_num_arg;
962     ts->threadattr = thread_attr;
963
964     
965     rv = apr_thread_create(&start_thread_id, thread_attr, start_threads,
966                            ts, pchild);
967     if (rv != APR_SUCCESS) {
968         ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
969                      "apr_thread_create: unable to create worker thread");
970         /* In case system resources are maxxed out, we don't want
971            Apache running away with the CPU trying to fork over and
972            over and over again if we exit. */
973         apr_sleep(10 * APR_USEC_PER_SEC);
974         clean_child_exit(APEXIT_CHILDFATAL);
975     }
976
977     /* If we are only running in one_process mode, we will want to
978      * still handle signals. */
979     if (one_process) {
980         /* Set up a signal handler for this thread. */
981         apr_signal_thread(check_signal);
982         signal_workers(); /* helps us terminate a little more quickly when
983                            * the dispatch of the signal thread
984                            * beats the Pipe of Death and the browsers
985                            */
986         /* A terminating signal was received. Now join each of the
987          * workers to clean them up.
988          *   If the worker already exited, then the join frees
989          *   their resources and returns.
990          *   If the worker hasn't exited, then this blocks until
991          *   they have (then cleans up).
992          */
993         apr_thread_join(&rv, start_thread_id);
994         for (i = 0; i < ap_threads_per_child; i++) {
995             if (threads[i]) { /* if we ever created this thread */
996                 apr_thread_join(&rv, threads[i]);
997             }
998         }
999     }
1000     else { /* !one_process */
1001         /* Watch for any messages from the parent over the POD */
1002         while (1) {
1003             rv = ap_mpm_pod_check(pod);
1004             if (rv == AP_GRACEFUL || rv == AP_RESTART) {
1005                 signal_workers();
1006                 break;
1007             }
1008         }
1009
1010         if (rv == AP_GRACEFUL) {
1011             /* A terminating signal was received. Now join each of the
1012              * workers to clean them up.
1013              *   If the worker already exited, then the join frees
1014              *   their resources and returns.
1015              *   If the worker hasn't exited, then this blocks until
1016              *   they have (then cleans up).
1017              */
1018             apr_thread_join(&rv, start_thread_id);
1019             for (i = 0; i < ap_threads_per_child; i++) {
1020                 if (threads[i]) { /* if we ever created this thread */
1021                     apr_thread_join(&rv, threads[i]);
1022                 }
1023             }
1024         }
1025     }
1026
1027     free(threads);
1028
1029     clean_child_exit(resource_shortage ? APEXIT_CHILDSICK : 0);
1030 }
1031
1032 static int make_child(server_rec *s, int slot) 
1033 {
1034     int pid;
1035
1036     if (slot + 1 > ap_max_daemons_limit) {
1037         ap_max_daemons_limit = slot + 1;
1038     }
1039
1040     if (one_process) {
1041         set_signals();
1042         ap_scoreboard_image->parent[slot].pid = getpid();
1043         child_main(slot);
1044     }
1045
1046     if ((pid = fork()) == -1) {
1047         ap_log_error(APLOG_MARK, APLOG_ERR, errno, s, 
1048                      "fork: Unable to fork new process");
1049
1050         /* fork didn't succeed. Fix the scoreboard or else
1051          * it will say SERVER_STARTING forever and ever
1052          */
1053         ap_update_child_status_from_indexes(slot, 0, SERVER_DEAD, NULL);
1054
1055         /* In case system resources are maxxed out, we don't want
1056            Apache running away with the CPU trying to fork over and
1057            over and over again. */
1058         apr_sleep(10 * APR_USEC_PER_SEC);
1059
1060         return -1;
1061     }
1062
1063     if (!pid) {
1064 #ifdef HAVE_BINDPROCESSOR
1065         /* By default, AIX binds to a single processor.  This bit unbinds
1066          * children which will then bind to another CPU.
1067          */
1068         int status = bindprocessor(BINDPROCESS, (int)getpid(),
1069                                PROCESSOR_CLASS_ANY);
1070         if (status != OK)
1071             ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, errno, 
1072                          ap_server_conf,
1073                          "processor unbind failed %d", status);
1074 #endif
1075         RAISE_SIGSTOP(MAKE_CHILD);
1076
1077         apr_signal(SIGTERM, just_die);
1078         child_main(slot);
1079
1080         clean_child_exit(0);
1081     }
1082     /* else */
1083     ap_scoreboard_image->parent[slot].quiescing = 0;
1084     ap_scoreboard_image->parent[slot].pid = pid;
1085     return 0;
1086 }
1087
1088 /* start up a bunch of children */
1089 static void startup_children(int number_to_start)
1090 {
1091     int i;
1092
1093     for (i = 0; number_to_start && i < ap_daemons_limit; ++i) {
1094         if (ap_scoreboard_image->parent[i].pid != 0) {
1095             continue;
1096         }
1097         if (make_child(ap_server_conf, i) < 0) {
1098             break;
1099         }
1100         --number_to_start;
1101     }
1102 }
1103
1104
1105 /*
1106  * idle_spawn_rate is the number of children that will be spawned on the
1107  * next maintenance cycle if there aren't enough idle servers.  It is
1108  * doubled up to MAX_SPAWN_RATE, and reset only when a cycle goes by
1109  * without the need to spawn.
1110  */
1111 static int idle_spawn_rate = 1;
1112 #ifndef MAX_SPAWN_RATE
1113 #define MAX_SPAWN_RATE        (32)
1114 #endif
1115 static int hold_off_on_exponential_spawning;
1116
1117 static void perform_idle_server_maintenance(void)
1118 {
1119     int i, j;
1120     int idle_thread_count;
1121     worker_score *ws;
1122     process_score *ps;
1123     int free_length;
1124     int totally_free_length = 0;
1125     int free_slots[MAX_SPAWN_RATE];
1126     int last_non_dead;
1127     int total_non_dead;
1128
1129     /* initialize the free_list */
1130     free_length = 0;
1131
1132     idle_thread_count = 0;
1133     last_non_dead = -1;
1134     total_non_dead = 0;
1135
1136     ap_sync_scoreboard_image();
1137     for (i = 0; i < ap_daemons_limit; ++i) {
1138         /* Initialization to satisfy the compiler. It doesn't know
1139          * that ap_threads_per_child is always > 0 */
1140         int status = SERVER_DEAD;
1141         int any_dying_threads = 0;
1142         int any_dead_threads = 0;
1143         int all_dead_threads = 1;
1144
1145         if (i >= ap_max_daemons_limit && totally_free_length == idle_spawn_rate)
1146             break;
1147         ps = &ap_scoreboard_image->parent[i];
1148         for (j = 0; j < ap_threads_per_child; j++) {
1149             ws = &ap_scoreboard_image->servers[i][j];
1150             status = ws->status;
1151
1152             /* XXX any_dying_threads is probably no longer needed    GLA */
1153             any_dying_threads = any_dying_threads || 
1154                                 (status == SERVER_GRACEFUL);
1155             any_dead_threads = any_dead_threads || (status == SERVER_DEAD);
1156             all_dead_threads = all_dead_threads &&
1157                                    (status == SERVER_DEAD ||
1158                                     status == SERVER_GRACEFUL);
1159
1160             /* We consider a starting server as idle because we started it
1161              * at least a cycle ago, and if it still hasn't finished starting
1162              * then we're just going to swamp things worse by forking more.
1163              * So we hopefully won't need to fork more if we count it.
1164              * This depends on the ordering of SERVER_READY and SERVER_STARTING.
1165              */
1166             if (status <= SERVER_READY && status != SERVER_DEAD &&
1167                     !ps->quiescing &&
1168                     ps->generation == ap_my_generation &&
1169                  /* XXX the following shouldn't be necessary if we clean up 
1170                   *     properly after seg faults, but we're not yet    GLA 
1171                   */     
1172                     ps->pid != 0) {
1173                 ++idle_thread_count;
1174             }
1175         }
1176         if (any_dead_threads && totally_free_length < idle_spawn_rate 
1177                 && (!ps->pid               /* no process in the slot */
1178                     || ps->quiescing)) {   /* or at least one is going away */
1179             if (all_dead_threads) {
1180                 /* great! we prefer these, because the new process can
1181                  * start more threads sooner.  So prioritize this slot 
1182                  * by putting it ahead of any slots with active threads.
1183                  *
1184                  * first, make room by moving a slot that's potentially still
1185                  * in use to the end of the array
1186                  */
1187                 free_slots[free_length] = free_slots[totally_free_length];
1188                 free_slots[totally_free_length++] = i;
1189             }
1190             else {
1191                 /* slot is still in use - back of the bus
1192                  */
1193             free_slots[free_length] = i;
1194             }
1195             ++free_length;
1196         }
1197         /* XXX if (!ps->quiescing)     is probably more reliable  GLA */
1198         if (!any_dying_threads) {
1199             last_non_dead = i;
1200             ++total_non_dead;
1201         }
1202     }
1203     ap_max_daemons_limit = last_non_dead + 1;
1204
1205     if (idle_thread_count > max_spare_threads) {
1206         /* Kill off one child */
1207         ap_mpm_pod_signal(pod, TRUE);
1208         idle_spawn_rate = 1;
1209     }
1210     else if (idle_thread_count < min_spare_threads) {
1211         /* terminate the free list */
1212         if (free_length == 0) {
1213             /* only report this condition once */
1214             static int reported = 0;
1215             
1216             if (!reported) {
1217                 ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, 
1218                              ap_server_conf,
1219                              "server reached MaxClients setting, consider"
1220                              " raising the MaxClients setting");
1221                 reported = 1;
1222             }
1223             idle_spawn_rate = 1;
1224         }
1225         else {
1226             if (free_length > idle_spawn_rate) {
1227                 free_length = idle_spawn_rate;
1228             }
1229             if (idle_spawn_rate >= 8) {
1230                 ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0, 
1231                              ap_server_conf,
1232                              "server seems busy, (you may need "
1233                              "to increase StartServers, ThreadsPerChild "
1234                              "or Min/MaxSpareThreads), "
1235                              "spawning %d children, there are around %d idle "
1236                              "threads, and %d total children", free_length,
1237                              idle_thread_count, total_non_dead);
1238             }
1239             for (i = 0; i < free_length; ++i) {
1240                 make_child(ap_server_conf, free_slots[i]);
1241             }
1242             /* the next time around we want to spawn twice as many if this
1243              * wasn't good enough, but not if we've just done a graceful
1244              */
1245             if (hold_off_on_exponential_spawning) {
1246                 --hold_off_on_exponential_spawning;
1247             }
1248             else if (idle_spawn_rate < MAX_SPAWN_RATE) {
1249                 idle_spawn_rate *= 2;
1250             }
1251         }
1252     }
1253     else {
1254       idle_spawn_rate = 1;
1255     }
1256 }
1257
1258 static void server_main_loop(int remaining_children_to_start)
1259 {
1260     int child_slot;
1261     apr_exit_why_e exitwhy;
1262     int status, processed_status;
1263     apr_proc_t pid;
1264     int i;
1265
1266     while (!restart_pending && !shutdown_pending) {
1267         ap_wait_or_timeout(&exitwhy, &status, &pid, pconf);
1268         
1269         if (pid.pid != -1) {
1270             processed_status = ap_process_child_status(&pid, exitwhy, status);
1271             if (processed_status == APEXIT_CHILDFATAL) {
1272                 shutdown_pending = 1;
1273                 child_fatal = 1;
1274                 return;
1275             }
1276             /* non-fatal death... note that it's gone in the scoreboard. */
1277             child_slot = find_child_by_pid(&pid);
1278             if (child_slot >= 0) {
1279                 for (i = 0; i < ap_threads_per_child; i++)
1280                     ap_update_child_status_from_indexes(child_slot, i, SERVER_DEAD, 
1281                                                         (request_rec *) NULL);
1282                 
1283                 ap_scoreboard_image->parent[child_slot].pid = 0;
1284                 ap_scoreboard_image->parent[child_slot].quiescing = 0;
1285                 if (processed_status == APEXIT_CHILDSICK) {
1286                     /* resource shortage, minimize the fork rate */
1287                     idle_spawn_rate = 1;
1288                 }
1289                 else if (remaining_children_to_start
1290                     && child_slot < ap_daemons_limit) {
1291                     /* we're still doing a 1-for-1 replacement of dead
1292                      * children with new children
1293                      */
1294                     make_child(ap_server_conf, child_slot);
1295                     --remaining_children_to_start;
1296                 }
1297 #if APR_HAS_OTHER_CHILD
1298             }
1299             else if (apr_proc_other_child_read(&pid, status) == 0) {
1300                 /* handled */
1301 #endif
1302             }
1303             else if (is_graceful) {
1304                 /* Great, we've probably just lost a slot in the
1305                  * scoreboard.  Somehow we don't know about this child.
1306                  */
1307                 ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0,
1308                              ap_server_conf,
1309                              "long lost child came home! (pid %ld)",
1310                              (long)pid.pid);
1311             }
1312             /* Don't perform idle maintenance when a child dies,
1313              * only do it when there's a timeout.  Remember only a
1314              * finite number of children can die, and it's pretty
1315              * pathological for a lot to die suddenly.
1316              */
1317             continue;
1318         }
1319         else if (remaining_children_to_start) {
1320             /* we hit a 1 second timeout in which none of the previous
1321              * generation of children needed to be reaped... so assume
1322              * they're all done, and pick up the slack if any is left.
1323              */
1324             startup_children(remaining_children_to_start);
1325             remaining_children_to_start = 0;
1326             /* In any event we really shouldn't do the code below because
1327              * few of the servers we just started are in the IDLE state
1328              * yet, so we'd mistakenly create an extra server.
1329              */
1330             continue;
1331         }
1332
1333         perform_idle_server_maintenance();
1334     }
1335 }
1336
1337 int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
1338 {
1339     int remaining_children_to_start;
1340     apr_status_t rv;
1341
1342     ap_log_pid(pconf, ap_pid_fname);
1343
1344     first_server_limit = server_limit;
1345     first_thread_limit = thread_limit;
1346     if (changed_limit_at_restart) {
1347         ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_NOERRNO, 0, s,
1348                      "WARNING: Attempt to change ServerLimit or ThreadLimit "
1349                      "ignored during restart");
1350         changed_limit_at_restart = 0;
1351     }
1352     
1353     /* Initialize cross-process accept lock */
1354     ap_lock_fname = apr_psprintf(_pconf, "%s.%" APR_OS_PROC_T_FMT,
1355                                  ap_server_root_relative(_pconf, ap_lock_fname),
1356                                  ap_my_pid);
1357
1358     rv = apr_proc_mutex_create(&accept_mutex, ap_lock_fname, 
1359                                ap_accept_lock_mech, _pconf);
1360     if (rv != APR_SUCCESS) {
1361         ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s,
1362                      "Couldn't create accept lock");
1363         return 1;
1364     }
1365
1366 #if APR_USE_SYSVSEM_SERIALIZE
1367     if (ap_accept_lock_mech == APR_LOCK_DEFAULT || 
1368         ap_accept_lock_mech == APR_LOCK_SYSVSEM) {
1369 #else
1370     if (ap_accept_lock_mech == APR_LOCK_SYSVSEM) {
1371 #endif
1372         rv = unixd_set_proc_mutex_perms(accept_mutex);
1373         if (rv != APR_SUCCESS) {
1374             ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s,
1375                          "Couldn't set permissions on cross-process lock");
1376             return 1;
1377         }
1378     }
1379
1380     if (!is_graceful) {
1381         if (ap_run_pre_mpm(pconf, SB_SHARED) != OK) {
1382             return 1;
1383         }
1384     }
1385
1386     set_signals();
1387     /* Don't thrash... */
1388     if (max_spare_threads < min_spare_threads + ap_threads_per_child)
1389         max_spare_threads = min_spare_threads + ap_threads_per_child;
1390
1391     /* If we're doing a graceful_restart then we're going to see a lot
1392      * of children exiting immediately when we get into the main loop
1393      * below (because we just sent them AP_SIG_GRACEFUL).  This happens pretty
1394      * rapidly... and for each one that exits we'll start a new one until
1395      * we reach at least daemons_min_free.  But we may be permitted to
1396      * start more than that, so we'll just keep track of how many we're
1397      * supposed to start up without the 1 second penalty between each fork.
1398      */
1399     remaining_children_to_start = ap_daemons_to_start;
1400     if (remaining_children_to_start > ap_daemons_limit) {
1401         remaining_children_to_start = ap_daemons_limit;
1402     }
1403     if (!is_graceful) {
1404         startup_children(remaining_children_to_start);
1405         remaining_children_to_start = 0;
1406     }
1407     else {
1408         /* give the system some time to recover before kicking into
1409             * exponential mode */
1410         hold_off_on_exponential_spawning = 10;
1411     }
1412
1413     ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, ap_server_conf,
1414                 "%s configured -- resuming normal operations",
1415                 ap_get_server_version());
1416     ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0, ap_server_conf,
1417                 "Server built: %s", ap_get_server_built());
1418     restart_pending = shutdown_pending = 0;
1419
1420     server_main_loop(remaining_children_to_start);
1421
1422     if (shutdown_pending) {
1423         /* Time to gracefully shut down:
1424          * Kill child processes, tell them to call child_exit, etc...
1425          */
1426         ap_mpm_pod_killpg(pod, ap_daemons_limit, TRUE);
1427         ap_reclaim_child_processes(1);                /* Start with SIGTERM */
1428
1429         if (!child_fatal) {
1430             /* cleanup pid file on normal shutdown */
1431             const char *pidfile = NULL;
1432             pidfile = ap_server_root_relative (pconf, ap_pid_fname);
1433             if ( pidfile != NULL && unlink(pidfile) == 0)
1434                 ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0,
1435                              ap_server_conf,
1436                              "removed PID file %s (pid=%ld)",
1437                              pidfile, (long)getpid());
1438     
1439             ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0,
1440                          ap_server_conf, "caught SIGTERM, shutting down");
1441         }
1442         return 1;
1443     }
1444
1445     /* we've been told to restart */
1446     apr_signal(SIGHUP, SIG_IGN);
1447
1448     if (one_process) {
1449         /* not worth thinking about */
1450         return 1;
1451     }
1452
1453     /* advance to the next generation */
1454     /* XXX: we really need to make sure this new generation number isn't in
1455      * use by any of the children.
1456      */
1457     ++ap_my_generation;
1458     ap_scoreboard_image->global->running_generation = ap_my_generation;
1459     update_scoreboard_global();
1460     
1461     if (is_graceful) {
1462         ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, ap_server_conf,
1463                      AP_SIG_GRACEFUL_STRING " received.  Doing graceful restart");
1464         /* wake up the children...time to die.  But we'll have more soon */
1465         ap_mpm_pod_killpg(pod, ap_daemons_limit, TRUE);
1466     
1467
1468         /* This is mostly for debugging... so that we know what is still
1469          * gracefully dealing with existing request.
1470          */
1471         
1472     }
1473     else {
1474         /* Kill 'em all.  Since the child acts the same on the parents SIGTERM 
1475          * and a SIGHUP, we may as well use the same signal, because some user
1476          * pthreads are stealing signals from us left and right.
1477          */
1478         ap_mpm_pod_killpg(pod, ap_daemons_limit, FALSE);
1479
1480         ap_reclaim_child_processes(1);                /* Start with SIGTERM */
1481         ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, ap_server_conf,
1482                     "SIGHUP received.  Attempting to restart");
1483     }
1484
1485     return 0;
1486 }
1487
1488 /* This really should be a post_config hook, but the error log is already
1489  * redirected by that point, so we need to do this in the open_logs phase.
1490  */
1491 static int worker_open_logs(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
1492 {
1493     apr_status_t rv;
1494
1495     pconf = p;
1496     ap_server_conf = s;
1497
1498     if ((num_listensocks = ap_setup_listeners(ap_server_conf)) < 1) {
1499         ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ALERT|APLOG_STARTUP, 0,
1500                      NULL, "no listening sockets available, shutting down");
1501         return DONE;
1502     }
1503
1504     if (!one_process) {
1505         if ((rv = ap_mpm_pod_open(pconf, &pod))) {
1506             ap_log_error(APLOG_MARK, APLOG_CRIT|APLOG_STARTUP, rv, NULL,
1507                     "Could not open pipe-of-death.");
1508             return DONE;
1509         }
1510     }
1511     return OK;
1512 }
1513
1514 static int worker_pre_config(apr_pool_t *pconf, apr_pool_t *plog, 
1515                              apr_pool_t *ptemp)
1516 {
1517     static int restart_num = 0;
1518     int no_detach, debug;
1519     ap_directive_t *pdir;
1520     ap_directive_t *max_clients = NULL;
1521     apr_status_t rv;
1522
1523     /* make sure that "ThreadsPerChild" gets set before "MaxClients" */
1524     for (pdir = ap_conftree; pdir != NULL; pdir = pdir->next) {
1525         if (strncasecmp(pdir->directive, "ThreadsPerChild", 15) == 0) {
1526             if (!max_clients) {
1527                 break; /* we're in the clear, got ThreadsPerChild first */
1528             }
1529             else {
1530                 /* now to swap the data */
1531                 ap_directive_t temp;
1532
1533                 temp.directive = pdir->directive;
1534                 temp.args = pdir->args;
1535                 /* Make sure you don't change 'next', or you may get loops! */
1536                 /* XXX: first_child, parent, and data can never be set
1537                  * for these directives, right? -aaron */
1538                 temp.filename = pdir->filename;
1539                 temp.line_num = pdir->line_num;
1540
1541                 pdir->directive = max_clients->directive;
1542                 pdir->args = max_clients->args;
1543                 pdir->filename = max_clients->filename;
1544                 pdir->line_num = max_clients->line_num;
1545                 
1546                 max_clients->directive = temp.directive;
1547                 max_clients->args = temp.args;
1548                 max_clients->filename = temp.filename;
1549                 max_clients->line_num = temp.line_num;
1550                 break;
1551             }
1552         }
1553         else if (!max_clients
1554                  && strncasecmp(pdir->directive, "MaxClients", 10) == 0) {
1555             max_clients = pdir;
1556         }
1557     }
1558
1559     debug = ap_exists_config_define("DEBUG");
1560
1561     if (debug) {
1562         no_detach = one_process = 1;
1563     }
1564     else {
1565         one_process = ap_exists_config_define("ONE_PROCESS");
1566         no_detach = ap_exists_config_define("NO_DETACH");
1567     }
1568
1569     /* sigh, want this only the second time around */
1570     if (restart_num++ == 1) {
1571         is_graceful = 0;
1572
1573         if (!one_process) {
1574             rv = apr_proc_detach(no_detach ? APR_PROC_DETACH_FOREGROUND
1575                                            : APR_PROC_DETACH_DAEMONIZE);
1576             if (rv != APR_SUCCESS) {
1577                 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL,
1578                              "apr_proc_detach failed");
1579                 return HTTP_INTERNAL_SERVER_ERROR;
1580             }
1581         }
1582         parent_pid = ap_my_pid = getpid();
1583     }
1584
1585     unixd_pre_config(ptemp);
1586     ap_listen_pre_config();
1587     ap_daemons_to_start = DEFAULT_START_DAEMON;
1588     min_spare_threads = DEFAULT_MIN_FREE_DAEMON * DEFAULT_THREADS_PER_CHILD;
1589     max_spare_threads = DEFAULT_MAX_FREE_DAEMON * DEFAULT_THREADS_PER_CHILD;
1590     ap_daemons_limit = server_limit;
1591     ap_threads_per_child = DEFAULT_THREADS_PER_CHILD;
1592     ap_pid_fname = DEFAULT_PIDLOG;
1593     ap_lock_fname = DEFAULT_LOCKFILE;
1594     ap_max_requests_per_child = DEFAULT_MAX_REQUESTS_PER_CHILD;
1595     ap_extended_status = 0;
1596
1597     apr_cpystrn(ap_coredump_dir, ap_server_root, sizeof(ap_coredump_dir));
1598
1599     return OK;
1600 }
1601
1602 static void worker_hooks(apr_pool_t *p)
1603 {
1604     /* The worker open_logs phase must run before the core's, or stderr
1605      * will be redirected to a file, and the messages won't print to the
1606      * console.
1607      */
1608     static const char *const aszSucc[] = {"core.c", NULL};
1609     one_process = 0;
1610
1611     ap_hook_open_logs(worker_open_logs, NULL, aszSucc, APR_HOOK_MIDDLE);
1612     ap_hook_pre_config(worker_pre_config, NULL, NULL, APR_HOOK_MIDDLE);
1613 }
1614
1615 static const char *set_daemons_to_start(cmd_parms *cmd, void *dummy,
1616                                         const char *arg) 
1617 {
1618     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
1619     if (err != NULL) {
1620         return err;
1621     }
1622
1623     ap_daemons_to_start = atoi(arg);
1624     return NULL;
1625 }
1626
1627 static const char *set_min_spare_threads(cmd_parms *cmd, void *dummy,
1628                                          const char *arg)
1629 {
1630     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
1631     if (err != NULL) {
1632         return err;
1633     }
1634
1635     min_spare_threads = atoi(arg);
1636     if (min_spare_threads <= 0) {
1637        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
1638                     "WARNING: detected MinSpareThreads set to non-positive.");
1639        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
1640                     "Resetting to 1 to avoid almost certain Apache failure.");
1641        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
1642                     "Please read the documentation.");
1643        min_spare_threads = 1;
1644     }
1645        
1646     return NULL;
1647 }
1648
1649 static const char *set_max_spare_threads(cmd_parms *cmd, void *dummy,
1650                                          const char *arg)
1651 {
1652     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
1653     if (err != NULL) {
1654         return err;
1655     }
1656
1657     max_spare_threads = atoi(arg);
1658     return NULL;
1659 }
1660
1661 static const char *set_max_clients (cmd_parms *cmd, void *dummy,
1662                                      const char *arg) 
1663 {
1664     int max_clients;
1665     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
1666     if (err != NULL) {
1667         return err;
1668     }
1669
1670     /* It is ok to use ap_threads_per_child here because we are
1671      * sure that it gets set before MaxClients in the pre_config stage. */
1672     max_clients = atoi(arg);
1673     if (max_clients < ap_threads_per_child) {
1674        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
1675                     "WARNING: MaxClients (%d) must be at least as large",
1676                     max_clients);
1677        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
1678                     " large as ThreadsPerChild (%d). Automatically",
1679                     ap_threads_per_child);
1680        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
1681                     " increasing MaxClients to %d.",
1682                     ap_threads_per_child);
1683        max_clients = ap_threads_per_child;
1684     }
1685     ap_daemons_limit = max_clients / ap_threads_per_child;
1686     if ((max_clients > 0) && (max_clients % ap_threads_per_child)) {
1687        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
1688                     "WARNING: MaxClients (%d) is not an integer multiple",
1689                     max_clients);
1690        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
1691                     " of ThreadsPerChild (%d), lowering MaxClients to %d",
1692                     ap_threads_per_child,
1693                     ap_daemons_limit * ap_threads_per_child);
1694        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
1695                     " for a maximum of %d child processes,",
1696                     ap_daemons_limit);
1697        max_clients = ap_daemons_limit * ap_threads_per_child; 
1698     }
1699     if (ap_daemons_limit > server_limit) {
1700        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
1701                     "WARNING: MaxClients of %d would require %d servers,",
1702                     max_clients, ap_daemons_limit);
1703        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
1704                     " and would exceed the ServerLimit value of %d.",
1705                     server_limit);
1706        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
1707                     " Automatically lowering MaxClients to %d.  To increase,",
1708                     server_limit);
1709        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
1710                     " please see the ServerLimit directive.");
1711        ap_daemons_limit = server_limit;
1712     } 
1713     else if (ap_daemons_limit < 1) {
1714         ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
1715                      "WARNING: Require MaxClients > 0, setting to 1");
1716         ap_daemons_limit = 1;
1717     }
1718     return NULL;
1719 }
1720
1721 static const char *set_threads_per_child (cmd_parms *cmd, void *dummy,
1722                                           const char *arg) 
1723 {
1724     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
1725     if (err != NULL) {
1726         return err;
1727     }
1728
1729     ap_threads_per_child = atoi(arg);
1730     if (ap_threads_per_child > thread_limit) {
1731         ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
1732                      "WARNING: ThreadsPerChild of %d exceeds ThreadLimit "
1733                      "value of %d", ap_threads_per_child,
1734                      thread_limit);
1735         ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
1736                      "threads, lowering ThreadsPerChild to %d. To increase, please"
1737                      " see the", thread_limit);
1738         ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
1739                      " ThreadLimit directive.");
1740         ap_threads_per_child = thread_limit;
1741     }
1742     else if (ap_threads_per_child < 1) {
1743         ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
1744                      "WARNING: Require ThreadsPerChild > 0, setting to 1");
1745         ap_threads_per_child = 1;
1746     }
1747     return NULL;
1748 }
1749
1750 static const char *set_server_limit (cmd_parms *cmd, void *dummy, const char *arg) 
1751 {
1752     int tmp_server_limit;
1753     
1754     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
1755     if (err != NULL) {
1756         return err;
1757     }
1758
1759     tmp_server_limit = atoi(arg);
1760     /* you cannot change ServerLimit across a restart; ignore
1761      * any such attempts
1762      */
1763     if (first_server_limit &&
1764         tmp_server_limit != server_limit) {
1765         /* how do we log a message?  the error log is a bit bucket at this
1766          * point; we'll just have to set a flag so that ap_mpm_run()
1767          * logs a warning later
1768          */
1769         changed_limit_at_restart = 1;
1770         return NULL;
1771     }
1772     server_limit = tmp_server_limit;
1773     
1774     if (server_limit > MAX_SERVER_LIMIT) {
1775        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
1776                     "WARNING: ServerLimit of %d exceeds compile time limit "
1777                     "of %d servers,", server_limit, MAX_SERVER_LIMIT);
1778        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
1779                     " lowering ServerLimit to %d.", MAX_SERVER_LIMIT);
1780        server_limit = MAX_SERVER_LIMIT;
1781     } 
1782     else if (server_limit < 1) {
1783         ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
1784                      "WARNING: Require ServerLimit > 0, setting to 1");
1785         server_limit = 1;
1786     }
1787     return NULL;
1788 }
1789
1790 static const char *set_thread_limit (cmd_parms *cmd, void *dummy, const char *arg) 
1791 {
1792     int tmp_thread_limit;
1793     
1794     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
1795     if (err != NULL) {
1796         return err;
1797     }
1798
1799     tmp_thread_limit = atoi(arg);
1800     /* you cannot change ThreadLimit across a restart; ignore
1801      * any such attempts
1802      */
1803     if (first_thread_limit &&
1804         tmp_thread_limit != thread_limit) {
1805         /* how do we log a message?  the error log is a bit bucket at this
1806          * point; we'll just have to set a flag so that ap_mpm_run()
1807          * logs a warning later
1808          */
1809         changed_limit_at_restart = 1;
1810         return NULL;
1811     }
1812     thread_limit = tmp_thread_limit;
1813     
1814     if (thread_limit > MAX_THREAD_LIMIT) {
1815        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
1816                     "WARNING: ThreadLimit of %d exceeds compile time limit "
1817                     "of %d servers,", thread_limit, MAX_THREAD_LIMIT);
1818        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
1819                     " lowering ThreadLimit to %d.", MAX_THREAD_LIMIT);
1820        thread_limit = MAX_THREAD_LIMIT;
1821     } 
1822     else if (thread_limit < 1) {
1823         ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
1824                      "WARNING: Require ThreadLimit > 0, setting to 1");
1825         thread_limit = 1;
1826     }
1827     return NULL;
1828 }
1829
1830 static const command_rec worker_cmds[] = {
1831 UNIX_DAEMON_COMMANDS,
1832 LISTEN_COMMANDS,
1833 AP_INIT_TAKE1("StartServers", set_daemons_to_start, NULL, RSRC_CONF,
1834   "Number of child processes launched at server startup"),
1835 AP_INIT_TAKE1("MinSpareThreads", set_min_spare_threads, NULL, RSRC_CONF,
1836   "Minimum number of idle children, to handle request spikes"),
1837 AP_INIT_TAKE1("MaxSpareThreads", set_max_spare_threads, NULL, RSRC_CONF,
1838   "Maximum number of idle children"),
1839 AP_INIT_TAKE1("MaxClients", set_max_clients, NULL, RSRC_CONF,
1840   "Maximum number of children alive at the same time"),
1841 AP_INIT_TAKE1("ThreadsPerChild", set_threads_per_child, NULL, RSRC_CONF,
1842   "Number of threads each child creates"),
1843 AP_INIT_TAKE1("ServerLimit", set_server_limit, NULL, RSRC_CONF,
1844   "Maximum value of MaxClients for this run of Apache"),
1845 AP_INIT_TAKE1("ThreadLimit", set_thread_limit, NULL, RSRC_CONF,
1846   "Maximum worker threads in a server for this run of Apache"),
1847 { NULL }
1848 };
1849
1850 module AP_MODULE_DECLARE_DATA mpm_worker_module = {
1851     MPM20_MODULE_STUFF,
1852     NULL,                       /* hook to run before apache parses args */
1853     NULL,                       /* create per-directory config structure */
1854     NULL,                       /* merge per-directory config structures */
1855     NULL,                       /* create per-server config structure */
1856     NULL,                       /* merge per-server config structures */
1857     worker_cmds,                /* command apr_table_t */
1858     worker_hooks                /* register_hooks */
1859 };
1860