]> granicus.if.org Git - apache/blob - server/mpm/perchild/perchild.c
This makes the perchild MPM server requests again, but it still isn't
[apache] / server / mpm / perchild / perchild.c
1 /* ====================================================================
2  * The Apache Software License, Version 1.1
3  *
4  * Copyright (c) 2000 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 #define CORE_PRIVATE 
60  
61 #include "ap_config.h"
62 #include "apr_hash.h"
63 #include "apr_strings.h"
64 #include "apr_portable.h"
65 #include "apr_file_io.h"
66 #include "httpd.h" 
67 #include "http_main.h" 
68 #include "http_log.h" 
69 #include "http_config.h"        /* for read_config */ 
70 #include "http_core.h"          /* for get_remote_host */ 
71 #include "http_protocol.h"
72 #include "http_connection.h"
73 #include "ap_mpm.h"
74 #include "unixd.h"
75 #include "mpm_common.h"
76 #include "ap_iol.h"
77 #include "ap_listen.h"
78 #include "mpm_default.h"
79 #include "mpm.h"
80 #include "scoreboard.h"
81
82 #ifdef HAVE_UNISTD_H
83 #include <unistd.h>
84 #endif
85 #include <poll.h>
86 #ifdef HAVE_SYS_SOCKET_H
87 #include <sys/socket.h>
88 #endif
89 #ifdef HAVE_NETINET_TCP_H
90 #include <netinet/tcp.h>
91 #endif
92 #include <grp.h>
93 #include <pwd.h>
94 #include <pthread.h>
95 #include <sys/stat.h>
96 #include <signal.h>
97 #include <sys/un.h>
98
99 /*
100  * Actual definitions of config globals
101  */
102
103 static int threads_to_start = 0;         /* Worker threads per child */
104 static int min_spare_threads = 0;
105 static int max_spare_threads = 0;
106 static int max_threads = 0;
107 static int max_requests_per_child = 0;
108 static const char *ap_pid_fname=NULL;
109 API_VAR_EXPORT const char *ap_scoreboard_fname=NULL;
110 static int num_daemons=0;
111 static int workers_may_exit = 0;
112 static int requests_this_child;
113 static int num_listenfds = 0;
114 static ap_socket_t **listenfds;
115
116 struct child_info_t {
117     uid_t uid;
118     gid_t gid;
119 };
120
121 struct socket_info_t {
122     const char *sname;   /* The servername */
123     int        cnum;     /* The child number */
124 };
125
126 typedef struct {
127     const char *sockname;
128 } perchild_server_conf;
129
130 typedef struct child_info_t child_info_t;
131 typedef struct socket_info_t socket_info_t;
132
133 /* Tables used to determine the user and group each child process should
134  * run as.  The hash table is used to correlate a server name with a child
135  * process.
136  */
137 static child_info_t child_info_table[HARD_SERVER_LIMIT];
138 static ap_hash_t    *socket_info_table = NULL;
139
140
141 struct ap_ctable    ap_child_table[HARD_SERVER_LIMIT];
142
143 /*
144  * The max child slot ever assigned, preserved across restarts.  Necessary
145  * to deal with NumServers changes across SIGWINCH restarts.  We use this
146  * value to optimize routines that have to scan the entire child table.
147  *
148  * XXX - It might not be worth keeping this code in. There aren't very
149  * many child processes in this MPM.
150  */
151 int ap_max_daemons_limit = -1;
152
153 char ap_coredump_dir[MAX_STRING_LEN];
154
155 module MODULE_VAR_EXPORT mpm_perchild_module;
156
157 static ap_file_t *pipe_of_death_in = NULL;
158 static ap_file_t *pipe_of_death_out = NULL;
159 static pthread_mutex_t pipe_of_death_mutex;
160
161 /* *Non*-shared http_main globals... */
162
163 server_rec *ap_server_conf;
164
165 /* one_process --- debugging mode variable; can be set from the command line
166  * with the -X flag.  If set, this gets you the child_main loop running
167  * in the process which originally started up (no detach, no make_child),
168  * which is a pretty nice debugging environment.  (You'll get a SIGHUP
169  * early in standalone_main; just continue through.  This is the server
170  * trying to kill off any child processes which it might have lying
171  * around --- Apache doesn't keep track of their pids, it just sends
172  * SIGHUP to the process group, ignoring it in the root process.
173  * Continue through and you'll be fine.).
174  */
175
176 static int one_process = 0;
177
178 #ifdef DEBUG_SIGSTOP
179 int raise_sigstop_flags;
180 #endif
181
182 static ap_pool_t *pconf;                /* Pool for config stuff */
183 static ap_pool_t *pchild;               /* Pool for httpd child stuff */
184 static ap_pool_t *thread_pool_parent; /* Parent of per-thread pools */
185 static pthread_mutex_t thread_pool_parent_mutex;
186
187 static int child_num;
188 static unsigned int my_pid; /* Linux getpid() doesn't work except in 
189                       main thread. Use this instead */
190 /* Keep track of the number of worker threads currently active */
191 static int worker_thread_count;
192 static pthread_mutex_t worker_thread_count_mutex;
193 static int worker_thread_free_ids[HARD_THREAD_LIMIT];
194 static pthread_attr_t worker_thread_attr;
195
196 /* Keep track of the number of idle worker threads */
197 static int idle_thread_count;
198 static pthread_mutex_t idle_thread_count_mutex;
199
200 /* Locks for accept serialization */
201 #ifdef NO_SERIALIZED_ACCEPT
202 #define SAFE_ACCEPT(stmt) APR_SUCCESS
203 #else
204 #define SAFE_ACCEPT(stmt) (stmt)
205 static ap_lock_t *process_accept_mutex;
206 #endif /* NO_SERIALIZED_ACCEPT */
207 static const char *lock_fname;
208 static pthread_mutex_t thread_accept_mutex = PTHREAD_MUTEX_INITIALIZER;
209
210 API_EXPORT(int) ap_get_max_daemons(void)
211 {
212     return ap_max_daemons_limit;
213 }
214
215 /* a clean exit from a child with proper cleanup */
216 static void clean_child_exit(int code)
217 {
218     if (pchild) {
219         ap_destroy_pool(pchild);
220     }
221     exit(code);
222 }
223
224 /* handle all varieties of core dumping signals */
225 static void sig_coredump(int sig)
226 {
227     chdir(ap_coredump_dir);
228     ap_signal(sig, SIG_DFL);
229     kill(getpid(), sig);
230     /* At this point we've got sig blocked, because we're still inside
231      * the signal handler.  When we leave the signal handler it will
232      * be unblocked, and we'll take the signal... and coredump or whatever
233      * is appropriate for this particular Unix.  In addition the parent
234      * will see the real signal we received -- whereas if we called
235      * abort() here, the parent would only see SIGABRT.
236      */
237 }
238
239 static void just_die(int sig)
240 {
241     clean_child_exit(0);
242 }
243
244 /*****************************************************************
245  * Connection structures and accounting...
246  */
247
248 /* volatile just in case */
249 static int volatile shutdown_pending;
250 static int volatile restart_pending;
251 static int volatile is_graceful;
252
253 /*
254  * ap_start_shutdown() and ap_start_restart(), below, are a first stab at
255  * functions to initiate shutdown or restart without relying on signals. 
256  * Previously this was initiated in sig_term() and restart() signal handlers, 
257  * but we want to be able to start a shutdown/restart from other sources --
258  * e.g. on Win32, from the service manager. Now the service manager can
259  * call ap_start_shutdown() or ap_start_restart() as appropiate.  Note that
260  * these functions can also be called by the child processes, since global
261  * variables are no longer used to pass on the required action to the parent.
262  *
263  * These should only be called from the parent process itself, since the
264  * parent process will use the shutdown_pending and restart_pending variables
265  * to determine whether to shutdown or restart. The child process should
266  * call signal_parent() directly to tell the parent to die -- this will
267  * cause neither of those variable to be set, which the parent will
268  * assume means something serious is wrong (which it will be, for the
269  * child to force an exit) and so do an exit anyway.
270  */
271
272 void ap_start_shutdown(void)
273 {
274     if (shutdown_pending == 1) {
275         /* Um, is this _probably_ not an error, if the user has
276          * tried to do a shutdown twice quickly, so we won't
277          * worry about reporting it.
278          */
279         return;
280     }
281     shutdown_pending = 1;
282 }
283
284 /* do a graceful restart if graceful == 1 */
285 static void ap_start_restart(int graceful)
286 {
287
288     if (restart_pending == 1) {
289         /* Probably not an error - don't bother reporting it */
290         return;
291     }
292     restart_pending = 1;
293     is_graceful = graceful;
294     if (is_graceful) {
295         ap_kill_cleanup(pconf, NULL, ap_cleanup_shared_mem);
296     }
297 }
298
299 static void sig_term(int sig)
300 {
301     ap_start_shutdown();
302 }
303
304 static void restart(int sig)
305 {
306 #ifndef WIN32
307     ap_start_restart(sig == SIGWINCH);
308 #else
309     ap_start_restart(1);
310 #endif
311 }
312
313 static void set_signals(void)
314 {
315 #ifndef NO_USE_SIGACTION
316     struct sigaction sa;
317
318     sigemptyset(&sa.sa_mask);
319     sa.sa_flags = 0;
320
321     if (!one_process) {
322         sa.sa_handler = sig_coredump;
323 #if defined(SA_ONESHOT)
324         sa.sa_flags = SA_ONESHOT;
325 #elif defined(SA_RESETHAND)
326         sa.sa_flags = SA_RESETHAND;
327 #endif
328         if (sigaction(SIGSEGV, &sa, NULL) < 0)
329             ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGSEGV)");
330 #ifdef SIGBUS
331         if (sigaction(SIGBUS, &sa, NULL) < 0)
332             ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGBUS)");
333 #endif
334 #ifdef SIGABORT
335         if (sigaction(SIGABORT, &sa, NULL) < 0)
336             ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGABORT)");
337 #endif
338 #ifdef SIGABRT
339         if (sigaction(SIGABRT, &sa, NULL) < 0)
340             ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGABRT)");
341 #endif
342 #ifdef SIGILL
343         if (sigaction(SIGILL, &sa, NULL) < 0)
344             ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGILL)");
345 #endif
346         sa.sa_flags = 0;
347     }
348     sa.sa_handler = sig_term;
349     if (sigaction(SIGTERM, &sa, NULL) < 0)
350         ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGTERM)");
351 #ifdef SIGINT
352     if (sigaction(SIGINT, &sa, NULL) < 0)
353         ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGINT)");
354 #endif
355 #ifdef SIGXCPU
356     sa.sa_handler = SIG_DFL;
357     if (sigaction(SIGXCPU, &sa, NULL) < 0)
358         ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGXCPU)");
359 #endif
360 #ifdef SIGXFSZ
361     sa.sa_handler = SIG_DFL;
362     if (sigaction(SIGXFSZ, &sa, NULL) < 0)
363         ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGXFSZ)");
364 #endif
365 #ifdef SIGPIPE
366     sa.sa_handler = SIG_IGN;
367     if (sigaction(SIGPIPE, &sa, NULL) < 0)
368         ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGPIPE)");
369 #endif
370
371     /* we want to ignore HUPs and WINCH while we're busy processing one */
372     sigaddset(&sa.sa_mask, SIGHUP);
373     sigaddset(&sa.sa_mask, SIGWINCH);
374     sa.sa_handler = restart;
375     if (sigaction(SIGHUP, &sa, NULL) < 0)
376         ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGHUP)");
377     if (sigaction(SIGWINCH, &sa, NULL) < 0)
378         ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGWINCH)");
379 #else
380     if (!one_process) {
381         ap_signal(SIGSEGV, sig_coredump);
382 #ifdef SIGBUS
383         ap_signal(SIGBUS, sig_coredump);
384 #endif /* SIGBUS */
385 #ifdef SIGABORT
386         ap_signal(SIGABORT, sig_coredump);
387 #endif /* SIGABORT */
388 #ifdef SIGABRT
389         ap_signal(SIGABRT, sig_coredump);
390 #endif /* SIGABRT */
391 #ifdef SIGILL
392         ap_signal(SIGILL, sig_coredump);
393 #endif /* SIGILL */
394 #ifdef SIGXCPU
395         ap_signal(SIGXCPU, SIG_DFL);
396 #endif /* SIGXCPU */
397 #ifdef SIGXFSZ
398         ap_signal(SIGXFSZ, SIG_DFL);
399 #endif /* SIGXFSZ */
400     }
401
402     ap_signal(SIGTERM, sig_term);
403 #ifdef SIGHUP
404     ap_signal(SIGHUP, restart);
405 #endif /* SIGHUP */
406 #ifdef SIGWINCH
407     ap_signal(SIGWINCH, restart);
408 #endif /* SIGWINCH */
409 #ifdef SIGPIPE
410     ap_signal(SIGPIPE, SIG_IGN);
411 #endif /* SIGPIPE */
412
413 #endif
414 }
415
416 /*****************************************************************
417  * Here follows a long bunch of generic server bookkeeping stuff...
418  */
419
420 int ap_graceful_stop_signalled(void)
421 {
422     /* XXX - Does this really work? - Manoj */
423     return is_graceful;
424 }
425
426 /*****************************************************************
427  * Child process main loop.
428  */
429
430 static void process_socket(ap_pool_t *p, ap_socket_t *sock, long conn_id)
431 {
432     BUFF *conn_io;
433     conn_rec *current_conn;
434     ap_iol *iol;
435     int csd;
436     ap_status_t rv;
437
438     if ((rv = ap_get_os_sock(&csd, sock)) != APR_SUCCESS) {
439         ap_log_error(APLOG_MARK, APLOG_ERR, rv, NULL, "ap_get_os_sock");
440     }
441
442     if (csd >= FD_SETSIZE) {
443         ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, NULL,
444                      "new file descriptor %d is too large; you probably need "
445                      "to rebuild Apache with a larger FD_SETSIZE "
446                      "(currently %d)", 
447                      csd, FD_SETSIZE);
448         ap_close_socket(sock);
449         return;
450     }
451
452     ap_sock_disable_nagle(csd);
453     iol = ap_iol_attach_socket(p, sock);
454     conn_io = ap_bcreate(p, B_RDWR);
455     ap_bpush_iol(conn_io, iol);
456
457     current_conn = ap_new_apr_connection(p, ap_server_conf, conn_io, sock,
458                                          conn_id);
459
460     ap_process_connection(current_conn);
461     ap_lingering_close(current_conn);
462 }
463
464 static void *worker_thread(void *);
465
466 /* Starts a thread as long as we're below max_threads */
467 static int start_thread(void)
468 {
469     pthread_t thread;
470
471     pthread_mutex_lock(&worker_thread_count_mutex);
472     if (worker_thread_count < max_threads) {
473         if (pthread_create(&thread, &worker_thread_attr, worker_thread,
474           &worker_thread_free_ids[worker_thread_count])) {
475             ap_log_error(APLOG_MARK, APLOG_ALERT, errno, ap_server_conf,
476                          "pthread_create: unable to create worker thread");
477             /* In case system resources are maxxed out, we don't want
478                Apache running away with the CPU trying to fork over and
479                over and over again if we exit. */
480             sleep(10);
481             workers_may_exit = 1;
482             pthread_mutex_unlock(&worker_thread_count_mutex);
483             return 0;
484         }
485         else {
486             worker_thread_count++;
487         }
488     }
489     else {
490         static int reported = 0;
491         
492         if (!reported) {
493             ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, ap_server_conf,
494                          "server reached MaxThreadsPerChild setting, consider raising the"
495                          " MaxThreadsPerChild or NumServers settings");
496             reported = 1;
497         }
498         pthread_mutex_unlock(&worker_thread_count_mutex);
499         return 0;
500     }
501     pthread_mutex_unlock(&worker_thread_count_mutex);
502     return 1;
503
504 }
505 /* Sets workers_may_exit if we received a character on the pipe_of_death */
506 static void check_pipe_of_death(void)
507 {
508     pthread_mutex_lock(&pipe_of_death_mutex);
509     if (!workers_may_exit) {
510         int ret;
511         char pipe_read_char;
512         ap_ssize_t n = 1;
513
514         ret = ap_recv(listenfds[0], &pipe_read_char, &n);
515         if (ap_canonical_error(ret) == APR_EAGAIN) {
516             /* It lost the lottery. It must continue to suffer
517              * through a life of servitude. */
518         }
519         else {
520             /* It won the lottery (or something else is very
521              * wrong). Embrace death with open arms. */
522             workers_may_exit = 1;
523         }
524     }
525     pthread_mutex_unlock(&pipe_of_death_mutex);
526 }
527
528 /* idle_thread_count should be incremented before starting a worker_thread */
529
530 static void *worker_thread(void *arg)
531 {
532     ap_socket_t *csd = NULL;
533     ap_pool_t *tpool;           /* Pool for this thread           */
534     ap_pool_t *ptrans;          /* Pool for per-transaction stuff */
535     ap_socket_t *sd = NULL;
536     int srv;
537     int curr_pollfd, last_pollfd = 0;
538     int thread_just_started = 1;
539     int thread_num = *((int *) arg);
540     long conn_id = child_num * HARD_THREAD_LIMIT + thread_num;
541     ap_pollfd_t *pollset;
542     int n;
543     ap_status_t rv;
544
545     pthread_mutex_lock(&thread_pool_parent_mutex);
546     ap_create_pool(&tpool, thread_pool_parent);
547     pthread_mutex_unlock(&thread_pool_parent_mutex);
548     ap_create_pool(&ptrans, tpool);
549
550     ap_setup_poll(&pollset, num_listenfds+1, tpool);
551     for(n=0 ; n <= num_listenfds ; ++n)
552         ap_add_poll_socket(pollset, listenfds[n], APR_POLLIN);
553
554     while (!workers_may_exit) {
555         workers_may_exit |= (max_requests_per_child != 0) && (requests_this_child <= 0);
556         if (workers_may_exit) break;
557         if (!thread_just_started) {
558             pthread_mutex_lock(&idle_thread_count_mutex);
559             if (idle_thread_count < max_spare_threads) {
560                 idle_thread_count++;
561                 pthread_mutex_unlock(&idle_thread_count_mutex);
562             }
563             else {
564                 pthread_mutex_unlock(&idle_thread_count_mutex);
565                 break;
566             }
567         }
568         else {
569             thread_just_started = 0;
570         }
571         pthread_mutex_lock(&thread_accept_mutex);
572         if (workers_may_exit) {
573             pthread_mutex_unlock(&thread_accept_mutex);
574             break;
575         }
576         if ((rv = SAFE_ACCEPT(ap_lock(process_accept_mutex)))
577             != APR_SUCCESS) {
578             ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
579                          "ap_lock failed. Attempting to shutdown "
580                          "process gracefully.");
581             workers_may_exit = 1;
582         }
583
584         while (!workers_may_exit) {
585             ap_int16_t event;
586             srv = ap_poll(pollset, &n, -1);
587
588             if (srv != APR_SUCCESS) {
589                 if (ap_canonical_error(srv) == APR_EINTR) {
590                     continue;
591                 }
592
593                 /* ap_poll() will only return errors in catastrophic
594                  * circumstances. Let's try exiting gracefully, for now. */
595                 ap_log_error(APLOG_MARK, APLOG_ERR, srv, (const server_rec *)
596                              ap_server_conf, "ap_poll: (listen)");
597                 workers_may_exit = 1;
598             }
599             if (workers_may_exit) break;
600
601             ap_get_revents(&event, listenfds[0], pollset);
602             if (event & APR_POLLIN) {
603                 /* A process got a signal on the shutdown pipe. Check if we're
604                  * the lucky process to die. */
605                 check_pipe_of_death();
606                 continue;
607             }
608
609             if (num_listenfds == 1) {
610                 sd = ap_listeners->sd;
611                 goto got_fd;
612             }
613             else {
614                 /* find a listener */
615                 curr_pollfd = last_pollfd;
616                 do {
617                     curr_pollfd++;
618                     if (curr_pollfd > num_listenfds) {
619                         curr_pollfd = 1;
620                     }
621                     /* XXX: Should we check for POLLERR? */
622                     ap_get_revents(&event, listenfds[curr_pollfd], pollset);
623                     if (event & APR_POLLIN) {
624                         last_pollfd = curr_pollfd;
625                         sd = listenfds[curr_pollfd];
626                         goto got_fd;
627                     }
628                 } while (curr_pollfd != last_pollfd);
629             }
630         }
631     got_fd:
632         if (!workers_may_exit) {
633             if ((rv = ap_accept(&csd, sd, ptrans)) != APR_SUCCESS) {
634                 ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf, "ap_accept");
635             }
636             if ((rv = SAFE_ACCEPT(ap_unlock(process_accept_mutex)))
637                 != APR_SUCCESS) {
638                 ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
639                              "ap_unlock failed. Attempting to shutdown "
640                              "process gracefully.");
641                 workers_may_exit = 1;
642             }
643             pthread_mutex_unlock(&thread_accept_mutex);
644             pthread_mutex_lock(&idle_thread_count_mutex);
645             if (idle_thread_count > min_spare_threads) {
646                 idle_thread_count--;
647             }
648             else {
649                 if (!start_thread()) {
650                     idle_thread_count--;
651                 }
652             }
653             pthread_mutex_unlock(&idle_thread_count_mutex);
654             process_socket(ptrans, csd, conn_id);
655             requests_this_child--;
656         } else {
657             if ((rv = SAFE_ACCEPT(ap_unlock(process_accept_mutex)))
658                 != APR_SUCCESS) {
659                 ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
660                              "ap_unlock failed. Attempting to shutdown "
661                              "process gracefully.");
662                 workers_may_exit = 1;
663             }
664             pthread_mutex_unlock(&thread_accept_mutex);
665             pthread_mutex_lock(&idle_thread_count_mutex);
666             idle_thread_count--;
667             pthread_mutex_unlock(&idle_thread_count_mutex);
668             break;
669         }
670         ap_clear_pool(ptrans);
671     }
672
673     pthread_mutex_lock(&thread_pool_parent_mutex);
674     ap_destroy_pool(tpool);
675     pthread_mutex_unlock(&thread_pool_parent_mutex);
676     pthread_mutex_lock(&worker_thread_count_mutex);
677     worker_thread_count--;
678     worker_thread_free_ids[worker_thread_count] = thread_num;
679     if (worker_thread_count == 0) {
680         /* All the threads have exited, now finish the shutdown process
681          * by signalling the sigwait thread */
682         kill(my_pid, SIGTERM);
683     }
684     pthread_mutex_unlock(&worker_thread_count_mutex);
685
686     return NULL;
687 }
688
689 /* Set group privileges.
690  *
691  * Note that we use the username as set in the config files, rather than
692  * the lookup of to uid --- the same uid may have multiple passwd entries,
693  * with different sets of groups for each.
694  */
695
696 static int set_group_privs(uid_t uid, gid_t gid)
697 {
698     if (!geteuid()) {
699         const char *name;
700
701         /* Get username if passed as a uid */
702
703         struct passwd *ent;
704
705         if ((ent = getpwuid(uid)) == NULL) {
706             ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL,
707                      "getpwuid: couldn't determine user name from uid %u, "
708                      "you probably need to modify the User directive",
709                      (unsigned)uid);
710             return -1;
711         }
712
713         name = ent->pw_name;
714
715         /*
716          * Set the GID before initgroups(), since on some platforms
717          * setgid() is known to zap the group list.
718          */
719         if (setgid(gid) == -1) {
720             ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL,
721                         "setgid: unable to set group id to Group %u",
722                         (unsigned)gid);
723             return -1;
724         }
725
726         /* Reset `groups' attributes. */
727
728         if (initgroups(name, gid) == -1) {
729             ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL,
730                         "initgroups: unable to set groups for User %s "
731                         "and Group %u", name, (unsigned)gid);
732             return -1;
733         }
734     }
735     return 0;
736 }
737
738
739 static int perchild_setup_child(int childnum)
740 {
741     child_info_t *ug = &child_info_table[childnum];
742
743     if (ug->uid == -1 && ug->gid == -1) {
744         return unixd_setup_child();
745     }
746     if (set_group_privs(ug->uid, ug->gid)) {
747         return -1;
748     }
749     /* Only try to switch if we're running as root */
750     if (!geteuid() && (
751 #ifdef _OSD_POSIX
752         os_init_job_environment(server_conf, unixd_config.user_name, one_process) != 0 ||
753 #endif
754         setuid(ug->uid) == -1)) {
755         ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL,
756                     "setuid: unable to change to uid: %ld",
757                     (long) ug->uid);
758         return -1;
759     }
760     return 0;
761 }
762
763 static int create_child_socket(int child_num, ap_pool_t *p)
764 {
765     struct sockaddr_un unix_addr;
766     mode_t omask;
767     int rc;
768     int sd;
769     perchild_server_conf *sconf = (perchild_server_conf *)
770               ap_get_module_config(ap_server_conf->module_config, &mpm_perchild_module);
771     char *socket_name = ap_palloc(p, strlen(sconf->sockname) + 6);
772
773     ap_snprintf(socket_name, strlen(socket_name), "%s.%d", sconf->sockname, child_num);
774     if (unlink(socket_name) < 0 &&
775         errno != ENOENT) {
776         ap_log_error(APLOG_MARK, APLOG_ERR, errno, ap_server_conf,
777                      "Couldn't unlink unix domain socket %s",
778                      socket_name);
779         /* Just a warning; don't bail out */
780     }
781
782     if ((sd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
783         ap_log_error(APLOG_MARK, APLOG_ERR, errno, ap_server_conf,
784                      "Couldn't create unix domain socket");
785         return -1;
786     }
787
788     memset(&unix_addr, 0, sizeof(unix_addr));
789     unix_addr.sun_family = AF_UNIX;
790     strcpy(unix_addr.sun_path, socket_name);
791
792     omask = umask(0077); /* so that only Apache can use socket */
793     rc = bind(sd, (struct sockaddr *)&unix_addr, sizeof(unix_addr));
794     umask(omask); /* can't fail, so can't clobber errno */
795     if (rc < 0) {
796         ap_log_error(APLOG_MARK, APLOG_ERR, errno, ap_server_conf,
797                      "Couldn't bind unix domain socket %s",
798                      socket_name);
799         return -1;
800     }
801
802     if (listen(sd, DEFAULT_PERCHILD_LISTENBACKLOG) < 0) {
803         ap_log_error(APLOG_MARK, APLOG_ERR, errno, ap_server_conf,
804                      "Couldn't listen on unix domain socket");
805         return -1;
806     }
807
808     if (!geteuid()) {
809         if (chown(socket_name, unixd_config.user_id, -1) < 0) {
810             ap_log_error(APLOG_MARK, APLOG_ERR, errno, ap_server_conf,
811                          "Couldn't change owner of unix domain socket %s",
812                          socket_name);
813             return -1;
814         }
815     }
816     return sd;
817 }
818
819 static void child_main(int child_num_arg)
820 {
821     sigset_t sig_mask;
822     int signal_received;
823     int i;
824     ap_listen_rec *lr;
825     ap_status_t rv;
826     int sd;
827
828     my_pid = getpid();
829     child_num = child_num_arg;
830     ap_create_pool(&pchild, pconf);
831
832     /*stuff to do before we switch id's, so we have permissions.*/
833
834     rv = SAFE_ACCEPT(ap_child_init_lock(&process_accept_mutex, lock_fname,
835                                         pchild));
836     if (rv != APR_SUCCESS) {
837         ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
838                      "Couldn't initialize cross-process lock in child");
839         clean_child_exit(APEXIT_CHILDFATAL);
840     }
841
842     /* Add the sockets for this child process's virtual hosts */
843     sd = create_child_socket(child_num, pchild);
844
845     if (perchild_setup_child(child_num)) {
846         clean_child_exit(APEXIT_CHILDFATAL);
847     }
848
849     ap_child_init_hook(pchild, ap_server_conf);
850
851     /*done with init critical section */
852
853     /* All threads should mask signals out, accoring to sigwait(2) man page */
854     sigfillset(&sig_mask);
855
856 #ifdef SIGPROCMASK_SETS_THREAD_MASK
857     if (sigprocmask(SIG_SETMASK, &sig_mask, NULL) != 0) {
858         ap_log_error(APLOG_MARK, APLOG_ALERT, errno, ap_server_conf, "sigprocmask");
859     }
860 #else
861     if (pthread_sigmask(SIG_SETMASK, &sig_mask, NULL) != 0) {
862         ap_log_error(APLOG_MARK, APLOG_ALERT, errno, ap_server_conf,
863                      "pthread_sigmask");
864     }
865 #endif
866
867     requests_this_child = max_requests_per_child;
868     
869     /* Set up the pollfd array, num_listenfds + 1 for the pipe and 1 for
870      * the child socket.
871      */
872     listenfds = ap_pcalloc(pchild, sizeof(*listenfds) * (num_listenfds + 2));
873 #if APR_FILES_AS_SOCKETS
874     ap_socket_from_file(&listenfds[0], pipe_of_death_in);
875 #endif
876     for (lr = ap_listeners, i = 1; i <= num_listenfds; lr = lr->next, ++i)
877         listenfds[i]=lr->sd;
878
879     /* Setup worker threads */
880
881     if (threads_to_start > max_threads) {
882         threads_to_start = max_threads;
883     }
884     idle_thread_count = threads_to_start;
885     worker_thread_count = 0;
886     for (i = 0; i < max_threads; i++) {
887         worker_thread_free_ids[i] = i;
888     }
889     ap_create_pool(&thread_pool_parent, pchild);
890     pthread_mutex_init(&thread_pool_parent_mutex, NULL);
891     pthread_mutex_init(&idle_thread_count_mutex, NULL);
892     pthread_mutex_init(&worker_thread_count_mutex, NULL);
893     pthread_mutex_init(&pipe_of_death_mutex, NULL);
894     pthread_attr_init(&worker_thread_attr);
895 #ifdef PTHREAD_ATTR_SETDETACHSTATE_ARG2_ADDR
896     {
897         int on = 1;
898
899         pthread_attr_setdetachstate(&worker_thread_attr, &on);
900     }
901 #else
902     pthread_attr_setdetachstate(&worker_thread_attr, PTHREAD_CREATE_DETACHED);
903 #endif
904
905     /* We are creating worker threads right now */
906     for (i=0; i < threads_to_start; i++) {
907         /* start_thread shouldn't fail here */
908         if (!start_thread()) {
909             break;
910         }
911     }
912
913     /* This thread will be the one responsible for handling signals */
914     sigemptyset(&sig_mask);
915     sigaddset(&sig_mask, SIGTERM);
916     sigaddset(&sig_mask, SIGINT);
917     ap_sigwait(&sig_mask, &signal_received);
918     switch (signal_received) {
919         case SIGTERM:
920         case SIGINT:
921             just_die(signal_received);
922             break;
923         default:
924             ap_log_error(APLOG_MARK, APLOG_ALERT, errno, ap_server_conf,
925             "received impossible signal: %d", signal_received);
926             just_die(SIGTERM);
927     }
928 }
929
930 static int make_child(server_rec *s, int slot, time_t now)
931 {
932     int pid;
933
934     if (slot + 1 > ap_max_daemons_limit) {
935         ap_max_daemons_limit = slot + 1;
936     }
937
938     if (one_process) {
939         set_signals();
940         ap_child_table[slot].pid = getpid();
941         ap_child_table[slot].status = SERVER_ALIVE;
942         child_main(slot);
943     }
944
945     if ((pid = fork()) == -1) {
946         ap_log_error(APLOG_MARK, APLOG_ERR, errno, s,
947                      "fork: Unable to fork new process");
948         /* In case system resources are maxxed out, we don't want
949            Apache running away with the CPU trying to fork over and
950            over and over again. */
951         sleep(10);
952
953         return -1;
954     }
955
956     if (!pid) {
957 #ifdef AIX_BIND_PROCESSOR
958       /* By default, AIX binds to a single processor.  This bit unbinds
959          children which will then bind to another CPU.
960       */
961 #include <sys/processor.h>
962         int status = bindprocessor(BINDPROCESS, (int)getpid(),
963                                PROCESSOR_CLASS_ANY);
964         if (status != OK)
965             ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, errno, 
966                          ap_server_conf, "processor unbind failed %d", status);
967 #endif
968
969         RAISE_SIGSTOP(MAKE_CHILD);
970
971         /* XXX - For an unthreaded server, a signal handler will be necessary
972         ap_signal(SIGTERM, just_die);
973         */
974         child_main(slot);
975
976         return 0;
977     }
978     /* else */
979     ap_child_table[slot].pid = pid;
980     ap_child_table[slot].status = SERVER_ALIVE;
981
982     return 0;
983 }
984
985 /* start up a bunch of children */
986 static int startup_children(int number_to_start)
987 {
988     int i;
989
990     for (i = 0; number_to_start && i < num_daemons; ++i) {
991         if (ap_child_table[i].pid) {
992             continue;
993         }
994         if (make_child(ap_server_conf, i, 0) < 0) {
995             break;
996         }
997         --number_to_start;
998     }
999     return number_to_start;
1000 }
1001
1002
1003 /*
1004  * spawn_rate is the number of children that will be spawned on the
1005  * next maintenance cycle if there aren't enough servers.  It is
1006  * doubled up to MAX_SPAWN_RATE, and reset only when a cycle goes by
1007  * without the need to spawn.
1008  */
1009 static int spawn_rate = 1;
1010 #ifndef MAX_SPAWN_RATE
1011 #define MAX_SPAWN_RATE  (32)
1012 #endif
1013 static int hold_off_on_exponential_spawning;
1014
1015 static void perform_child_maintenance(void)
1016 {
1017     int i;
1018     time_t now = 0;
1019     int free_length;
1020     int free_slots[MAX_SPAWN_RATE];
1021     int last_non_dead = -1;
1022
1023     /* initialize the free_list */
1024     free_length = 0;
1025     
1026     for (i = 0; i < num_daemons; ++i) {
1027         if (ap_child_table[i].pid == 0) {
1028             if (free_length < spawn_rate) {
1029                 free_slots[free_length] = i;
1030                 ++free_length;
1031             }
1032         }
1033         else {
1034             last_non_dead = i;
1035         }
1036
1037         if (i >= ap_max_daemons_limit && free_length >= spawn_rate) {
1038             break;
1039         }
1040     }
1041     ap_max_daemons_limit = last_non_dead + 1;
1042
1043     if (free_length > 0) {
1044         for (i = 0; i < free_length; ++i) {
1045             make_child(ap_server_conf, free_slots[i], now);
1046         }
1047         /* the next time around we want to spawn twice as many if this
1048          * wasn't good enough, but not if we've just done a graceful
1049          */
1050         if (hold_off_on_exponential_spawning) {
1051             --hold_off_on_exponential_spawning;
1052         }
1053         else if (spawn_rate < MAX_SPAWN_RATE) {
1054             spawn_rate *= 2;
1055         }
1056     }
1057     else {
1058         spawn_rate = 1;
1059     }
1060 }
1061
1062 static void server_main_loop(int remaining_children_to_start)
1063 {
1064     int child_slot;
1065     ap_wait_t status;
1066     ap_proc_t pid;
1067     int i;
1068
1069     while (!restart_pending && !shutdown_pending) {
1070         ap_wait_or_timeout(&status, &pid, pconf);
1071         
1072         if (pid.pid != -1) {
1073             ap_process_child_status(&pid, status);
1074             /* non-fatal death... note that it's gone in the child table and
1075              * clean out the status table. */
1076             child_slot = -1;
1077             for (i = 0; i < ap_max_daemons_limit; ++i) {
1078                 if (ap_child_table[i].pid == pid.pid) {
1079                     int j;
1080
1081                     child_slot = i;
1082                     for (j = 0; j < HARD_THREAD_LIMIT; j++) {
1083                         ap_perchild_force_reset_connection_status(i * HARD_THREAD_LIMIT + j);
1084                     }
1085                     break;
1086                 }
1087             }
1088             if (child_slot >= 0) {
1089                 ap_child_table[child_slot].pid = 0;
1090                 
1091                 if (remaining_children_to_start
1092                     && child_slot < num_daemons) {
1093                     /* we're still doing a 1-for-1 replacement of dead
1094                      * children with new children
1095                      */
1096                     make_child(ap_server_conf, child_slot, time(NULL));
1097                     --remaining_children_to_start;
1098                 }
1099 #if APR_HAS_OTHER_CHILD
1100             }
1101             else if (ap_reap_other_child(&pid, status) == 0) {
1102                 /* handled */
1103 #endif
1104             }
1105             else if (is_graceful) {
1106                 /* Great, we've probably just lost a slot in the
1107                  * child table.  Somehow we don't know about this
1108                  * child.
1109                  */
1110                 ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, 
1111                              ap_server_conf,
1112                             "long lost child came home! (pid %ld)", 
1113                              (long)pid.pid);
1114             }
1115             /* Don't perform idle maintenance when a child dies,
1116              * only do it when there's a timeout.  Remember only a
1117              * finite number of children can die, and it's pretty
1118              * pathological for a lot to die suddenly.
1119              */
1120             continue;
1121         }
1122         else if (remaining_children_to_start) {
1123             /* we hit a 1 second timeout in which none of the previous
1124              * generation of children needed to be reaped... so assume
1125              * they're all done, and pick up the slack if any is left.
1126              */
1127             remaining_children_to_start = \
1128                 startup_children(remaining_children_to_start);
1129             /* In any event we really shouldn't do the code below because
1130              * few of the servers we just started are in the IDLE state
1131              * yet, so we'd mistakenly create an extra server.
1132              */
1133             continue;
1134         }
1135
1136         perform_child_maintenance();
1137     }
1138 }
1139
1140 int ap_mpm_run(ap_pool_t *_pconf, ap_pool_t *plog, server_rec *s)
1141 {
1142     int remaining_children_to_start;
1143     int i;
1144     ap_status_t rv;
1145     ap_ssize_t one = 1;
1146
1147     pconf = _pconf;
1148     ap_server_conf = s;
1149     if ((rv = ap_create_pipe(&pipe_of_death_in, &pipe_of_death_out, pconf)) 
1150         != APR_SUCCESS) {
1151         ap_log_error(APLOG_MARK, APLOG_ERR, rv,
1152                      (const server_rec*) ap_server_conf,
1153                      "ap_create_pipe (pipe_of_death)");
1154         exit(1);
1155     }
1156     if ((rv = ap_set_pipe_timeout(pipe_of_death_in, 0)) != APR_SUCCESS) {
1157         ap_log_error(APLOG_MARK, APLOG_ERR, rv,
1158                      (const server_rec*) ap_server_conf,
1159                      "ap_set_pipe_timeout (pipe_of_death)");
1160         exit(1);
1161     }
1162     ap_server_conf = s;
1163     if ((num_listenfds = ap_setup_listeners(ap_server_conf)) < 1) {
1164         /* XXX: hey, what's the right way for the mpm to indicate a fatal error? */
1165         ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ALERT, 0, s,
1166             "no listening sockets available, shutting down");
1167         return 1;
1168     }
1169     ap_log_pid(pconf, ap_pid_fname);
1170
1171     /* Initialize cross-process accept lock */
1172     lock_fname = ap_psprintf(_pconf, "%s.%u",
1173                              ap_server_root_relative(_pconf, lock_fname),
1174                              my_pid);
1175     rv = SAFE_ACCEPT(ap_create_lock(&process_accept_mutex, APR_MUTEX,
1176                                     APR_CROSS_PROCESS, lock_fname, _pconf));
1177     if (rv != APR_SUCCESS) {
1178         ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s,
1179                      "Couldn't create cross-process lock");
1180         return 1;
1181     }
1182
1183     if (!is_graceful) {
1184         reinit_scoreboard(pconf);
1185     }
1186     /* Initialize the child table */
1187     if (!is_graceful) {
1188         for (i = 0; i < HARD_SERVER_LIMIT; i++) {
1189             ap_child_table[i].pid = 0;
1190         }
1191     }
1192
1193     set_signals();
1194
1195     /* If we're doing a graceful_restart then we're going to see a lot
1196      * of children exiting immediately when we get into the main loop
1197      * below (because we just sent them SIGWINCH).  This happens pretty
1198      * rapidly... and for each one that exits we'll start a new one until
1199      * we reach at least daemons_min_free.  But we may be permitted to
1200      * start more than that, so we'll just keep track of how many we're
1201      * supposed to start up without the 1 second penalty between each fork.
1202      */
1203     remaining_children_to_start = num_daemons;
1204     if (!is_graceful) {
1205         remaining_children_to_start = \
1206             startup_children(remaining_children_to_start);
1207     }
1208     else {
1209         /* give the system some time to recover before kicking into
1210             * exponential mode */
1211         hold_off_on_exponential_spawning = 10;
1212     }
1213
1214     ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, ap_server_conf,
1215                 "%s configured -- resuming normal operations",
1216                 ap_get_server_version());
1217     ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0, ap_server_conf,
1218                 "Server built: %s", ap_get_server_built());
1219     restart_pending = shutdown_pending = 0;
1220
1221     server_main_loop(remaining_children_to_start);
1222
1223     if (shutdown_pending) {
1224         /* Time to gracefully shut down:
1225          * Kill child processes, tell them to call child_exit, etc...
1226          */
1227         if (unixd_killpg(getpgrp(), SIGTERM) < 0) {
1228             ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
1229                          "killpg SIGTERM");
1230         }
1231         ap_reclaim_child_processes(1);          /* Start with SIGTERM */
1232     
1233         /* cleanup pid file on normal shutdown */
1234         {
1235             const char *pidfile = NULL;
1236             pidfile = ap_server_root_relative (pconf, ap_pid_fname);
1237             if ( pidfile != NULL && unlink(pidfile) == 0)
1238                 ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0,
1239                          ap_server_conf,
1240                          "removed PID file %s (pid=%ld)",
1241                          pidfile, (long)getpid());
1242         }
1243     
1244         ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0,
1245                      ap_server_conf, "caught SIGTERM, shutting down");
1246     
1247         return 1;
1248     }
1249
1250     /* we've been told to restart */
1251     ap_signal(SIGHUP, SIG_IGN);
1252
1253     if (one_process) {
1254         /* not worth thinking about */
1255         return 1;
1256     }
1257
1258     if (is_graceful) {
1259         char char_of_death = '!';
1260
1261         ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, ap_server_conf,
1262                     "SIGWINCH received.  Doing graceful restart");
1263
1264         /* This is mostly for debugging... so that we know what is still
1265          * gracefully dealing with existing request.
1266          */
1267         
1268         for (i = 0; i < num_daemons; ++i) {
1269             if (ap_child_table[i].pid) {
1270                 ap_child_table[i].status = SERVER_DYING;
1271             } 
1272         }
1273         /* give the children the signal to die */
1274         for (i = 0; i < num_daemons;) {
1275             if ((rv = ap_write(pipe_of_death_out, &char_of_death, &one)) != APR_SUCCESS) {
1276                 if (ap_canonical_error(rv) == APR_EINTR) continue;
1277                 ap_log_error(APLOG_MARK, APLOG_WARNING, rv, ap_server_conf,
1278                              "write pipe_of_death");
1279             }
1280             i++;
1281         }
1282     }
1283     else {
1284       /* Kill 'em all.  Since the child acts the same on the parents SIGTERM 
1285        * and a SIGHUP, we may as well use the same signal, because some user
1286        * pthreads are stealing signals from us left and right.
1287        */
1288         if (unixd_killpg(getpgrp(), SIGTERM) < 0) {
1289             ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
1290                          "killpg SIGTERM");
1291         }
1292         ap_reclaim_child_processes(1);          /* Start with SIGTERM */
1293         ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0,
1294                      ap_server_conf, "SIGHUP received.  Attempting to restart");
1295     }
1296     return 0;
1297 }
1298
1299 static void perchild_pre_config(ap_pool_t *p, ap_pool_t *plog, ap_pool_t *ptemp)
1300 {
1301     static int restart_num = 0;
1302     int i;
1303
1304     one_process = !!getenv("ONE_PROCESS");
1305
1306     /* sigh, want this only the second time around */
1307     if (restart_num++ == 1) {
1308         is_graceful = 0;
1309
1310         if (!one_process) {
1311             ap_detach();
1312         }
1313
1314         my_pid = getpid();
1315     }
1316
1317     unixd_pre_config();
1318     ap_listen_pre_config();
1319     num_daemons = DEFAULT_NUM_DAEMON;
1320     threads_to_start = DEFAULT_START_THREAD;
1321     min_spare_threads = DEFAULT_MIN_SPARE_THREAD;
1322     max_spare_threads = DEFAULT_MAX_SPARE_THREAD;
1323     max_threads = HARD_THREAD_LIMIT;
1324     ap_pid_fname = DEFAULT_PIDLOG;
1325     ap_scoreboard_fname = DEFAULT_SCOREBOARD;
1326     lock_fname = DEFAULT_LOCKFILE;
1327     max_requests_per_child = DEFAULT_MAX_REQUESTS_PER_CHILD;
1328     ap_perchild_set_maintain_connection_status(1);
1329
1330     ap_cpystrn(ap_coredump_dir, ap_server_root, sizeof(ap_coredump_dir));
1331
1332     for (i = 0; i < HARD_SERVER_LIMIT; i++) {
1333         child_info_table[i].uid = -1;
1334         child_info_table[i].gid = -1;
1335     }
1336 }
1337
1338 static int perchild_post_read(request_rec *r)
1339 {
1340     const char *hostname = ap_table_get(r->headers_in, "Host");
1341     char *process_num;
1342     int num;
1343
1344 fprintf(stderr, "In perchild_post_read\n");
1345     process_num = ap_hash_get(socket_info_table, hostname, 0);
1346     if (process_num) {
1347         num = atoi(process_num);
1348     }
1349     else {
1350         num = -1;
1351     }
1352
1353     if (num != child_num) {
1354         /* package the request and send it to another child */
1355 fprintf(stderr, "leaving DECLINED\n");
1356         return DECLINED;
1357     }
1358 fprintf(stderr, "leaving OK\n");
1359     return OK;
1360 }
1361
1362 static void perchild_hooks(void)
1363 {
1364     INIT_SIGLIST()
1365     one_process = 0;
1366
1367     ap_hook_pre_config(perchild_pre_config, NULL, NULL, AP_HOOK_MIDDLE); 
1368     /* This must be run absolutely first.  If this request isn't for this
1369      * server then we need to forward it to the proper child.  No sense
1370      * tying up this server running more post_read request hooks if it is
1371      * just going to be forwarded along.
1372      */
1373     ap_hook_post_read_request(perchild_post_read, NULL, NULL, AP_HOOK_REALLY_FIRST);
1374 }
1375
1376 static const char *set_pidfile(cmd_parms *cmd, void *dummy, const char *arg) 
1377 {
1378     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
1379     if (err != NULL) {
1380         return err;
1381     }
1382
1383     if (cmd->server->is_virtual) {
1384         return "PidFile directive not allowed in <VirtualHost>";
1385     }
1386     ap_pid_fname = arg;
1387     return NULL;
1388 }
1389
1390 static const char *set_scoreboard(cmd_parms *cmd, void *dummy, const char *arg)
1391 {
1392     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
1393     if (err != NULL) {
1394         return err;
1395     }
1396
1397     ap_scoreboard_fname = arg;
1398     return NULL;
1399 }
1400
1401 static const char *set_lockfile(cmd_parms *cmd, void *dummy, const char *arg) 
1402 {
1403     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
1404     if (err != NULL) {
1405         return err;
1406     }
1407
1408     lock_fname = arg;
1409     return NULL;
1410 }
1411 static const char *set_num_daemons (cmd_parms *cmd, void *dummy, const char *arg) 
1412 {
1413     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
1414     if (err != NULL) {
1415         return err;
1416     }
1417
1418     num_daemons = atoi(arg);
1419     if (num_daemons > HARD_SERVER_LIMIT) {
1420        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
1421                     "WARNING: NumServers of %d exceeds compile time limit "
1422                     "of %d servers,", num_daemons, HARD_SERVER_LIMIT);
1423        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
1424                     " lowering NumServers to %d.  To increase, please "
1425                     "see the", HARD_SERVER_LIMIT);
1426        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
1427                     " HARD_SERVER_LIMIT define in %s.",
1428                     AP_MPM_HARD_LIMITS_FILE);
1429        num_daemons = HARD_SERVER_LIMIT;
1430     } 
1431     else if (num_daemons < 1) {
1432         ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
1433                      "WARNING: Require NumServers > 0, setting to 1");
1434         num_daemons = 1;
1435     }
1436     return NULL;
1437 }
1438
1439 static const char *set_threads_to_start (cmd_parms *cmd, void *dummy, const char *arg) 
1440 {
1441     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
1442     if (err != NULL) {
1443         return err;
1444     }
1445
1446     threads_to_start = atoi(arg);
1447     if (threads_to_start > HARD_THREAD_LIMIT) {
1448         ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
1449                      "WARNING: StartThreads of %d exceeds compile time"
1450                      " limit of %d threads,", threads_to_start,
1451                      HARD_THREAD_LIMIT);
1452         ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
1453                      " lowering StartThreads to %d. To increase, please"
1454                      " see the", HARD_THREAD_LIMIT);
1455         ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
1456                      " HARD_THREAD_LIMIT define in %s.",
1457                      AP_MPM_HARD_LIMITS_FILE);
1458     }
1459     else if (threads_to_start < 1) {
1460         ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
1461                      "WARNING: Require StartThreads > 0, setting to 1");
1462         threads_to_start = 1;
1463     }
1464     return NULL;
1465 }
1466
1467 static const char *set_min_spare_threads(cmd_parms *cmd, void *dummy, const char *arg)
1468 {
1469     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
1470     if (err != NULL) {
1471         return err;
1472     }
1473
1474     min_spare_threads = atoi(arg);
1475     if (min_spare_threads <= 0) {
1476        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
1477                     "WARNING: detected MinSpareThreads set to non-positive.");
1478        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
1479                     "Resetting to 1 to avoid almost certain Apache failure.");
1480        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
1481                     "Please read the documentation.");
1482        min_spare_threads = 1;
1483     }
1484        
1485     return NULL;
1486 }
1487
1488 static const char *set_max_spare_threads(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     max_spare_threads = atoi(arg);
1496     if (max_spare_threads >= HARD_THREAD_LIMIT) {
1497        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
1498                     "WARNING: detected MinSpareThreads set higher than");
1499        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
1500                     "HARD_THREAD_LIMIT. Resetting to %d", HARD_THREAD_LIMIT);
1501        max_spare_threads = HARD_THREAD_LIMIT;
1502     }
1503     return NULL;
1504 }
1505
1506 static const char *set_max_threads(cmd_parms *cmd, void *dummy, const char *arg)
1507 {
1508     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
1509     if (err != NULL) {
1510         return err;
1511     }
1512
1513     max_threads = atoi(arg);
1514     if (max_threads > HARD_THREAD_LIMIT) {
1515        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
1516                     "WARNING: detected MaxThreadsPerChild set higher than");
1517        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
1518                     "HARD_THREAD_LIMIT. Resetting to %d", HARD_THREAD_LIMIT);
1519        max_threads = HARD_THREAD_LIMIT;
1520     }
1521     return NULL;
1522 }
1523
1524 static const char *set_max_requests(cmd_parms *cmd, void *dummy, const char *arg) 
1525 {
1526     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
1527     if (err != NULL) {
1528         return err;
1529     }
1530
1531     max_requests_per_child = atoi(arg);
1532
1533     return NULL;
1534 }
1535
1536 static const char *set_maintain_connection_status(cmd_parms *cmd,
1537                                                   void *dummy, int arg) 
1538 {
1539     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
1540     if (err != NULL) {
1541         return err;
1542     }
1543
1544     ap_perchild_set_maintain_connection_status(arg != 0);
1545     return NULL;
1546 }
1547
1548 static const char *set_coredumpdir (cmd_parms *cmd, void *dummy, const char *arg) 
1549 {
1550     ap_finfo_t finfo;
1551     const char *fname;
1552     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
1553     if (err != NULL) {
1554         return err;
1555     }
1556
1557     fname = ap_server_root_relative(cmd->pool, arg);
1558     if ((ap_stat(&finfo, fname, cmd->pool) != APR_SUCCESS) || 
1559         (finfo.filetype != APR_DIR)) {
1560         return ap_pstrcat(cmd->pool, "CoreDumpDirectory ", fname, 
1561                           " does not exist or is not a directory", NULL);
1562     }
1563     ap_cpystrn(ap_coredump_dir, fname, sizeof(ap_coredump_dir));
1564     return NULL;
1565 }
1566
1567 static const char *set_childprocess(cmd_parms *cmd, void *dummy, const char *p,
1568                                     const char *u, const char *g) 
1569 {
1570     int curr_child_num = atoi(p);
1571     child_info_t *ug = &child_info_table[curr_child_num - 1];
1572
1573     if (curr_child_num > num_daemons) {
1574         return "Trying to use more child ID's than NumServers.  Increase "
1575                "NumServers in your config file.";
1576     }
1577    
1578     ug->uid = atoi(u);
1579     ug->gid = atoi(g); 
1580
1581     return NULL;
1582 }
1583
1584 static const char *set_socket_name(cmd_parms *cmd, void *dummy, const char *arg)
1585 {
1586     server_rec *s = cmd->server;
1587     perchild_server_conf *conf = (perchild_server_conf *) 
1588                   ap_get_module_config(s->module_config, &mpm_perchild_module);
1589
1590     conf->sockname = ap_server_root_relative(cmd->pool, arg);
1591     return NULL;
1592 }
1593     
1594 static ap_status_t cleanup_hash(void *dptr)
1595 {
1596     socket_info_table = NULL;
1597     return APR_SUCCESS;
1598 }
1599
1600 static const char *assign_childprocess(cmd_parms *cmd, void *dummy, const char *p)
1601 {
1602     if (socket_info_table == NULL) {
1603         socket_info_table = ap_make_hash(cmd->pool);
1604         ap_register_cleanup(cmd->pool, socket_info_table, cleanup_hash, NULL);
1605     }
1606     ap_hash_set(socket_info_table, cmd->server->server_hostname, 0, p);
1607     return NULL;
1608 }
1609
1610
1611 static const command_rec perchild_cmds[] = {
1612 UNIX_DAEMON_COMMANDS
1613 LISTEN_COMMANDS
1614 AP_INIT_TAKE1("PidFile", set_pidfile, NULL, RSRC_CONF,
1615               "A file for logging the server process ID"),
1616 AP_INIT_TAKE1("ScoreBoardFile", set_scoreboard, NULL, RSRC_CONF,
1617               "A file for Apache to maintain runtime process management information"),
1618 AP_INIT_TAKE1("LockFile", set_lockfile, NULL, RSRC_CONF,
1619               "The lockfile used when Apache needs to lock the accept() call"),
1620 AP_INIT_TAKE1("NumServers", set_num_daemons, NULL, RSRC_CONF,
1621               "Number of children alive at the same time"),
1622 AP_INIT_TAKE1("StartThreads", set_threads_to_start, NULL, RSRC_CONF,
1623               "Number of threads each child creates"),
1624 AP_INIT_TAKE1("MinSpareThreads", set_min_spare_threads, NULL, RSRC_CONF,
1625               "Minimum number of idle threads per child, to handle request spikes"),
1626 AP_INIT_TAKE1("MaxSpareThreads", set_max_spare_threads, NULL, RSRC_CONF,
1627               "Maximum number of idle threads per child"),
1628 AP_INIT_TAKE1("MaxThreadsPerChild", set_max_threads, NULL, RSRC_CONF,
1629               "Maximum number of threads per child"),
1630 AP_INIT_TAKE1("MaxRequestsPerChild", set_max_requests, NULL, RSRC_CONF,
1631               "Maximum number of requests a particular child serves before dying."),
1632 AP_INIT_FLAG("ConnectionStatus", set_maintain_connection_status, NULL, RSRC_CONF,
1633              "Whether or not to maintain status information on current connections"),
1634 AP_INIT_TAKE1("CoreDumpDirectory", set_coredumpdir, NULL, RSRC_CONF,
1635               "The location of the directory Apache changes to before dumping core"),
1636 AP_INIT_TAKE3("ChildProcess", set_childprocess, NULL, RSRC_CONF,
1637               "Specify a User and Group for a specific child process."),
1638 AP_INIT_TAKE1("AssignChild", assign_childprocess, NULL, RSRC_CONF,
1639               "Tie a virtual host to a specific child process."),
1640 AP_INIT_TAKE1("ChildSockName", set_socket_name, NULL, RSRC_CONF,
1641               "the base name of the socket to use for communication between "
1642               "child processes.  The actual socket will be "
1643               "basename.childnum"),
1644 { NULL }
1645 };
1646
1647 static void *perchild_create_config(ap_pool_t *p, server_rec *s)
1648 {
1649     perchild_server_conf *c =
1650     (perchild_server_conf *) ap_pcalloc(p, sizeof(perchild_server_conf));
1651
1652     c->sockname = ap_server_root_relative(p, DEFAULT_PERCHILD_SOCKET);
1653     return c;
1654 }
1655
1656 module MODULE_VAR_EXPORT mpm_perchild_module = {
1657     MPM20_MODULE_STUFF,
1658     NULL,                       /* hook to run before apache parses args */
1659     NULL,                       /* create per-directory config structure */
1660     NULL,                       /* merge per-directory config structures */
1661     perchild_create_config,     /* create per-server config structure */
1662     NULL,                       /* merge per-server config structures */
1663     perchild_cmds,              /* command ap_table_t */
1664     NULL,                       /* handlers */
1665     perchild_hooks              /* register_hooks */
1666 };
1667