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 #include "apr.h"
18 #include "apr_portable.h"
19 #include "apr_strings.h"
20 #include "apr_thread_proc.h"
21 #include "apr_signal.h"
22 
23 #define APR_WANT_STDIO
24 #define APR_WANT_STRFUNC
25 #include "apr_want.h"
26 
27 #if APR_HAVE_UNISTD_H
28 #include <unistd.h>
29 #endif
30 #if APR_HAVE_SYS_TYPES_H
31 #include <sys/types.h>
32 #endif
33 
34 #include "ap_config.h"
35 #include "httpd.h"
36 #include "mpm_default.h"
37 #include "http_main.h"
38 #include "http_log.h"
39 #include "http_config.h"
40 #include "http_core.h"          /* for get_remote_host */
41 #include "http_connection.h"
42 #include "scoreboard.h"
43 #include "ap_mpm.h"
44 #include "util_mutex.h"
45 #include "unixd.h"
46 #include "mpm_common.h"
47 #include "ap_listen.h"
48 #include "ap_mmn.h"
49 #include "apr_poll.h"
50 
51 #include <stdlib.h>
52 
53 #ifdef HAVE_TIME_H
54 #include <time.h>
55 #endif
56 #ifdef HAVE_SYS_PROCESSOR_H
57 #include <sys/processor.h> /* for bindprocessor() */
58 #endif
59 
60 #include <signal.h>
61 #include <sys/times.h>
62 
63 /* Limit on the total --- clients will be locked out if more servers than
64  * this are needed.  It is intended solely to keep the server from crashing
65  * when things get out of hand.
66  *
67  * We keep a hard maximum number of servers, for two reasons --- first off,
68  * in case something goes seriously wrong, we want to stop the fork bomb
69  * short of actually crashing the machine we're running on by filling some
70  * kernel table.  Secondly, it keeps the size of the scoreboard file small
71  * enough that we can read the whole thing without worrying too much about
72  * the overhead.
73  */
74 #ifndef DEFAULT_SERVER_LIMIT
75 #define DEFAULT_SERVER_LIMIT 256
76 #endif
77 
78 /* Admin can't tune ServerLimit beyond MAX_SERVER_LIMIT.  We want
79  * some sort of compile-time limit to help catch typos.
80  */
81 #ifndef MAX_SERVER_LIMIT
82 #define MAX_SERVER_LIMIT 200000
83 #endif
84 
85 #ifndef HARD_THREAD_LIMIT
86 #define HARD_THREAD_LIMIT 1
87 #endif
88 
89 /* config globals */
90 
91 static int ap_daemons_to_start=0;
92 static int ap_daemons_min_free=0;
93 static int ap_daemons_max_free=0;
94 static int ap_daemons_limit=0;      /* MaxRequestWorkers */
95 static int server_limit = 0;
96 
97 /* data retained by prefork across load/unload of the module
98  * allocated on first call to pre-config hook; located on
99  * subsequent calls to pre-config hook
100  */
101 typedef struct prefork_retained_data {
102     ap_unixd_mpm_retained_data *mpm;
103 
104     int first_server_limit;
105     int maxclients_reported;
106     /*
107      * The max child slot ever assigned, preserved across restarts.  Necessary
108      * to deal with MaxRequestWorkers changes across AP_SIG_GRACEFUL restarts.  We
109      * use this value to optimize routines that have to scan the entire scoreboard.
110      */
111     int max_daemons_limit;
112     /*
113      * idle_spawn_rate is the number of children that will be spawned on the
114      * next maintenance cycle if there aren't enough idle servers.  It is
115      * doubled up to MAX_SPAWN_RATE, and reset only when a cycle goes by
116      * without the need to spawn.
117      */
118     int idle_spawn_rate;
119 #ifndef MAX_SPAWN_RATE
120 #define MAX_SPAWN_RATE  (32)
121 #endif
122     int hold_off_on_exponential_spawning;
123 } prefork_retained_data;
124 static prefork_retained_data *retained;
125 
126 typedef struct prefork_child_bucket {
127     ap_pod_t *pod;
128     ap_listen_rec *listeners;
129     apr_proc_mutex_t *mutex;
130 } prefork_child_bucket;
131 static prefork_child_bucket *all_buckets, /* All listeners buckets */
132                             *my_bucket;   /* Current child bucket */
133 
134 #define MPM_CHILD_PID(i) (ap_scoreboard_image->parent[i].pid)
135 
136 /* one_process --- debugging mode variable; can be set from the command line
137  * with the -X flag.  If set, this gets you the child_main loop running
138  * in the process which originally started up (no detach, no make_child),
139  * which is a pretty nice debugging environment.  (You'll get a SIGHUP
140  * early in standalone_main; just continue through.  This is the server
141  * trying to kill off any child processes which it might have lying
142  * around --- Apache doesn't keep track of their pids, it just sends
143  * SIGHUP to the process group, ignoring it in the root process.
144  * Continue through and you'll be fine.).
145  */
146 
147 static int one_process = 0;
148 
149 static apr_pool_t *pconf;               /* Pool for config stuff */
150 static apr_pool_t *pchild;              /* Pool for httpd child stuff */
151 
152 static pid_t ap_my_pid; /* it seems silly to call getpid all the time */
153 static pid_t parent_pid;
154 static int my_child_num;
155 
156 #ifdef GPROF
157 /*
158  * change directory for gprof to plop the gmon.out file
159  * configure in httpd.conf:
160  * GprofDir $RuntimeDir/   -> $ServerRoot/$RuntimeDir/gmon.out
161  * GprofDir $RuntimeDir/%  -> $ServerRoot/$RuntimeDir/gprof.$pid/gmon.out
162  */
chdir_for_gprof(void)163 static void chdir_for_gprof(void)
164 {
165     core_server_config *sconf =
166         ap_get_core_module_config(ap_server_conf->module_config);
167     char *dir = sconf->gprof_dir;
168     const char *use_dir;
169 
170     if(dir) {
171         apr_status_t res;
172         char *buf = NULL ;
173         int len = strlen(sconf->gprof_dir) - 1;
174         if(*(dir + len) == '%') {
175             dir[len] = '\0';
176             buf = ap_append_pid(pconf, dir, "gprof.");
177         }
178         use_dir = ap_server_root_relative(pconf, buf ? buf : dir);
179         res = apr_dir_make(use_dir,
180                            APR_UREAD | APR_UWRITE | APR_UEXECUTE |
181                            APR_GREAD | APR_GEXECUTE |
182                            APR_WREAD | APR_WEXECUTE, pconf);
183         if(res != APR_SUCCESS && !APR_STATUS_IS_EEXIST(res)) {
184             ap_log_error(APLOG_MARK, APLOG_ERR, res, ap_server_conf, APLOGNO(00142)
185                          "gprof: error creating directory %s", dir);
186         }
187     }
188     else {
189         use_dir = ap_runtime_dir_relative(pconf, "");
190     }
191 
192     chdir(use_dir);
193 }
194 #else
195 #define chdir_for_gprof()
196 #endif
197 
prefork_note_child_killed(int childnum,pid_t pid,ap_generation_t gen)198 static void prefork_note_child_killed(int childnum, pid_t pid,
199                                       ap_generation_t gen)
200 {
201     AP_DEBUG_ASSERT(childnum != -1); /* no scoreboard squatting with this MPM */
202     ap_run_child_status(ap_server_conf,
203                         ap_scoreboard_image->parent[childnum].pid,
204                         ap_scoreboard_image->parent[childnum].generation,
205                         childnum, MPM_CHILD_EXITED);
206     ap_scoreboard_image->parent[childnum].pid = 0;
207 }
208 
prefork_note_child_started(int slot,pid_t pid)209 static void prefork_note_child_started(int slot, pid_t pid)
210 {
211     ap_generation_t gen = retained->mpm->my_generation;
212     ap_scoreboard_image->parent[slot].pid = pid;
213     ap_scoreboard_image->parent[slot].generation = gen;
214     ap_run_child_status(ap_server_conf, pid, gen, slot, MPM_CHILD_STARTED);
215 }
216 
217 /* a clean exit from a child with proper cleanup */
218 static void clean_child_exit(int code) __attribute__ ((noreturn));
clean_child_exit(int code)219 static void clean_child_exit(int code)
220 {
221     retained->mpm->mpm_state = AP_MPMQ_STOPPING;
222 
223     apr_signal(SIGHUP, SIG_IGN);
224     apr_signal(SIGTERM, SIG_IGN);
225 
226     if (code == 0) {
227         ap_run_child_stopping(pchild, 0);
228     }
229 
230     if (pchild) {
231         apr_pool_destroy(pchild);
232     }
233 
234     if (one_process) {
235         prefork_note_child_killed(/* slot */ 0, 0, 0);
236     }
237 
238     ap_mpm_pod_close(my_bucket->pod);
239     chdir_for_gprof();
240     exit(code);
241 }
242 
accept_mutex_on(void)243 static apr_status_t accept_mutex_on(void)
244 {
245     apr_status_t rv = apr_proc_mutex_lock(my_bucket->mutex);
246     if (rv != APR_SUCCESS) {
247         const char *msg = "couldn't grab the accept mutex";
248 
249         if (retained->mpm->my_generation !=
250             ap_scoreboard_image->global->running_generation) {
251             ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, ap_server_conf, APLOGNO(00143) "%s", msg);
252             clean_child_exit(0);
253         }
254         else {
255             ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf, APLOGNO(00144) "%s", msg);
256             exit(APEXIT_CHILDFATAL);
257         }
258     }
259     return APR_SUCCESS;
260 }
261 
accept_mutex_off(void)262 static apr_status_t accept_mutex_off(void)
263 {
264     apr_status_t rv = apr_proc_mutex_unlock(my_bucket->mutex);
265     if (rv != APR_SUCCESS) {
266         const char *msg = "couldn't release the accept mutex";
267 
268         if (retained->mpm->my_generation !=
269             ap_scoreboard_image->global->running_generation) {
270             ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, ap_server_conf, APLOGNO(00145) "%s", msg);
271             /* don't exit here... we have a connection to
272              * process, after which point we'll see that the
273              * generation changed and we'll exit cleanly
274              */
275         }
276         else {
277             ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf, APLOGNO(00146) "%s", msg);
278             exit(APEXIT_CHILDFATAL);
279         }
280     }
281     return APR_SUCCESS;
282 }
283 
284 /* On some architectures it's safe to do unserialized accept()s in the single
285  * Listen case.  But it's never safe to do it in the case where there's
286  * multiple Listen statements.  Define SINGLE_LISTEN_UNSERIALIZED_ACCEPT
287  * when it's safe in the single Listen case.
288  */
289 #ifdef SINGLE_LISTEN_UNSERIALIZED_ACCEPT
290 #define SAFE_ACCEPT(stmt) (ap_listeners->next ? (stmt) : APR_SUCCESS)
291 #else
292 #define SAFE_ACCEPT(stmt) (stmt)
293 #endif
294 
prefork_query(int query_code,int * result,apr_status_t * rv)295 static int prefork_query(int query_code, int *result, apr_status_t *rv)
296 {
297     *rv = APR_SUCCESS;
298     switch(query_code){
299     case AP_MPMQ_MAX_DAEMON_USED:
300         *result = ap_daemons_limit;
301         break;
302     case AP_MPMQ_IS_THREADED:
303         *result = AP_MPMQ_NOT_SUPPORTED;
304         break;
305     case AP_MPMQ_IS_FORKED:
306         *result = AP_MPMQ_DYNAMIC;
307         break;
308     case AP_MPMQ_HARD_LIMIT_DAEMONS:
309         *result = server_limit;
310         break;
311     case AP_MPMQ_HARD_LIMIT_THREADS:
312         *result = HARD_THREAD_LIMIT;
313         break;
314     case AP_MPMQ_MAX_THREADS:
315         *result = 1;
316         break;
317     case AP_MPMQ_MIN_SPARE_DAEMONS:
318         *result = ap_daemons_min_free;
319         break;
320     case AP_MPMQ_MIN_SPARE_THREADS:
321         *result = 0;
322         break;
323     case AP_MPMQ_MAX_SPARE_DAEMONS:
324         *result = ap_daemons_max_free;
325         break;
326     case AP_MPMQ_MAX_SPARE_THREADS:
327         *result = 0;
328         break;
329     case AP_MPMQ_MAX_REQUESTS_DAEMON:
330         *result = ap_max_requests_per_child;
331         break;
332     case AP_MPMQ_MAX_DAEMONS:
333         *result = ap_daemons_limit;
334         break;
335     case AP_MPMQ_MPM_STATE:
336         *result = retained->mpm->mpm_state;
337         break;
338     case AP_MPMQ_GENERATION:
339         *result = retained->mpm->my_generation;
340         break;
341     default:
342         *rv = APR_ENOTIMPL;
343         break;
344     }
345     return OK;
346 }
347 
prefork_get_name(void)348 static const char *prefork_get_name(void)
349 {
350     return "prefork";
351 }
352 
353 /*****************************************************************
354  * Connection structures and accounting...
355  */
356 
just_die(int sig)357 static void just_die(int sig)
358 {
359     clean_child_exit(0);
360 }
361 
362 /* volatile because it's updated from a signal handler */
363 static int volatile die_now = 0;
364 
stop_listening(int sig)365 static void stop_listening(int sig)
366 {
367     retained->mpm->mpm_state = AP_MPMQ_STOPPING;
368     ap_close_listeners_ex(my_bucket->listeners);
369 
370     /* For a graceful stop, we want the child to exit when done */
371     die_now = 1;
372 }
373 
374 /*****************************************************************
375  * Child process main loop.
376  * The following vars are static to avoid getting clobbered by longjmp();
377  * they are really private to child_main.
378  */
379 
380 static int requests_this_child;
381 static int num_listensocks = 0;
382 
383 #if APR_HAS_THREADS
child_sigmask(sigset_t * new_mask,sigset_t * old_mask)384 static void child_sigmask(sigset_t *new_mask, sigset_t *old_mask)
385 {
386 #if defined(SIGPROCMASK_SETS_THREAD_MASK)
387     sigprocmask(SIG_SETMASK, new_mask, old_mask);
388 #else
389     pthread_sigmask(SIG_SETMASK, new_mask, old_mask);
390 #endif
391 }
392 #endif
393 
child_main(int child_num_arg,int child_bucket)394 static void child_main(int child_num_arg, int child_bucket)
395 {
396 #if APR_HAS_THREADS
397     apr_thread_t *thd = NULL;
398     sigset_t sig_mask;
399 #endif
400     apr_pool_t *ptrans;
401     apr_allocator_t *allocator;
402     apr_status_t status;
403     int i;
404     ap_listen_rec *lr;
405     apr_pollset_t *pollset;
406     ap_sb_handle_t *sbh;
407     apr_bucket_alloc_t *bucket_alloc;
408     int last_poll_idx = 0;
409     const char *lockfile;
410 
411     /* for benefit of any hooks that run as this child initializes */
412     retained->mpm->mpm_state = AP_MPMQ_STARTING;
413 
414     my_child_num = child_num_arg;
415     ap_my_pid = getpid();
416     requests_this_child = 0;
417 
418     ap_fatal_signal_child_setup(ap_server_conf);
419 
420     /* Get a sub context for global allocations in this child, so that
421      * we can have cleanups occur when the child exits.
422      */
423     apr_allocator_create(&allocator);
424     apr_allocator_max_free_set(allocator, ap_max_mem_free);
425     apr_pool_create_ex(&pchild, pconf, NULL, allocator);
426     apr_allocator_owner_set(allocator, pchild);
427     apr_pool_tag(pchild, "pchild");
428 
429 #if AP_HAS_THREAD_LOCAL
430     if (one_process) {
431         thd = ap_thread_current();
432     }
433     else if ((status = ap_thread_main_create(&thd, pchild))) {
434         ap_log_error(APLOG_MARK, APLOG_EMERG, status, ap_server_conf, APLOGNO(10378)
435                      "Couldn't initialize child main thread");
436         clean_child_exit(APEXIT_CHILDFATAL);
437     }
438 #elif APR_HAS_THREADS
439     {
440         apr_os_thread_t osthd = apr_os_thread_current();
441         apr_os_thread_put(&thd, &osthd, pchild);
442     }
443 #endif
444 #if APR_HAS_THREADS
445     ap_assert(thd != NULL);
446 #endif
447 
448     apr_pool_create(&ptrans, pchild);
449     apr_pool_tag(ptrans, "transaction");
450 
451     /* close unused listeners and pods */
452     for (i = 0; i < retained->mpm->num_buckets; i++) {
453         if (i != child_bucket) {
454             ap_close_listeners_ex(all_buckets[i].listeners);
455             ap_mpm_pod_close(all_buckets[i].pod);
456         }
457     }
458 
459     /* needs to be done before we switch UIDs so we have permissions */
460     ap_reopen_scoreboard(pchild, NULL, 0);
461     status = SAFE_ACCEPT(apr_proc_mutex_child_init(&my_bucket->mutex,
462                                     apr_proc_mutex_lockfile(my_bucket->mutex),
463                                     pchild));
464     if (status != APR_SUCCESS) {
465         lockfile = apr_proc_mutex_lockfile(my_bucket->mutex);
466         ap_log_error(APLOG_MARK, APLOG_EMERG, status, ap_server_conf, APLOGNO(00155)
467                      "Couldn't initialize cross-process lock in child "
468                      "(%s) (%s)",
469                      lockfile ? lockfile : "none",
470                      apr_proc_mutex_name(my_bucket->mutex));
471         clean_child_exit(APEXIT_CHILDFATAL);
472     }
473 
474     if (ap_run_drop_privileges(pchild, ap_server_conf)) {
475         clean_child_exit(APEXIT_CHILDFATAL);
476     }
477 
478 #if APR_HAS_THREADS
479     /* Save the signal mask and block all the signals from being received by
480      * threads potentially created in child_init() hooks (e.g. mod_watchdog).
481      */
482     child_sigmask(NULL, &sig_mask);
483     {
484         apr_status_t rv;
485         rv = apr_setup_signal_thread();
486         if (rv != APR_SUCCESS) {
487             ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf, APLOGNO(10271)
488                          "Couldn't initialize signal thread");
489             clean_child_exit(APEXIT_CHILDFATAL);
490         }
491     }
492 #endif /* APR_HAS_THREADS */
493 
494     ap_run_child_init(pchild, ap_server_conf);
495 
496 #if APR_HAS_THREADS
497     /* Restore the original signal mask for this main thread, the only one
498      * that should possibly get interrupted by signals.
499      */
500     child_sigmask(&sig_mask, NULL);
501 #endif
502 
503     ap_create_sb_handle(&sbh, pchild, my_child_num, 0);
504 
505     (void) ap_update_child_status(sbh, SERVER_READY, (request_rec *) NULL);
506 
507     /* Set up the pollfd array */
508     status = apr_pollset_create(&pollset, num_listensocks, pchild,
509                                 APR_POLLSET_NOCOPY);
510     if (status != APR_SUCCESS) {
511         ap_log_error(APLOG_MARK, APLOG_EMERG, status, ap_server_conf, APLOGNO(00156)
512                      "Couldn't create pollset in child; check system or user limits");
513         clean_child_exit(APEXIT_CHILDSICK); /* assume temporary resource issue */
514     }
515 
516     for (lr = my_bucket->listeners, i = num_listensocks; i--; lr = lr->next) {
517         apr_pollfd_t *pfd = apr_pcalloc(pchild, sizeof *pfd);
518 
519         pfd->desc_type = APR_POLL_SOCKET;
520         pfd->desc.s = lr->sd;
521         pfd->reqevents = APR_POLLIN;
522         pfd->client_data = lr;
523 
524         status = apr_pollset_add(pollset, pfd);
525         if (status != APR_SUCCESS) {
526             /* If the child processed a SIGWINCH before setting up the
527              * pollset, this error path is expected and harmless,
528              * since the listener fd was already closed; so don't
529              * pollute the logs in that case. */
530             if (!die_now) {
531                 ap_log_error(APLOG_MARK, APLOG_EMERG, status, ap_server_conf, APLOGNO(00157)
532                              "Couldn't add listener to pollset; check system or user limits");
533                 clean_child_exit(APEXIT_CHILDSICK);
534             }
535             clean_child_exit(0);
536         }
537 
538         lr->accept_func = ap_unixd_accept;
539     }
540 
541     retained->mpm->mpm_state = AP_MPMQ_RUNNING;
542 
543     bucket_alloc = apr_bucket_alloc_create(pchild);
544 
545     /* die_now is set when AP_SIG_GRACEFUL is received in the child;
546      * {shutdown,restart}_pending are set when a signal is received while
547      * running in single process mode.
548      */
549     while (!die_now
550            && !retained->mpm->shutdown_pending
551            && !retained->mpm->restart_pending) {
552         conn_rec *current_conn;
553         void *csd;
554 
555         /*
556          * (Re)initialize this child to a pre-connection state.
557          */
558 
559         apr_pool_clear(ptrans);
560 
561         if ((ap_max_requests_per_child > 0
562              && requests_this_child++ >= ap_max_requests_per_child)) {
563             clean_child_exit(0);
564         }
565 
566         (void) ap_update_child_status(sbh, SERVER_READY, (request_rec *) NULL);
567 
568         /*
569          * Wait for an acceptable connection to arrive.
570          */
571 
572         /* Lock around "accept", if necessary */
573         SAFE_ACCEPT(accept_mutex_on());
574 
575         if (num_listensocks == 1) {
576             /* There is only one listener record, so refer to that one. */
577             lr = my_bucket->listeners;
578         }
579         else {
580             /* multiple listening sockets - need to poll */
581             for (;;) {
582                 apr_int32_t numdesc;
583                 const apr_pollfd_t *pdesc;
584 
585                 /* check for termination first so we don't sleep for a while in
586                  * poll if already signalled
587                  */
588                 if (die_now         /* in graceful stop/restart */
589                         || retained->mpm->shutdown_pending
590                         || retained->mpm->restart_pending) {
591                     SAFE_ACCEPT(accept_mutex_off());
592                     clean_child_exit(0);
593                 }
594 
595                 /* timeout == 10 seconds to avoid a hang at graceful restart/stop
596                  * caused by the closing of sockets by the signal handler
597                  */
598                 status = apr_pollset_poll(pollset, apr_time_from_sec(10),
599                                           &numdesc, &pdesc);
600                 if (status != APR_SUCCESS) {
601                     if (APR_STATUS_IS_TIMEUP(status) ||
602                         APR_STATUS_IS_EINTR(status)) {
603                         continue;
604                     }
605                     /* Single Unix documents select as returning errnos
606                      * EBADF, EINTR, and EINVAL... and in none of those
607                      * cases does it make sense to continue.  In fact
608                      * on Linux 2.0.x we seem to end up with EFAULT
609                      * occasionally, and we'd loop forever due to it.
610                      */
611                     ap_log_error(APLOG_MARK, APLOG_ERR, status,
612                                  ap_server_conf, APLOGNO(00158) "apr_pollset_poll: (listen)");
613                     SAFE_ACCEPT(accept_mutex_off());
614                     clean_child_exit(APEXIT_CHILDSICK);
615                 }
616 
617                 /* We can always use pdesc[0], but sockets at position N
618                  * could end up completely starved of attention in a very
619                  * busy server. Therefore, we round-robin across the
620                  * returned set of descriptors. While it is possible that
621                  * the returned set of descriptors might flip around and
622                  * continue to starve some sockets, we happen to know the
623                  * internal pollset implementation retains ordering
624                  * stability of the sockets. Thus, the round-robin should
625                  * ensure that a socket will eventually be serviced.
626                  */
627                 if (last_poll_idx >= numdesc)
628                     last_poll_idx = 0;
629 
630                 /* Grab a listener record from the client_data of the poll
631                  * descriptor, and advance our saved index to round-robin
632                  * the next fetch.
633                  *
634                  * ### hmm... this descriptor might have POLLERR rather
635                  * ### than POLLIN
636                  */
637                 lr = pdesc[last_poll_idx++].client_data;
638                 goto got_fd;
639             }
640         }
641     got_fd:
642         /* if we accept() something we don't want to die, so we have to
643          * defer the exit
644          */
645         status = lr->accept_func(&csd, lr, ptrans);
646 
647         SAFE_ACCEPT(accept_mutex_off());      /* unlock after "accept" */
648 
649         if (status == APR_EGENERAL) {
650             /* resource shortage or should-not-occur occurred */
651             clean_child_exit(APEXIT_CHILDSICK);
652         }
653         else if (status != APR_SUCCESS) {
654             continue;
655         }
656 
657         /*
658          * We now have a connection, so set it up with the appropriate
659          * socket options, file descriptors, and read/write buffers.
660          */
661 
662         current_conn = ap_run_create_connection(ptrans, ap_server_conf, csd, my_child_num, sbh, bucket_alloc);
663         if (current_conn) {
664 #if APR_HAS_THREADS
665             current_conn->current_thread = thd;
666 #endif
667             ap_process_connection(current_conn, csd);
668             ap_lingering_close(current_conn);
669         }
670 
671         /* Check the pod and the generation number after processing a
672          * connection so that we'll go away if a graceful restart occurred
673          * while we were processing the connection or we are the lucky
674          * idle server process that gets to die.
675          */
676         if (ap_mpm_pod_check(my_bucket->pod) == APR_SUCCESS) { /* selected as idle? */
677             die_now = 1;
678         }
679         else if (retained->mpm->my_generation !=
680                  ap_scoreboard_image->global->running_generation) { /* restart? */
681             /* yeah, this could be non-graceful restart, in which case the
682              * parent will kill us soon enough, but why bother checking?
683              */
684             die_now = 1;
685         }
686     }
687     apr_pool_clear(ptrans); /* kludge to avoid crash in APR reslist cleanup code */
688     clean_child_exit(0);
689 }
690 
691 
make_child(server_rec * s,int slot)692 static int make_child(server_rec *s, int slot)
693 {
694     int bucket = slot % retained->mpm->num_buckets;
695     int pid;
696 
697     if (slot + 1 > retained->max_daemons_limit) {
698         retained->max_daemons_limit = slot + 1;
699     }
700 
701     if (one_process) {
702         my_bucket = &all_buckets[0];
703 
704         prefork_note_child_started(slot, getpid());
705         child_main(slot, 0);
706         /* NOTREACHED */
707         ap_assert(0);
708         return -1;
709     }
710 
711     (void) ap_update_child_status_from_indexes(slot, 0, SERVER_STARTING,
712                                                (request_rec *) NULL);
713 
714 #ifdef _OSD_POSIX
715     /* BS2000 requires a "special" version of fork() before a setuid() call */
716     if ((pid = os_fork(ap_unixd_config.user_name)) == -1) {
717 #else
718     if ((pid = fork()) == -1) {
719 #endif
720         ap_log_error(APLOG_MARK, APLOG_ERR, errno, s, APLOGNO(00159) "fork: Unable to fork new process");
721 
722         /* fork didn't succeed. Fix the scoreboard or else
723          * it will say SERVER_STARTING forever and ever
724          */
725         (void) ap_update_child_status_from_indexes(slot, 0, SERVER_DEAD,
726                                                    (request_rec *) NULL);
727 
728         /* In case system resources are maxxed out, we don't want
729          * Apache running away with the CPU trying to fork over and
730          * over and over again.
731          */
732         sleep(10);
733 
734         return -1;
735     }
736 
737     if (!pid) {
738 #if AP_HAS_THREAD_LOCAL
739         ap_thread_current_after_fork();
740 #endif
741 
742         my_bucket = &all_buckets[bucket];
743 
744 #ifdef HAVE_BINDPROCESSOR
745         /* by default AIX binds to a single processor
746          * this bit unbinds children which will then bind to another cpu
747          */
748         int status = bindprocessor(BINDPROCESS, (int)getpid(),
749                                    PROCESSOR_CLASS_ANY);
750         if (status != OK) {
751             ap_log_error(APLOG_MARK, APLOG_DEBUG, errno,
752                          ap_server_conf, APLOGNO(00160) "processor unbind failed");
753         }
754 #endif
755         RAISE_SIGSTOP(MAKE_CHILD);
756         AP_MONCONTROL(1);
757         /* Disable the parent's signal handlers and set up proper handling in
758          * the child.
759          */
760         apr_signal(SIGHUP, just_die);
761         apr_signal(SIGTERM, just_die);
762         /* Ignore SIGINT in child. This fixes race-conditions in signals
763          * handling when httpd is running on foreground and user hits ctrl+c.
764          * In this case, SIGINT is sent to all children followed by SIGTERM
765          * from the main process, which interrupts the SIGINT handler and
766          * leads to inconsistency.
767          */
768         apr_signal(SIGINT, SIG_IGN);
769         /* The child process just closes listeners on AP_SIG_GRACEFUL.
770          * The pod is used for signalling the graceful restart.
771          */
772         apr_signal(AP_SIG_GRACEFUL, stop_listening);
773         child_main(slot, bucket);
774     }
775 
776     prefork_note_child_started(slot, pid);
777 
778     return 0;
779 }
780 
781 
782 /* start up a bunch of children */
783 static void startup_children(int number_to_start)
784 {
785     int i;
786 
787     for (i = 0; number_to_start && i < ap_daemons_limit; ++i) {
788         if (ap_scoreboard_image->servers[i][0].status != SERVER_DEAD) {
789             continue;
790         }
791         if (make_child(ap_server_conf, i) < 0) {
792             break;
793         }
794         --number_to_start;
795     }
796 }
797 
798 static void perform_idle_server_maintenance(apr_pool_t *p)
799 {
800     int i;
801     int idle_count;
802     worker_score *ws;
803     int free_length;
804     int free_slots[MAX_SPAWN_RATE];
805     int last_non_dead;
806     int total_non_dead;
807 
808     /* initialize the free_list */
809     free_length = 0;
810 
811     idle_count = 0;
812     last_non_dead = -1;
813     total_non_dead = 0;
814 
815     for (i = 0; i < ap_daemons_limit; ++i) {
816         int status;
817 
818         if (i >= retained->max_daemons_limit && free_length == retained->idle_spawn_rate)
819             break;
820         ws = &ap_scoreboard_image->servers[i][0];
821         status = ws->status;
822         if (status == SERVER_DEAD) {
823             /* try to keep children numbers as low as possible */
824             if (free_length < retained->idle_spawn_rate) {
825                 free_slots[free_length] = i;
826                 ++free_length;
827             }
828         }
829         else {
830             /* We consider a starting server as idle because we started it
831              * at least a cycle ago, and if it still hasn't finished starting
832              * then we're just going to swamp things worse by forking more.
833              * So we hopefully won't need to fork more if we count it.
834              * This depends on the ordering of SERVER_READY and SERVER_STARTING.
835              */
836             if (status <= SERVER_READY) {
837                 ++ idle_count;
838             }
839 
840             ++total_non_dead;
841             last_non_dead = i;
842         }
843     }
844     retained->max_daemons_limit = last_non_dead + 1;
845     if (idle_count > ap_daemons_max_free) {
846         static int bucket_kill_child_record = -1;
847         /* kill off one child... we use the pod because that'll cause it to
848          * shut down gracefully, in case it happened to pick up a request
849          * while we were counting
850          */
851         bucket_kill_child_record = (bucket_kill_child_record + 1) % retained->mpm->num_buckets;
852         ap_mpm_pod_signal(all_buckets[bucket_kill_child_record].pod);
853         retained->idle_spawn_rate = 1;
854     }
855     else if (idle_count < ap_daemons_min_free) {
856         /* terminate the free list */
857         if (free_length == 0) {
858             /* only report this condition once */
859             if (!retained->maxclients_reported) {
860                 ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, APLOGNO(00161)
861                             "server reached MaxRequestWorkers setting, consider"
862                             " raising the MaxRequestWorkers setting");
863                 retained->maxclients_reported = 1;
864             }
865             retained->idle_spawn_rate = 1;
866         }
867         else {
868             if (retained->idle_spawn_rate >= 8) {
869                 ap_log_error(APLOG_MARK, APLOG_INFO, 0, ap_server_conf, APLOGNO(00162)
870                     "server seems busy, (you may need "
871                     "to increase StartServers, or Min/MaxSpareServers), "
872                     "spawning %d children, there are %d idle, and "
873                     "%d total children", retained->idle_spawn_rate,
874                     idle_count, total_non_dead);
875             }
876             for (i = 0; i < free_length; ++i) {
877                 make_child(ap_server_conf, free_slots[i]);
878             }
879             /* the next time around we want to spawn twice as many if this
880              * wasn't good enough, but not if we've just done a graceful
881              */
882             if (retained->hold_off_on_exponential_spawning) {
883                 --retained->hold_off_on_exponential_spawning;
884             }
885             else if (retained->idle_spawn_rate < MAX_SPAWN_RATE) {
886                 retained->idle_spawn_rate *= 2;
887             }
888         }
889     }
890     else {
891         retained->idle_spawn_rate = 1;
892     }
893 }
894 
895 /*****************************************************************
896  * Executive routines.
897  */
898 
899 static int prefork_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
900 {
901     int index;
902     int remaining_children_to_start;
903     int i;
904 
905     ap_log_pid(pconf, ap_pid_fname);
906 
907     if (!retained->mpm->was_graceful) {
908         if (ap_run_pre_mpm(s->process->pool, SB_SHARED) != OK) {
909             retained->mpm->mpm_state = AP_MPMQ_STOPPING;
910             return !OK;
911         }
912         /* fix the generation number in the global score; we just got a new,
913          * cleared scoreboard
914          */
915         ap_scoreboard_image->global->running_generation = retained->mpm->my_generation;
916     }
917 
918     ap_unixd_mpm_set_signals(pconf, one_process);
919 
920     if (one_process) {
921         AP_MONCONTROL(1);
922         make_child(ap_server_conf, 0);
923         /* NOTREACHED */
924         ap_assert(0);
925         return !OK;
926     }
927 
928     /* Don't thrash since num_buckets depends on the
929      * system and the number of online CPU cores...
930      */
931     if (ap_daemons_limit < retained->mpm->num_buckets)
932         ap_daemons_limit = retained->mpm->num_buckets;
933     if (ap_daemons_to_start < retained->mpm->num_buckets)
934         ap_daemons_to_start = retained->mpm->num_buckets;
935     if (ap_daemons_min_free < retained->mpm->num_buckets)
936         ap_daemons_min_free = retained->mpm->num_buckets;
937     if (ap_daemons_max_free < ap_daemons_min_free + retained->mpm->num_buckets)
938         ap_daemons_max_free = ap_daemons_min_free + retained->mpm->num_buckets;
939 
940     /* If we're doing a graceful_restart then we're going to see a lot
941      * of children exiting immediately when we get into the main loop
942      * below (because we just sent them AP_SIG_GRACEFUL).  This happens pretty
943      * rapidly... and for each one that exits we'll start a new one until
944      * we reach at least daemons_min_free.  But we may be permitted to
945      * start more than that, so we'll just keep track of how many we're
946      * supposed to start up without the 1 second penalty between each fork.
947      */
948     remaining_children_to_start = ap_daemons_to_start;
949     if (remaining_children_to_start > ap_daemons_limit) {
950         remaining_children_to_start = ap_daemons_limit;
951     }
952     if (!retained->mpm->was_graceful) {
953         startup_children(remaining_children_to_start);
954         remaining_children_to_start = 0;
955     }
956     else {
957         /* give the system some time to recover before kicking into
958          * exponential mode
959          */
960         retained->hold_off_on_exponential_spawning = 10;
961     }
962 
963     ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, APLOGNO(00163)
964                 "%s configured -- resuming normal operations",
965                 ap_get_server_description());
966     ap_log_error(APLOG_MARK, APLOG_INFO, 0, ap_server_conf, APLOGNO(00164)
967                 "Server built: %s", ap_get_server_built());
968     ap_log_command_line(plog, s);
969     ap_log_mpm_common(s);
970     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(00165)
971                 "Accept mutex: %s (default: %s)",
972                 (all_buckets[0].mutex)
973                     ? apr_proc_mutex_name(all_buckets[0].mutex)
974                     : "none",
975                 apr_proc_mutex_defname());
976 
977     retained->mpm->mpm_state = AP_MPMQ_RUNNING;
978 
979     while (!retained->mpm->restart_pending && !retained->mpm->shutdown_pending) {
980         int child_slot;
981         apr_exit_why_e exitwhy;
982         int status, processed_status;
983         /* this is a memory leak, but I'll fix it later. */
984         apr_proc_t pid;
985 
986         ap_wait_or_timeout(&exitwhy, &status, &pid, pconf, ap_server_conf);
987 
988         /* XXX: if it takes longer than 1 second for all our children
989          * to start up and get into IDLE state then we may spawn an
990          * extra child
991          */
992         if (pid.pid != -1) {
993             processed_status = ap_process_child_status(&pid, exitwhy, status);
994             child_slot = ap_find_child_by_pid(&pid);
995             if (processed_status == APEXIT_CHILDFATAL) {
996                 /* fix race condition found in PR 39311
997                  * A child created at the same time as a graceful happens
998                  * can find the lock missing and create a fatal error.
999                  * It is not fatal for the last generation to be in this state.
1000                  */
1001                 if (child_slot < 0
1002                     || ap_get_scoreboard_process(child_slot)->generation
1003                        == retained->mpm->my_generation) {
1004                     retained->mpm->mpm_state = AP_MPMQ_STOPPING;
1005                     return !OK;
1006                 }
1007                 else {
1008                     ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ap_server_conf, APLOGNO(00166)
1009                                  "Ignoring fatal error in child of previous "
1010                                  "generation (pid %ld).",
1011                                  (long)pid.pid);
1012                 }
1013             }
1014 
1015             /* non-fatal death... note that it's gone in the scoreboard. */
1016             if (child_slot >= 0) {
1017                 (void) ap_update_child_status_from_indexes(child_slot, 0, SERVER_DEAD,
1018                                                            (request_rec *) NULL);
1019                 prefork_note_child_killed(child_slot, 0, 0);
1020                 if (processed_status == APEXIT_CHILDSICK) {
1021                     /* child detected a resource shortage (E[NM]FILE, ENOBUFS, etc)
1022                      * cut the fork rate to the minimum
1023                      */
1024                     retained->idle_spawn_rate = 1;
1025                 }
1026                 else if (remaining_children_to_start
1027                     && child_slot < ap_daemons_limit) {
1028                     /* we're still doing a 1-for-1 replacement of dead
1029                      * children with new children
1030                      */
1031                     make_child(ap_server_conf, child_slot);
1032                     --remaining_children_to_start;
1033                 }
1034 #if APR_HAS_OTHER_CHILD
1035             }
1036             else if (apr_proc_other_child_alert(&pid, APR_OC_REASON_DEATH, status) == APR_SUCCESS) {
1037                 /* handled */
1038 #endif
1039             }
1040             else if (retained->mpm->was_graceful) {
1041                 /* Great, we've probably just lost a slot in the
1042                  * scoreboard.  Somehow we don't know about this
1043                  * child.
1044                  */
1045                 ap_log_error(APLOG_MARK, APLOG_WARNING,
1046                             0, ap_server_conf, APLOGNO(00167)
1047                             "long lost child came home! (pid %ld)", (long)pid.pid);
1048             }
1049             /* Don't perform idle maintenance when a child dies,
1050              * only do it when there's a timeout.  Remember only a
1051              * finite number of children can die, and it's pretty
1052              * pathological for a lot to die suddenly.
1053              */
1054             continue;
1055         }
1056         else if (remaining_children_to_start) {
1057             /* we hit a 1 second timeout in which none of the previous
1058              * generation of children needed to be reaped... so assume
1059              * they're all done, and pick up the slack if any is left.
1060              */
1061             startup_children(remaining_children_to_start);
1062             remaining_children_to_start = 0;
1063             /* In any event we really shouldn't do the code below because
1064              * few of the servers we just started are in the IDLE state
1065              * yet, so we'd mistakenly create an extra server.
1066              */
1067             continue;
1068         }
1069 
1070         perform_idle_server_maintenance(pconf);
1071     }
1072 
1073     retained->mpm->mpm_state = AP_MPMQ_STOPPING;
1074 
1075     if (retained->mpm->shutdown_pending && retained->mpm->is_ungraceful) {
1076         /* Time to shut down:
1077          * Kill child processes, tell them to call child_exit, etc...
1078          */
1079         if (ap_unixd_killpg(getpgrp(), SIGTERM) < 0) {
1080             ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00168) "killpg SIGTERM");
1081         }
1082         ap_reclaim_child_processes(1, /* Start with SIGTERM */
1083                                    prefork_note_child_killed);
1084 
1085         /* cleanup pid file on normal shutdown */
1086         ap_remove_pid(pconf, ap_pid_fname);
1087         ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, APLOGNO(00169)
1088                     "caught SIGTERM, shutting down");
1089 
1090         return DONE;
1091     }
1092 
1093     if (retained->mpm->shutdown_pending) {
1094         /* Time to perform a graceful shut down:
1095          * Reap the inactive children, and ask the active ones
1096          * to close their listeners, then wait until they are
1097          * all done to exit.
1098          */
1099         int active_children;
1100         apr_time_t cutoff = 0;
1101 
1102         /* Stop listening */
1103         ap_close_listeners();
1104 
1105         /* kill off the idle ones */
1106         for (i = 0; i < retained->mpm->num_buckets; i++) {
1107             ap_mpm_pod_killpg(all_buckets[i].pod, retained->max_daemons_limit);
1108         }
1109 
1110         /* Send SIGUSR1 to the active children */
1111         active_children = 0;
1112         for (index = 0; index < ap_daemons_limit; ++index) {
1113             if (ap_scoreboard_image->servers[index][0].status != SERVER_DEAD) {
1114                 /* Ask each child to close its listeners. */
1115                 ap_mpm_safe_kill(MPM_CHILD_PID(index), AP_SIG_GRACEFUL);
1116                 active_children++;
1117             }
1118         }
1119 
1120         /* Allow each child which actually finished to exit */
1121         ap_relieve_child_processes(prefork_note_child_killed);
1122 
1123         /* cleanup pid file */
1124         ap_remove_pid(pconf, ap_pid_fname);
1125         ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, APLOGNO(00170)
1126            "caught " AP_SIG_GRACEFUL_STOP_STRING ", shutting down gracefully");
1127 
1128         if (ap_graceful_shutdown_timeout) {
1129             cutoff = apr_time_now() +
1130                      apr_time_from_sec(ap_graceful_shutdown_timeout);
1131         }
1132 
1133         /* Don't really exit until each child has finished */
1134         retained->mpm->shutdown_pending = 0;
1135         do {
1136             /* Pause for a second */
1137             sleep(1);
1138 
1139             /* Relieve any children which have now exited */
1140             ap_relieve_child_processes(prefork_note_child_killed);
1141 
1142             active_children = 0;
1143             for (index = 0; index < ap_daemons_limit; ++index) {
1144                 if (ap_mpm_safe_kill(MPM_CHILD_PID(index), 0) == APR_SUCCESS) {
1145                     active_children = 1;
1146                     /* Having just one child is enough to stay around */
1147                     break;
1148                 }
1149             }
1150         } while (!retained->mpm->shutdown_pending && active_children &&
1151                  (!ap_graceful_shutdown_timeout || apr_time_now() < cutoff));
1152 
1153         /* We might be here because we received SIGTERM, either
1154          * way, try and make sure that all of our processes are
1155          * really dead.
1156          */
1157         ap_unixd_killpg(getpgrp(), SIGTERM);
1158 
1159         return DONE;
1160     }
1161 
1162     /* we've been told to restart */
1163     if (one_process) {
1164         /* not worth thinking about */
1165         return DONE;
1166     }
1167 
1168     /* advance to the next generation */
1169     /* XXX: we really need to make sure this new generation number isn't in
1170      * use by any of the children.
1171      */
1172     ++retained->mpm->my_generation;
1173     ap_scoreboard_image->global->running_generation = retained->mpm->my_generation;
1174 
1175     if (!retained->mpm->is_ungraceful) {
1176         ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, APLOGNO(00171)
1177                     "Graceful restart requested, doing restart");
1178 
1179         /* kill off the idle ones */
1180         for (i = 0; i < retained->mpm->num_buckets; i++) {
1181             ap_mpm_pod_killpg(all_buckets[i].pod, retained->max_daemons_limit);
1182         }
1183 
1184         /* This is mostly for debugging... so that we know what is still
1185          * gracefully dealing with existing request.  This will break
1186          * in a very nasty way if we ever have the scoreboard totally
1187          * file-based (no shared memory)
1188          */
1189         for (index = 0; index < ap_daemons_limit; ++index) {
1190             if (ap_scoreboard_image->servers[index][0].status != SERVER_DEAD) {
1191                 ap_scoreboard_image->servers[index][0].status = SERVER_GRACEFUL;
1192                 /* Ask each child to close its listeners.
1193                  *
1194                  * NOTE: we use the scoreboard, because if we send SIGUSR1
1195                  * to every process in the group, this may include CGI's,
1196                  * piped loggers, etc. They almost certainly won't handle
1197                  * it gracefully.
1198                  */
1199                 ap_mpm_safe_kill(ap_scoreboard_image->parent[index].pid, AP_SIG_GRACEFUL);
1200             }
1201         }
1202     }
1203     else {
1204         /* Kill 'em off */
1205         if (ap_unixd_killpg(getpgrp(), SIGHUP) < 0) {
1206             ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00172) "killpg SIGHUP");
1207         }
1208         ap_reclaim_child_processes(0, /* Not when just starting up */
1209                                    prefork_note_child_killed);
1210         ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, APLOGNO(00173)
1211                     "SIGHUP received.  Attempting to restart");
1212     }
1213 
1214     return OK;
1215 }
1216 
1217 /* This really should be a post_config hook, but the error log is already
1218  * redirected by that point, so we need to do this in the open_logs phase.
1219  */
1220 static int prefork_open_logs(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
1221 {
1222     int startup = 0;
1223     int level_flags = 0;
1224     ap_listen_rec **listen_buckets;
1225     apr_status_t rv;
1226     char id[16];
1227     int i;
1228 
1229     pconf = p;
1230 
1231     /* the reverse of pre_config, we want this only the first time around */
1232     if (retained->mpm->module_loads == 1) {
1233         startup = 1;
1234         level_flags |= APLOG_STARTUP;
1235     }
1236 
1237     if ((num_listensocks = ap_setup_listeners(ap_server_conf)) < 1) {
1238         ap_log_error(APLOG_MARK, APLOG_ALERT | level_flags, 0,
1239                      (startup ? NULL : s),
1240                      "no listening sockets available, shutting down");
1241         return !OK;
1242     }
1243 
1244     if (one_process) {
1245         retained->mpm->num_buckets = 1;
1246     }
1247     else if (!retained->mpm->was_graceful) {
1248         /* Preserve the number of buckets on graceful restarts. */
1249         retained->mpm->num_buckets = 0;
1250     }
1251     if ((rv = ap_duplicate_listeners(pconf, ap_server_conf,
1252                                      &listen_buckets, &retained->mpm->num_buckets))) {
1253         ap_log_error(APLOG_MARK, APLOG_CRIT | level_flags, rv,
1254                      (startup ? NULL : s),
1255                      "could not duplicate listeners");
1256         return !OK;
1257     }
1258     all_buckets = apr_pcalloc(pconf, retained->mpm->num_buckets *
1259                                      sizeof(prefork_child_bucket));
1260     for (i = 0; i < retained->mpm->num_buckets; i++) {
1261         if ((rv = ap_mpm_pod_open(pconf, &all_buckets[i].pod))) {
1262             ap_log_error(APLOG_MARK, APLOG_CRIT | level_flags, rv,
1263                          (startup ? NULL : s),
1264                          "could not open pipe-of-death");
1265             return !OK;
1266         }
1267         /* Initialize cross-process accept lock (safe accept needed only) */
1268         if ((rv = SAFE_ACCEPT((apr_snprintf(id, sizeof id, "%i", i),
1269                                ap_proc_mutex_create(&all_buckets[i].mutex,
1270                                                     NULL, AP_ACCEPT_MUTEX_TYPE,
1271                                                     id, s, pconf, 0))))) {
1272             ap_log_error(APLOG_MARK, APLOG_CRIT | level_flags, rv,
1273                          (startup ? NULL : s),
1274                          "could not create accept mutex");
1275             return !OK;
1276         }
1277         all_buckets[i].listeners = listen_buckets[i];
1278     }
1279 
1280     return OK;
1281 }
1282 
1283 static int prefork_pre_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp)
1284 {
1285     int no_detach, debug, foreground;
1286     apr_status_t rv;
1287     const char *userdata_key = "mpm_prefork_module";
1288 
1289     debug = ap_exists_config_define("DEBUG");
1290 
1291     if (debug) {
1292         foreground = one_process = 1;
1293         no_detach = 0;
1294     }
1295     else
1296     {
1297         no_detach = ap_exists_config_define("NO_DETACH");
1298         one_process = ap_exists_config_define("ONE_PROCESS");
1299         foreground = ap_exists_config_define("FOREGROUND");
1300     }
1301 
1302     ap_mutex_register(p, AP_ACCEPT_MUTEX_TYPE, NULL, APR_LOCK_DEFAULT, 0);
1303 
1304     retained = ap_retained_data_get(userdata_key);
1305     if (!retained) {
1306         retained = ap_retained_data_create(userdata_key, sizeof(*retained));
1307         retained->mpm = ap_unixd_mpm_get_retained_data();
1308         retained->idle_spawn_rate = 1;
1309     }
1310     retained->mpm->mpm_state = AP_MPMQ_STARTING;
1311     if (retained->mpm->baton != retained) {
1312         retained->mpm->was_graceful = 0;
1313         retained->mpm->baton = retained;
1314     }
1315     ++retained->mpm->module_loads;
1316 
1317     /* sigh, want this only the second time around */
1318     if (retained->mpm->module_loads == 2) {
1319         if (!one_process && !foreground) {
1320             /* before we detach, setup crash handlers to log to errorlog */
1321             ap_fatal_signal_setup(ap_server_conf, p /* == pconf */);
1322             rv = apr_proc_detach(no_detach ? APR_PROC_DETACH_FOREGROUND
1323                                            : APR_PROC_DETACH_DAEMONIZE);
1324             if (rv != APR_SUCCESS) {
1325                 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL, APLOGNO(00174)
1326                              "apr_proc_detach failed");
1327                 return HTTP_INTERNAL_SERVER_ERROR;
1328             }
1329         }
1330     }
1331 
1332     parent_pid = ap_my_pid = getpid();
1333 
1334     ap_listen_pre_config();
1335     ap_daemons_to_start = DEFAULT_START_DAEMON;
1336     ap_daemons_min_free = DEFAULT_MIN_FREE_DAEMON;
1337     ap_daemons_max_free = DEFAULT_MAX_FREE_DAEMON;
1338     server_limit = DEFAULT_SERVER_LIMIT;
1339     ap_daemons_limit = server_limit;
1340     ap_extended_status = 0;
1341 
1342     return OK;
1343 }
1344 
1345 static int prefork_check_config(apr_pool_t *p, apr_pool_t *plog,
1346                                 apr_pool_t *ptemp, server_rec *s)
1347 {
1348     int startup = 0;
1349 
1350     /* the reverse of pre_config, we want this only the first time around */
1351     if (retained->mpm->module_loads == 1) {
1352         startup = 1;
1353     }
1354 
1355     if (server_limit > MAX_SERVER_LIMIT) {
1356         if (startup) {
1357             ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00175)
1358                          "WARNING: ServerLimit of %d exceeds compile-time "
1359                          "limit of %d servers, decreasing to %d.",
1360                          server_limit, MAX_SERVER_LIMIT, MAX_SERVER_LIMIT);
1361         } else {
1362             ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00176)
1363                          "ServerLimit of %d exceeds compile-time limit "
1364                          "of %d, decreasing to match",
1365                          server_limit, MAX_SERVER_LIMIT);
1366         }
1367         server_limit = MAX_SERVER_LIMIT;
1368     }
1369     else if (server_limit < 1) {
1370         if (startup) {
1371             ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00177)
1372                          "WARNING: ServerLimit of %d not allowed, "
1373                          "increasing to 1.", server_limit);
1374         } else {
1375             ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00178)
1376                          "ServerLimit of %d not allowed, increasing to 1",
1377                          server_limit);
1378         }
1379         server_limit = 1;
1380     }
1381 
1382     /* you cannot change ServerLimit across a restart; ignore
1383      * any such attempts
1384      */
1385     if (!retained->first_server_limit) {
1386         retained->first_server_limit = server_limit;
1387     }
1388     else if (server_limit != retained->first_server_limit) {
1389         /* don't need a startup console version here */
1390         ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00179)
1391                      "changing ServerLimit to %d from original value of %d "
1392                      "not allowed during restart",
1393                      server_limit, retained->first_server_limit);
1394         server_limit = retained->first_server_limit;
1395     }
1396 
1397     if (ap_daemons_limit > server_limit) {
1398         if (startup) {
1399             ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00180)
1400                          "WARNING: MaxRequestWorkers of %d exceeds ServerLimit "
1401                          "value of %d servers, decreasing MaxRequestWorkers to %d. "
1402                          "To increase, please see the ServerLimit directive.",
1403                          ap_daemons_limit, server_limit, server_limit);
1404         } else {
1405             ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00181)
1406                          "MaxRequestWorkers of %d exceeds ServerLimit value "
1407                          "of %d, decreasing to match",
1408                          ap_daemons_limit, server_limit);
1409         }
1410         ap_daemons_limit = server_limit;
1411     }
1412     else if (ap_daemons_limit < 1) {
1413         if (startup) {
1414             ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00182)
1415                          "WARNING: MaxRequestWorkers of %d not allowed, "
1416                          "increasing to 1.", ap_daemons_limit);
1417         } else {
1418             ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00183)
1419                          "MaxRequestWorkers of %d not allowed, increasing to 1",
1420                          ap_daemons_limit);
1421         }
1422         ap_daemons_limit = 1;
1423     }
1424 
1425     /* ap_daemons_to_start > ap_daemons_limit checked in prefork_run() */
1426     if (ap_daemons_to_start < 1) {
1427         if (startup) {
1428             ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00184)
1429                          "WARNING: StartServers of %d not allowed, "
1430                          "increasing to 1.", ap_daemons_to_start);
1431         } else {
1432             ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00185)
1433                          "StartServers of %d not allowed, increasing to 1",
1434                          ap_daemons_to_start);
1435         }
1436         ap_daemons_to_start = 1;
1437     }
1438 
1439     if (ap_daemons_min_free < 1) {
1440         if (startup) {
1441             ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00186)
1442                          "WARNING: MinSpareServers of %d not allowed, "
1443                          "increasing to 1 to avoid almost certain server failure. "
1444                          "Please read the documentation.", ap_daemons_min_free);
1445         } else {
1446             ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00187)
1447                          "MinSpareServers of %d not allowed, increasing to 1",
1448                          ap_daemons_min_free);
1449         }
1450         ap_daemons_min_free = 1;
1451     }
1452 
1453     /* ap_daemons_max_free < ap_daemons_min_free + 1 checked in prefork_run() */
1454 
1455     return OK;
1456 }
1457 
1458 static void prefork_hooks(apr_pool_t *p)
1459 {
1460     /* Our open_logs hook function must run before the core's, or stderr
1461      * will be redirected to a file, and the messages won't print to the
1462      * console.
1463      */
1464     static const char *const aszSucc[] = {"core.c", NULL};
1465 
1466     ap_hook_open_logs(prefork_open_logs, NULL, aszSucc, APR_HOOK_REALLY_FIRST);
1467     /* we need to set the MPM state before other pre-config hooks use MPM query
1468      * to retrieve it, so register as REALLY_FIRST
1469      */
1470     ap_hook_pre_config(prefork_pre_config, NULL, NULL, APR_HOOK_REALLY_FIRST);
1471     ap_hook_check_config(prefork_check_config, NULL, NULL, APR_HOOK_MIDDLE);
1472     ap_hook_mpm(prefork_run, NULL, NULL, APR_HOOK_MIDDLE);
1473     ap_hook_mpm_query(prefork_query, NULL, NULL, APR_HOOK_MIDDLE);
1474     ap_hook_mpm_get_name(prefork_get_name, NULL, NULL, APR_HOOK_MIDDLE);
1475 }
1476 
1477 static const char *set_daemons_to_start(cmd_parms *cmd, void *dummy, const char *arg)
1478 {
1479     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
1480     if (err != NULL) {
1481         return err;
1482     }
1483 
1484     ap_daemons_to_start = atoi(arg);
1485     return NULL;
1486 }
1487 
1488 static const char *set_min_free_servers(cmd_parms *cmd, void *dummy, const char *arg)
1489 {
1490     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
1491     if (err != NULL) {
1492         return err;
1493     }
1494 
1495     ap_daemons_min_free = atoi(arg);
1496     return NULL;
1497 }
1498 
1499 static const char *set_max_free_servers(cmd_parms *cmd, void *dummy, const char *arg)
1500 {
1501     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
1502     if (err != NULL) {
1503         return err;
1504     }
1505 
1506     ap_daemons_max_free = atoi(arg);
1507     return NULL;
1508 }
1509 
1510 static const char *set_max_clients (cmd_parms *cmd, void *dummy, const char *arg)
1511 {
1512     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
1513     if (err != NULL) {
1514         return err;
1515     }
1516     if (!strcasecmp(cmd->cmd->name, "MaxClients")) {
1517         ap_log_error(APLOG_MARK, APLOG_INFO, 0, NULL, APLOGNO(00188)
1518                      "MaxClients is deprecated, use MaxRequestWorkers "
1519                      "instead.");
1520     }
1521     ap_daemons_limit = atoi(arg);
1522     return NULL;
1523 }
1524 
1525 static const char *set_server_limit (cmd_parms *cmd, void *dummy, const char *arg)
1526 {
1527     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
1528     if (err != NULL) {
1529         return err;
1530     }
1531 
1532     server_limit = atoi(arg);
1533     return NULL;
1534 }
1535 
1536 static const command_rec prefork_cmds[] = {
1537 LISTEN_COMMANDS,
1538 AP_INIT_TAKE1("StartServers", set_daemons_to_start, NULL, RSRC_CONF,
1539               "Number of child processes launched at server startup"),
1540 AP_INIT_TAKE1("MinSpareServers", set_min_free_servers, NULL, RSRC_CONF,
1541               "Minimum number of idle children, to handle request spikes"),
1542 AP_INIT_TAKE1("MaxSpareServers", set_max_free_servers, NULL, RSRC_CONF,
1543               "Maximum number of idle children"),
1544 AP_INIT_TAKE1("MaxClients", set_max_clients, NULL, RSRC_CONF,
1545               "Deprecated name of MaxRequestWorkers"),
1546 AP_INIT_TAKE1("MaxRequestWorkers", set_max_clients, NULL, RSRC_CONF,
1547               "Maximum number of children alive at the same time"),
1548 AP_INIT_TAKE1("ServerLimit", set_server_limit, NULL, RSRC_CONF,
1549               "Maximum value of MaxRequestWorkers for this run of Apache"),
1550 AP_GRACEFUL_SHUTDOWN_TIMEOUT_COMMAND,
1551 { NULL }
1552 };
1553 
1554 AP_DECLARE_MODULE(mpm_prefork) = {
1555     MPM20_MODULE_STUFF,
1556     NULL,                       /* hook to run before apache parses args */
1557     NULL,                       /* create per-directory config structure */
1558     NULL,                       /* merge per-directory config structures */
1559     NULL,                       /* create per-server config structure */
1560     NULL,                       /* merge per-server config structures */
1561     prefork_cmds,               /* command apr_table_t */
1562     prefork_hooks,              /* register hooks */
1563 };
1564