]> granicus.if.org Git - apache/blob - server/mpm/experimental/perchild/perchild.c
switch to APR 1.0 API (which is still in flux)
[apache] / server / mpm / experimental / perchild / perchild.c
1 /* ====================================================================
2  * The Apache Software License, Version 1.1
3  *
4  * Copyright (c) 2000-2003 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 #include "apr_hash.h"
60 #include "apr_strings.h"
61 #include "apr_pools.h"
62 #include "apr_portable.h"
63 #include "apr_file_io.h"
64 #include "apr_signal.h"
65
66 #define APR_WANT_IOVEC
67 #include "apr_want.h"
68
69 #if APR_HAVE_UNISTD_H
70 #include <unistd.h>
71 #endif
72 #if APR_HAVE_SYS_SOCKET_H
73 #include <sys/socket.h>
74 #endif
75
76 #if !APR_HAS_THREADS
77 #error The perchild MPM requires APR threads, but they are unavailable.
78 #endif  
79
80 #define CORE_PRIVATE 
81  
82 #include "ap_config.h"
83 #include "httpd.h" 
84 #include "http_main.h" 
85 #include "http_log.h" 
86 #include "http_config.h"    /* for read_config */ 
87 #include "http_core.h"      /* for get_remote_host */ 
88 #include "http_protocol.h"
89 #include "http_connection.h"
90 #include "ap_mpm.h"
91 #include "unixd.h"
92 #include "mpm_common.h"
93 #include "ap_listen.h"
94 #include "mpm_default.h"
95 #include "mpm.h"
96 #include "scoreboard.h"
97 #include "util_filter.h"
98 #include "apr_poll.h"
99
100 #ifdef HAVE_POLL_H
101 #include <poll.h>
102 #endif
103 #ifdef HAVE_SYS_POLL_H
104 #include <sys/poll.h>
105 #endif
106
107 /* ### should be APR-ized */
108 #include <grp.h>
109 #include <pwd.h>
110 #include <sys/stat.h>
111 #include <sys/un.h>
112 #include <setjmp.h>
113 #ifdef HAVE_SYS_PROCESSOR_H
114 #include <sys/processor.h> /* for bindprocessor() */
115 #endif
116
117 /*
118  * Define some magic numbers that we use for the state of the incomming
119  * request. These must be < 0 so they don't collide with a file descriptor.
120  */
121 #define AP_PERCHILD_THISCHILD -1
122 #define AP_PERCHILD_OTHERCHILD -2
123
124 /* Limit on the threads per process.  Clients will be locked out if more than
125  * this * server_limit are needed.
126  *
127  * We keep this for one reason it keeps the size of the scoreboard file small
128  * enough that we can read the whole thing without worrying too much about
129  * the overhead.
130  */
131 #ifndef DEFAULT_THREAD_LIMIT
132 #define DEFAULT_THREAD_LIMIT 64 
133 #endif
134
135 /* Admin can't tune ThreadLimit beyond MAX_THREAD_LIMIT.  We want
136  * some sort of compile-time limit to help catch typos.
137  */
138 #ifndef MAX_THREAD_LIMIT
139 #define MAX_THREAD_LIMIT 20000
140 #endif 
141
142 /* Limit on the total --- clients will be locked out if more servers than
143  * this are needed.  It is intended solely to keep the server from crashing
144  * when things get out of hand.
145  *
146  * We keep a hard maximum number of servers, for two reasons --- first off,
147  * in case something goes seriously wrong, we want to stop the fork bomb
148  * short of actually crashing the machine we're running on by filling some
149  * kernel table.  Secondly, it keeps the size of the scoreboard file small
150  * enough that we can read the whole thing without worrying too much about
151  * the overhead.
152  */
153 #ifndef DEFAULT_SERVER_LIMIT
154 #define DEFAULT_SERVER_LIMIT 8 
155 #endif
156
157 /* Admin can't tune ServerLimit beyond MAX_SERVER_LIMIT.  We want
158  * some sort of compile-time limit to help catch typos.
159  */
160 #ifndef MAX_SERVER_LIMIT
161 #define MAX_SERVER_LIMIT 20000
162 #endif
163
164 /*
165  * Actual definitions of config globals
166  */
167
168 static int threads_to_start = 0;         /* Worker threads per child */
169 static int min_spare_threads = 0;
170 static int max_spare_threads = 0;
171 static int max_threads = 0;
172 static int server_limit = DEFAULT_SERVER_LIMIT;
173 static int first_server_limit;
174 static int thread_limit = DEFAULT_THREAD_LIMIT;
175 static int first_thread_limit;
176 static int changed_limit_at_restart;
177 static int num_daemons = 0;
178 static int curr_child_num = 0;
179 static int workers_may_exit = 0;
180 static int requests_this_child;
181 static int num_listensocks = 0;
182 static ap_pod_t *pod;
183 static jmp_buf jmpbuffer;
184
185 struct child_info_t {
186     uid_t uid;
187     gid_t gid;
188     int input;       /* The socket descriptor */
189     int output;      /* The socket descriptor */
190 };
191
192 typedef struct {
193     const char *sockname;       /* The base name for the socket */
194     const char *fullsockname;   /* socket base name + extension */
195     int        input;           /* The socket descriptor */
196     int        output;          /* The socket descriptor */
197 } perchild_server_conf;
198
199 typedef struct child_info_t child_info_t;
200
201 /* Tables used to determine the user and group each child process should
202  * run as.  The hash table is used to correlate a server name with a child
203  * process.
204  */
205 static child_info_t *child_info_table;
206 static int          *thread_socket_table;
207 struct ap_ctable    *ap_child_table;
208
209 /*
210  * The max child slot ever assigned, preserved across restarts.  Necessary
211  * to deal with NumServers changes across AP_SIG_GRACEFUL restarts.  We 
212  * use this value to optimize routines that have to scan the entire child 
213  * table.
214  *
215  * XXX - It might not be worth keeping this code in. There aren't very
216  * many child processes in this MPM.
217  */
218 int ap_max_daemons_limit = -1;
219 int ap_threads_per_child; /* XXX not part of API!  axe it! */
220
221 module AP_MODULE_DECLARE_DATA mpm_perchild_module;
222
223 static apr_file_t *pipe_of_death_in = NULL;
224 static apr_file_t *pipe_of_death_out = NULL;
225 static apr_thread_mutex_t *pipe_of_death_mutex;
226
227 /* *Non*-shared http_main globals... */
228
229 server_rec *ap_server_conf;
230
231 /* one_process --- debugging mode variable; can be set from the command line
232  * with the -X flag.  If set, this gets you the child_main loop running
233  * in the process which originally started up (no detach, no make_child),
234  * which is a pretty nice debugging environment.  (You'll get a SIGHUP
235  * early in standalone_main; just continue through.  This is the server
236  * trying to kill off any child processes which it might have lying
237  * around --- Apache doesn't keep track of their pids, it just sends
238  * SIGHUP to the process group, ignoring it in the root process.
239  * Continue through and you'll be fine.).
240  */
241
242 static int one_process = 0;
243
244 #ifdef DEBUG_SIGSTOP
245 int raise_sigstop_flags;
246 #endif
247
248 static apr_pool_t *pconf;              /* Pool for config stuff */
249 static apr_pool_t *pchild;             /* Pool for httpd child stuff */
250 static apr_pool_t *thread_pool_parent; /* Parent of per-thread pools */
251 static apr_thread_mutex_t *thread_pool_parent_mutex;
252
253 static int child_num;
254 static unsigned int my_pid; /* Linux getpid() doesn't work except in 
255                       main thread. Use this instead */
256 /* Keep track of the number of worker threads currently active */
257 static int worker_thread_count;
258 static apr_thread_mutex_t *worker_thread_count_mutex;
259 static int *worker_thread_free_ids;
260 static apr_threadattr_t *worker_thread_attr;
261
262 /* Keep track of the number of idle worker threads */
263 static int idle_thread_count;
264 static apr_thread_mutex_t *idle_thread_count_mutex;
265
266 /* Locks for accept serialization */
267 #ifdef NO_SERIALIZED_ACCEPT
268 #define SAFE_ACCEPT(stmt) APR_SUCCESS
269 #else
270 #define SAFE_ACCEPT(stmt) (stmt)
271 static apr_proc_mutex_t *process_accept_mutex;
272 #endif /* NO_SERIALIZED_ACCEPT */
273 static apr_thread_mutex_t *thread_accept_mutex;
274
275 AP_DECLARE(apr_status_t) ap_mpm_query(int query_code, int *result)
276 {
277     switch(query_code){
278         case AP_MPMQ_MAX_DAEMON_USED:
279             *result = ap_max_daemons_limit;
280             return APR_SUCCESS;
281         case AP_MPMQ_IS_THREADED:
282             *result = AP_MPMQ_DYNAMIC;
283             return APR_SUCCESS;
284         case AP_MPMQ_IS_FORKED:
285             *result = AP_MPMQ_STATIC;
286             return APR_SUCCESS;
287         case AP_MPMQ_HARD_LIMIT_DAEMONS:
288             *result = server_limit;
289             return APR_SUCCESS;
290         case AP_MPMQ_HARD_LIMIT_THREADS:
291             *result = thread_limit;
292             return APR_SUCCESS;
293         case AP_MPMQ_MAX_THREADS:
294             *result = max_threads;
295             return APR_SUCCESS;
296         case AP_MPMQ_MIN_SPARE_DAEMONS:
297             *result = 0;
298             return APR_SUCCESS;
299         case AP_MPMQ_MIN_SPARE_THREADS:    
300             *result = min_spare_threads;
301             return APR_SUCCESS;
302         case AP_MPMQ_MAX_SPARE_DAEMONS:
303             *result = 0;
304             return APR_SUCCESS;
305         case AP_MPMQ_MAX_SPARE_THREADS:
306             *result = max_spare_threads;
307             return APR_SUCCESS;
308         case AP_MPMQ_MAX_REQUESTS_DAEMON:
309             *result = ap_max_requests_per_child;
310             return APR_SUCCESS; 
311         case AP_MPMQ_MAX_DAEMONS:
312             *result = num_daemons;
313             return APR_SUCCESS;
314     }
315     return APR_ENOTIMPL;
316 }
317
318 /* a clean exit from a child with proper cleanup */
319 static void clean_child_exit(int code)
320 {
321     if (pchild) {
322         apr_pool_destroy(pchild);
323     }
324     exit(code);
325 }
326
327 static void just_die(int sig)
328 {
329     clean_child_exit(0);
330 }
331
332 /*****************************************************************
333  * Connection structures and accounting...
334  */
335
336 /* volatile just in case */
337 static int volatile shutdown_pending;
338 static int volatile restart_pending;
339 static int volatile is_graceful;
340 static int volatile child_fatal;
341 /* we don't currently track ap_my_generation, but mod_status 
342  * references it so it must be defined */
343 ap_generation_t volatile ap_my_generation=0;
344
345 /*
346  * ap_start_shutdown() and ap_start_restart(), below, are a first stab at
347  * functions to initiate shutdown or restart without relying on signals. 
348  * Previously this was initiated in sig_term() and restart() signal handlers, 
349  * but we want to be able to start a shutdown/restart from other sources --
350  * e.g. on Win32, from the service manager. Now the service manager can
351  * call ap_start_shutdown() or ap_start_restart() as appropiate.  Note that
352  * these functions can also be called by the child processes, since global
353  * variables are no longer used to pass on the required action to the parent.
354  *
355  * These should only be called from the parent process itself, since the
356  * parent process will use the shutdown_pending and restart_pending variables
357  * to determine whether to shutdown or restart. The child process should
358  * call signal_parent() directly to tell the parent to die -- this will
359  * cause neither of those variable to be set, which the parent will
360  * assume means something serious is wrong (which it will be, for the
361  * child to force an exit) and so do an exit anyway.
362  */
363
364 static void ap_start_shutdown(void)
365 {
366     if (shutdown_pending == 1) {
367         /* Um, is this _probably_ not an error, if the user has
368          * tried to do a shutdown twice quickly, so we won't
369          * worry about reporting it.
370          */
371         return;
372     }
373     shutdown_pending = 1;
374 }
375
376 /* do a graceful restart if graceful == 1 */
377 static void ap_start_restart(int graceful)
378 {
379
380     if (restart_pending == 1) {
381         /* Probably not an error - don't bother reporting it */
382         return;
383     }
384     restart_pending = 1;
385     is_graceful = graceful;
386 }
387
388 static void sig_term(int sig)
389 {
390     ap_start_shutdown();
391 }
392
393 static void restart(int sig)
394 {
395 #ifndef WIN32
396     ap_start_restart(sig == AP_SIG_GRACEFUL);
397 #else
398     ap_start_restart(1);
399 #endif
400 }
401
402 static void set_signals(void)
403 {
404 #ifndef NO_USE_SIGACTION
405     struct sigaction sa;
406 #endif
407
408     if (!one_process) {
409         ap_fatal_signal_setup(ap_server_conf, pconf);
410     }
411
412 #ifndef NO_USE_SIGACTION
413     sigemptyset(&sa.sa_mask);
414     sa.sa_flags = 0;
415
416     sa.sa_handler = sig_term;
417     if (sigaction(SIGTERM, &sa, NULL) < 0)
418         ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
419                      "sigaction(SIGTERM)");
420 #ifdef SIGINT
421     if (sigaction(SIGINT, &sa, NULL) < 0)
422         ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
423                      "sigaction(SIGINT)");
424 #endif
425 #ifdef SIGXCPU
426     sa.sa_handler = SIG_DFL;
427     if (sigaction(SIGXCPU, &sa, NULL) < 0)
428         ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
429                      "sigaction(SIGXCPU)");
430 #endif
431 #ifdef SIGXFSZ
432     sa.sa_handler = SIG_DFL;
433     if (sigaction(SIGXFSZ, &sa, NULL) < 0)
434         ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
435                      "sigaction(SIGXFSZ)");
436 #endif
437 #ifdef SIGPIPE
438     sa.sa_handler = SIG_IGN;
439     if (sigaction(SIGPIPE, &sa, NULL) < 0)
440         ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
441                      "sigaction(SIGPIPE)");
442 #endif
443
444     /* we want to ignore HUPs and AP_SIG_GRACEFUL while we're busy 
445      * processing one */
446     sigaddset(&sa.sa_mask, SIGHUP);
447     sigaddset(&sa.sa_mask, AP_SIG_GRACEFUL);
448     sa.sa_handler = restart;
449     if (sigaction(SIGHUP, &sa, NULL) < 0)
450         ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
451                      "sigaction(SIGHUP)");
452     if (sigaction(AP_SIG_GRACEFUL, &sa, NULL) < 0)
453         ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
454                      "sigaction(" AP_SIG_GRACEFUL_STRING ")");
455 #else
456     if (!one_process) {
457 #ifdef SIGXCPU
458         apr_signal(SIGXCPU, SIG_DFL);
459 #endif /* SIGXCPU */
460 #ifdef SIGXFSZ
461         apr_signal(SIGXFSZ, SIG_DFL);
462 #endif /* SIGXFSZ */
463     }
464
465     apr_signal(SIGTERM, sig_term);
466 #ifdef SIGHUP
467     apr_signal(SIGHUP, restart);
468 #endif /* SIGHUP */
469 #ifdef AP_SIG_GRACEFUL
470     apr_signal(AP_SIG_GRACEFUL, restart);
471 #endif /* AP_SIG_GRACEFUL */
472 #ifdef SIGPIPE
473     apr_signal(SIGPIPE, SIG_IGN);
474 #endif /* SIGPIPE */
475
476 #endif
477 }
478
479 /*****************************************************************
480  * Here follows a long bunch of generic server bookkeeping stuff...
481  */
482
483 int ap_graceful_stop_signalled(void)
484 {
485     /* XXX - Does this really work? - Manoj */
486     return is_graceful;
487 }
488
489 /*****************************************************************
490  * Child process main loop.
491  */
492
493 static void process_socket(apr_pool_t *p, apr_socket_t *sock, long conn_id,
494                            apr_bucket_alloc_t *bucket_alloc)
495 {
496     conn_rec *current_conn;
497     int csd;
498     apr_status_t rv;
499     int thread_num = conn_id % thread_limit;
500     ap_sb_handle_t *sbh;
501
502     if ((rv = apr_os_sock_get(&csd, sock)) != APR_SUCCESS) {
503         ap_log_error(APLOG_MARK, APLOG_ERR, rv, NULL, "apr_os_sock_get");
504     }
505
506     if (csd >= FD_SETSIZE) {
507         ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL,
508                      "new file descriptor %d is too large; you probably need "
509                      "to rebuild Apache with a larger FD_SETSIZE "
510                      "(currently %d)", 
511                      csd, FD_SETSIZE);
512         apr_socket_close(sock);
513         return;
514     }
515
516     if (thread_socket_table[thread_num] < 0) {
517         ap_sock_disable_nagle(sock);
518     }
519
520     ap_create_sb_handle(&sbh, p, conn_id / thread_limit, thread_num);
521     current_conn = ap_run_create_connection(p, ap_server_conf, sock, conn_id, 
522                                             sbh, bucket_alloc);
523     if (current_conn) {
524         ap_process_connection(current_conn, sock);
525         ap_lingering_close(current_conn);
526     }
527 }
528
529 static int perchild_process_connection(conn_rec *c)
530 {
531     ap_filter_t *f;
532     apr_bucket_brigade *bb;
533     core_net_rec *net;
534
535     apr_pool_userdata_get((void **)&bb, "PERCHILD_SOCKETS", c->pool);
536     if (bb != NULL) {
537         for (f = c->output_filters; f != NULL; f = f->next) {
538             if (!strcmp(f->frec->name, "core")) {
539                 break;
540             }
541         }
542         if (f != NULL) {
543             net = f->ctx;
544             net->in_ctx = apr_palloc(c->pool, sizeof(*net->in_ctx));
545             net->in_ctx->b = bb;
546         }
547     }
548     return DECLINED;
549 }
550     
551
552 static void *worker_thread(apr_thread_t *, void *);
553
554 /* Starts a thread as long as we're below max_threads */
555 static int start_thread(void)
556 {
557     apr_thread_t *thread;
558     int rc;
559
560     apr_thread_mutex_lock(worker_thread_count_mutex);
561     if (worker_thread_count < max_threads - 1) {
562         rc = apr_thread_create(&thread, worker_thread_attr, worker_thread,
563                  &worker_thread_free_ids[worker_thread_count], pchild);
564         if (rc != APR_SUCCESS) {
565             ap_log_error(APLOG_MARK, APLOG_ALERT, rc, ap_server_conf,
566                          "apr_thread_create: unable to create worker thread");
567             /* In case system resources are maxxed out, we don't want
568                Apache running away with the CPU trying to fork over and
569                over and over again if we exit. */
570             sleep(10);
571             workers_may_exit = 1;
572             apr_thread_mutex_unlock(worker_thread_count_mutex);
573             return 0;
574         }
575         else {
576             worker_thread_count++;
577         }
578     }
579     else {
580         static int reported = 0;
581         
582         if (!reported) {
583             ap_log_error(APLOG_MARK, APLOG_ERR, 0,
584                          ap_server_conf,
585                          "server reached MaxThreadsPerChild setting, "
586                          "consider raising the MaxThreadsPerChild or "
587                          "NumServers settings");
588             reported = 1;
589         }
590         apr_thread_mutex_unlock(worker_thread_count_mutex);
591         return 0;
592     }
593     apr_thread_mutex_unlock(worker_thread_count_mutex);
594     return 1;
595
596 }
597
598 /* Sets workers_may_exit if we received a character on the pipe_of_death */
599 static apr_status_t check_pipe_of_death(void **csd, ap_listen_rec *lr,
600                                         apr_pool_t *ptrans)
601 {
602     apr_thread_mutex_lock(pipe_of_death_mutex);
603     if (!workers_may_exit) {
604         int ret;
605         char pipe_read_char;
606         apr_size_t n = 1;
607
608         ret = apr_socket_recv(lr->sd, &pipe_read_char, &n);
609         if (APR_STATUS_IS_EAGAIN(ret)) {
610             /* It lost the lottery. It must continue to suffer
611              * through a life of servitude. */
612         }
613         else {
614             /* It won the lottery (or something else is very
615              * wrong). Embrace death with open arms. */
616             workers_may_exit = 1;
617         }
618     }
619     apr_thread_mutex_unlock(pipe_of_death_mutex);
620     return APR_SUCCESS;
621 }
622
623 static apr_status_t receive_from_other_child(void **csd, ap_listen_rec *lr,
624                                              apr_pool_t *ptrans)
625 {
626     struct msghdr msg;
627     struct cmsghdr *cmsg;
628     char buffer[HUGE_STRING_LEN * 2], *headers, *body;
629     int headerslen, bodylen;
630     struct iovec iov;
631     int ret, dp;
632     apr_os_sock_t sd;
633     apr_bucket_alloc_t *alloc = apr_bucket_alloc_create(ptrans);
634     apr_bucket_brigade *bb = apr_brigade_create(ptrans, alloc);
635     apr_bucket *bucket;
636
637     apr_os_sock_get(&sd, lr->sd);
638
639     iov.iov_base = buffer;
640     iov.iov_len = sizeof(buffer);
641
642     msg.msg_name = NULL;
643     msg.msg_namelen = 0;
644     msg.msg_iov = &iov;
645     msg.msg_iovlen = 1;
646
647     cmsg = apr_palloc(ptrans, sizeof(*cmsg) + sizeof(sd));
648     cmsg->cmsg_len = sizeof(*cmsg) + sizeof(sd);
649     msg.msg_control = cmsg;
650     msg.msg_controllen = cmsg->cmsg_len;
651
652     ret = recvmsg(sd, &msg, 0);
653
654     memcpy(&dp, CMSG_DATA(cmsg), sizeof(dp));
655
656     *csd = NULL; /* tell apr_os_sock_put() to allocate new apr_socket_t */
657     apr_os_sock_put((apr_socket_t **)csd, &dp, ptrans);
658
659     bucket = apr_bucket_eos_create(alloc);
660     APR_BRIGADE_INSERT_HEAD(bb, bucket);
661     bucket = apr_bucket_socket_create(*csd, alloc);
662     APR_BRIGADE_INSERT_HEAD(bb, bucket);
663
664     body = strchr(iov.iov_base, 0);
665     if (!body) {
666         return 1;
667     }
668
669     body++;
670     bodylen = strlen(body);
671
672     headers = iov.iov_base;
673     headerslen = body - headers;
674
675     bucket = apr_bucket_heap_create(body, bodylen, NULL, alloc);
676     APR_BRIGADE_INSERT_HEAD(bb, bucket);
677     bucket = apr_bucket_heap_create(headers, headerslen, NULL, alloc);
678     APR_BRIGADE_INSERT_HEAD(bb, bucket);
679
680     apr_pool_userdata_set(bb, "PERCHILD_SOCKETS", NULL, ptrans);
681
682     return 0;
683 }
684
685 /* idle_thread_count should be incremented before starting a worker_thread */
686
687 static void *worker_thread(apr_thread_t *thd, void *arg)
688 {
689     void *csd;
690     apr_pool_t *tpool;      /* Pool for this thread           */
691     apr_pool_t *ptrans;     /* Pool for per-transaction stuff */
692     volatile int thread_just_started = 1;
693     int srv;
694     int thread_num = *((int *) arg);
695     long conn_id = child_num * thread_limit + thread_num;
696     apr_pollfd_t *pollset;
697     apr_status_t rv;
698     ap_listen_rec *lr, *last_lr = ap_listeners;
699     int n;
700     apr_bucket_alloc_t *bucket_alloc;
701
702     apr_thread_mutex_lock(thread_pool_parent_mutex);
703     apr_pool_create(&tpool, thread_pool_parent);
704     apr_thread_mutex_unlock(thread_pool_parent_mutex);
705     apr_pool_create(&ptrans, tpool);
706
707     (void) ap_update_child_status_from_indexes(child_num, thread_num, 
708                                                SERVER_STARTING,
709                                                (request_rec *) NULL);
710
711     bucket_alloc = apr_bucket_alloc_create(apr_thread_pool_get(thd));
712
713     apr_poll_setup(&pollset, num_listensocks, tpool);
714     for(lr = ap_listeners; lr != NULL; lr = lr->next) {
715         int fd;
716         apr_poll_socket_add(pollset, lr->sd, APR_POLLIN);
717
718         apr_os_sock_get(&fd, lr->sd);
719     }
720
721     while (!workers_may_exit) {
722         workers_may_exit |= ((ap_max_requests_per_child != 0)
723                             && (requests_this_child <= 0));
724         if (workers_may_exit) break;
725         if (!thread_just_started) {
726             apr_thread_mutex_lock(idle_thread_count_mutex);
727             if (idle_thread_count < max_spare_threads) {
728                 idle_thread_count++;
729                 apr_thread_mutex_unlock(idle_thread_count_mutex);
730             }
731             else {
732                 apr_thread_mutex_unlock(idle_thread_count_mutex);
733                 break;
734             }
735         }
736         else {
737             thread_just_started = 0;
738         }
739
740         (void) ap_update_child_status_from_indexes(child_num, thread_num, 
741                                                    SERVER_READY,
742                                                    (request_rec *) NULL);
743
744         apr_thread_mutex_lock(thread_accept_mutex);
745         if (workers_may_exit) {
746             apr_thread_mutex_unlock(thread_accept_mutex);
747             break;
748         }
749         if ((rv = SAFE_ACCEPT(apr_proc_mutex_lock(process_accept_mutex)))
750             != APR_SUCCESS) {
751             ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
752                          "apr_proc_mutex_lock failed. Attempting to shutdown "
753                          "process gracefully.");
754             workers_may_exit = 1;
755         }
756
757         while (!workers_may_exit) {
758             apr_int16_t event;
759             srv = apr_poll(pollset, num_listensocks, &n, -1);
760
761             if (srv != APR_SUCCESS) {
762                 if (APR_STATUS_IS_EINTR(srv)) {
763                     continue;
764                 }
765
766                 /* apr_poll() will only return errors in catastrophic
767                  * circumstances. Let's try exiting gracefully, for now. */
768                 ap_log_error(APLOG_MARK, APLOG_ERR, srv, (const server_rec *)
769                              ap_server_conf, "apr_poll: (listen)");
770                 workers_may_exit = 1;
771             }
772             if (workers_may_exit) break;
773
774             /* find a listener */
775             lr = last_lr;
776             do {
777                 lr = lr->next;
778                 if (lr == NULL) {
779                     lr = ap_listeners;
780                 }
781                 /* XXX: Should we check for POLLERR? */
782                 apr_poll_revents_get(&event, lr->sd, pollset);
783                 if (event & (APR_POLLIN)) {
784                     last_lr = lr;
785                     goto got_fd;
786                 }
787             } while (lr != last_lr);
788         }
789     got_fd:
790         if (!workers_may_exit) {
791             rv = lr->accept_func(&csd, lr, ptrans);
792             if (rv == APR_EGENERAL) {
793                 /* E[NM]FILE, ENOMEM, etc */
794                 workers_may_exit = 1;
795             }
796             if ((rv = SAFE_ACCEPT(apr_proc_mutex_unlock(process_accept_mutex)))
797                 != APR_SUCCESS) {
798                 ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
799                              "apr_proc_mutex_unlock failed. Attempting to shutdown "
800                              "process gracefully.");
801                 workers_may_exit = 1;
802             }
803             apr_thread_mutex_unlock(thread_accept_mutex);
804             apr_thread_mutex_lock(idle_thread_count_mutex);
805             if (idle_thread_count > min_spare_threads) {
806                 idle_thread_count--;
807             }
808             else {
809                 if (!start_thread()) {
810                     idle_thread_count--;
811                 }
812             }
813             apr_thread_mutex_unlock(idle_thread_count_mutex);
814             if (setjmp(jmpbuffer) != 1) {
815                 process_socket(ptrans, csd, conn_id, bucket_alloc);
816             }
817             else {
818                 thread_socket_table[thread_num] = AP_PERCHILD_THISCHILD;
819             }  
820             requests_this_child--;
821         }
822         else {
823             if ((rv = SAFE_ACCEPT(apr_proc_mutex_unlock(process_accept_mutex)))
824                 != APR_SUCCESS) {
825                 ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
826                              "apr_proc_mutex_unlock failed. Attempting to shutdown "
827                              "process gracefully.");
828                 workers_may_exit = 1;
829             }
830             apr_thread_mutex_unlock(thread_accept_mutex);
831             apr_thread_mutex_lock(idle_thread_count_mutex);
832             idle_thread_count--;
833             apr_thread_mutex_unlock(idle_thread_count_mutex);
834         break;
835         }
836         apr_pool_clear(ptrans);
837     }
838
839     apr_thread_mutex_lock(thread_pool_parent_mutex);
840     ap_update_child_status_from_indexes(child_num, thread_num, SERVER_DEAD,
841                                         (request_rec *) NULL);
842     apr_pool_destroy(tpool);
843     apr_thread_mutex_unlock(thread_pool_parent_mutex);
844     apr_thread_mutex_lock(worker_thread_count_mutex);
845     worker_thread_count--;
846     worker_thread_free_ids[worker_thread_count] = thread_num;
847     if (worker_thread_count == 0) {
848         /* All the threads have exited, now finish the shutdown process
849          * by signalling the sigwait thread */
850         kill(my_pid, SIGTERM);
851     }
852     apr_thread_mutex_unlock(worker_thread_count_mutex);
853
854     apr_bucket_alloc_destroy(bucket_alloc);
855
856     return NULL;
857 }
858
859
860
861 /* Set group privileges.
862  *
863  * Note that we use the username as set in the config files, rather than
864  * the lookup of to uid --- the same uid may have multiple passwd entries,
865  * with different sets of groups for each.
866  */
867
868 static int set_group_privs(uid_t uid, gid_t gid)
869 {
870     if (!geteuid()) {
871         const char *name;
872
873         /* Get username if passed as a uid */
874
875         struct passwd *ent;
876
877         if ((ent = getpwuid(uid)) == NULL) {
878             ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL,
879                          "getpwuid: couldn't determine user name from uid %u, "
880                          "you probably need to modify the User directive",
881                          (unsigned)uid);
882             return -1;
883         }
884
885         name = ent->pw_name;
886
887         /*
888          * Set the GID before initgroups(), since on some platforms
889          * setgid() is known to zap the group list.
890          */
891         if (setgid(gid) == -1) {
892             ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL,
893                          "setgid: unable to set group id to Group %u",
894                          (unsigned)gid);
895             return -1;
896         }
897
898         /* Reset `groups' attributes. */
899
900         if (initgroups(name, gid) == -1) {
901             ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL,
902                          "initgroups: unable to set groups for User %s "
903                          "and Group %u", name, (unsigned)gid);
904             return -1;
905         }
906     }
907     return 0;
908 }
909
910
911 static int perchild_setup_child(int childnum)
912 {
913     child_info_t *ug = &child_info_table[childnum];
914
915     if (ug->uid == -1 && ug->gid == -1) {
916         return unixd_setup_child();
917     }
918     if (set_group_privs(ug->uid, ug->gid)) {
919         return -1;
920     }
921     /* Only try to switch if we're running as root */
922     if (!geteuid()
923         && (
924 #ifdef _OSD_POSIX
925             os_init_job_environment(server_conf, unixd_config.user_name,
926                                     one_process) != 0 ||
927 #endif
928             setuid(ug->uid) == -1)) {
929         ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL,
930                      "setuid: unable to change to uid: %ld",
931                      (long) ug->uid);
932         return -1;
933     }
934     return 0;
935 }
936
937 static int check_signal(int signum)
938 {
939     switch (signum) {
940     case SIGTERM:
941     case SIGINT:
942         just_die(signum);
943         return 1;
944     }
945     return 0;
946 }                                                                               
947
948 typedef struct perchild_header {
949     char *headers;
950     apr_pool_t *p;
951 } perchild_header;
952
953 /* Send a single HTTP header field to the client.  Note that this function
954  * is used in calls to table_do(), so their interfaces are co-dependent.
955  * In other words, don't change this one without checking table_do in alloc.c.
956  * It returns true unless there was a write error of some kind.
957  */
958 static int perchild_header_field(perchild_header *h,
959                              const char *fieldname, const char *fieldval)
960 {
961     apr_pstrcat(h->p, h->headers, fieldname, ": ", fieldval, CRLF, NULL); 
962     return 1;
963 }
964
965
966 static void child_main(int child_num_arg)
967 {
968     int i;
969     apr_status_t rv;
970     apr_socket_t *sock = NULL;
971     ap_listen_rec *lr;
972     
973     my_pid = getpid();
974     ap_fatal_signal_child_setup(ap_server_conf);
975     child_num = child_num_arg;
976     apr_pool_create(&pchild, pconf);
977
978     for (lr = ap_listeners ; lr->next != NULL; lr = lr->next) {
979         continue;
980     }
981
982     apr_os_sock_put(&sock, &child_info_table[child_num].input, pconf);
983     lr->next = apr_palloc(pconf, sizeof(*lr));
984     lr->next->sd = sock;
985     lr->next->active = 1;
986     lr->next->accept_func = receive_from_other_child;
987     lr->next->next = NULL;
988     lr = lr->next;
989     num_listensocks++;
990
991     /*stuff to do before we switch id's, so we have permissions.*/
992
993     rv = SAFE_ACCEPT(apr_proc_mutex_child_init(&process_accept_mutex, 
994                                                ap_lock_fname, pchild));
995     if (rv != APR_SUCCESS) {
996         ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
997                      "Couldn't initialize cross-process lock in child");
998         clean_child_exit(APEXIT_CHILDFATAL);
999     }
1000
1001     if (perchild_setup_child(child_num)) {
1002         clean_child_exit(APEXIT_CHILDFATAL);
1003     }
1004
1005     ap_run_child_init(pchild, ap_server_conf);
1006
1007     /*done with init critical section */
1008
1009     apr_setup_signal_thread();
1010
1011     requests_this_child = ap_max_requests_per_child;
1012     
1013
1014     /* Setup worker threads */
1015
1016     if (threads_to_start > max_threads) {
1017         threads_to_start = max_threads;
1018     }
1019     idle_thread_count = threads_to_start;
1020     worker_thread_count = 0;
1021     worker_thread_free_ids = (int *)apr_pcalloc(pchild, thread_limit * sizeof(int));
1022     for (i = 0; i < max_threads; i++) {
1023         worker_thread_free_ids[i] = i;
1024     }
1025     apr_pool_create(&thread_pool_parent, pchild);
1026     apr_thread_mutex_create(&thread_pool_parent_mutex, 
1027                     APR_THREAD_MUTEX_DEFAULT, pchild);
1028     apr_thread_mutex_create(&idle_thread_count_mutex, 
1029                     APR_THREAD_MUTEX_DEFAULT, pchild);
1030     apr_thread_mutex_create(&worker_thread_count_mutex,
1031                     APR_THREAD_MUTEX_DEFAULT, pchild);
1032     apr_thread_mutex_create(&pipe_of_death_mutex,
1033                     APR_THREAD_MUTEX_DEFAULT, pchild);
1034     apr_thread_mutex_create(&thread_accept_mutex,
1035                     APR_THREAD_MUTEX_DEFAULT, pchild);
1036
1037     apr_threadattr_create(&worker_thread_attr, pchild);
1038     apr_threadattr_detach_set(worker_thread_attr, 1);                                     
1039
1040     /* We are creating worker threads right now */
1041     for (i=0; i < threads_to_start; i++) {
1042         /* start_thread shouldn't fail here */
1043         if (!start_thread()) {
1044             break;
1045         }
1046     }
1047
1048     apr_signal_thread(check_signal);
1049 }
1050
1051 static int make_child(server_rec *s, int slot)
1052 {
1053     int pid;
1054
1055     if (slot + 1 > ap_max_daemons_limit) {
1056         ap_max_daemons_limit = slot + 1;
1057     }
1058
1059     if (one_process) {
1060         set_signals();
1061         ap_child_table[slot].pid = getpid();
1062         ap_child_table[slot].status = SERVER_ALIVE;
1063         child_main(slot);
1064     }
1065     (void) ap_update_child_status_from_indexes(slot, 0, SERVER_STARTING,
1066                                                (request_rec *) NULL);
1067
1068     if ((pid = fork()) == -1) {
1069         ap_log_error(APLOG_MARK, APLOG_ERR, errno, s,
1070                      "fork: Unable to fork new process");
1071         /* In case system resources are maxxed out, we don't want
1072          * Apache running away with the CPU trying to fork over and
1073          * over and over again. */
1074         sleep(10);
1075
1076         return -1;
1077     }
1078
1079     if (!pid) {
1080 #ifdef HAVE_BINDPROCESSOR
1081         /* By default, AIX binds to a single processor.  This bit unbinds
1082          * children which will then bind to another CPU.
1083          */
1084         int status = bindprocessor(BINDPROCESS, (int)getpid(),
1085                                    PROCESSOR_CLASS_ANY);
1086         if (status != OK) {
1087             ap_log_error(APLOG_MARK, APLOG_WARNING, errno, 
1088                          ap_server_conf, "processor unbind failed %d", status);
1089         }
1090 #endif
1091
1092         RAISE_SIGSTOP(MAKE_CHILD);
1093
1094         /* XXX - For an unthreaded server, a signal handler will be necessary
1095          * apr_signal(SIGTERM, just_die);
1096          */
1097         child_main(slot);
1098         clean_child_exit(0);
1099     }
1100     /* else */
1101     ap_child_table[slot].pid = pid;
1102     ap_child_table[slot].status = SERVER_ALIVE;
1103
1104     return 0;
1105 }
1106
1107 /* start up a bunch of children */
1108 static int startup_children(int number_to_start)
1109 {
1110     int i;
1111
1112     for (i = 0; number_to_start && i < num_daemons; ++i) {
1113         if (ap_child_table[i].pid) {
1114             continue;
1115         }
1116         if (make_child(ap_server_conf, i) < 0) {
1117             break;
1118         }
1119         --number_to_start;
1120     }
1121     return number_to_start;
1122 }
1123
1124
1125 /*
1126  * spawn_rate is the number of children that will be spawned on the
1127  * next maintenance cycle if there aren't enough servers.  It is
1128  * doubled up to MAX_SPAWN_RATE, and reset only when a cycle goes by
1129  * without the need to spawn.
1130  */
1131 static int spawn_rate = 1;
1132 #ifndef MAX_SPAWN_RATE
1133 #define MAX_SPAWN_RATE  (32)
1134 #endif
1135 static int hold_off_on_exponential_spawning;
1136
1137 static void perform_child_maintenance(void)
1138 {
1139     int i;
1140     int free_length;
1141     int free_slots[MAX_SPAWN_RATE];
1142     int last_non_dead = -1;
1143
1144     /* initialize the free_list */
1145     free_length = 0;
1146     
1147     for (i = 0; i < num_daemons; ++i) {
1148         if (ap_child_table[i].pid == 0) {
1149             if (free_length < spawn_rate) {
1150                 free_slots[free_length] = i;
1151                 ++free_length;
1152             }
1153         }
1154         else {
1155             last_non_dead = i;
1156         }
1157
1158         if (i >= ap_max_daemons_limit && free_length >= spawn_rate) {
1159             break;
1160         }
1161     }
1162     ap_max_daemons_limit = last_non_dead + 1;
1163
1164     if (free_length > 0) {
1165         for (i = 0; i < free_length; ++i) {
1166             make_child(ap_server_conf, free_slots[i]);
1167         }
1168         /* the next time around we want to spawn twice as many if this
1169          * wasn't good enough, but not if we've just done a graceful
1170          */
1171         if (hold_off_on_exponential_spawning) {
1172             --hold_off_on_exponential_spawning;
1173         }
1174         else if (spawn_rate < MAX_SPAWN_RATE) {
1175             spawn_rate *= 2;
1176         }
1177     }
1178     else {
1179         spawn_rate = 1;
1180     }
1181 }
1182
1183 static void server_main_loop(int remaining_children_to_start)
1184 {
1185     int child_slot;
1186     apr_exit_why_e exitwhy;
1187     int status;
1188     apr_proc_t pid;
1189     int i;
1190
1191     while (!restart_pending && !shutdown_pending) {
1192         ap_wait_or_timeout(&exitwhy, &status, &pid, pconf);
1193         
1194         if (pid.pid != -1) {
1195             if (ap_process_child_status(&pid, exitwhy, status)
1196                 == APEXIT_CHILDFATAL) {
1197                 shutdown_pending = 1;
1198                 child_fatal = 1;
1199                 return;
1200             }
1201             /* non-fatal death... note that it's gone in the child table and
1202              * clean out the status table. */
1203             child_slot = -1;
1204             for (i = 0; i < ap_max_daemons_limit; ++i) {
1205                 if (ap_child_table[i].pid == pid.pid) {
1206                     child_slot = i;
1207                     break;
1208                 }
1209             }
1210             if (child_slot >= 0) {
1211                 ap_child_table[child_slot].pid = 0;
1212                 ap_update_child_status_from_indexes(child_slot, i, SERVER_DEAD,
1213                                                     (request_rec *) NULL);
1214
1215                 
1216                 if (remaining_children_to_start
1217                     && child_slot < num_daemons) {
1218                     /* we're still doing a 1-for-1 replacement of dead
1219                      * children with new children
1220                      */
1221                     make_child(ap_server_conf, child_slot);
1222                     --remaining_children_to_start;
1223                 }
1224 #if APR_HAS_OTHER_CHILD
1225             }
1226             else if (apr_proc_other_child_read(&pid, status) == 0) {
1227             /* handled */
1228 #endif
1229             }
1230             else if (is_graceful) {
1231                 /* Great, we've probably just lost a slot in the
1232                 * child table.  Somehow we don't know about this
1233                 * child.
1234                 */
1235                 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, 
1236                              ap_server_conf,
1237                              "long lost child came home! (pid %ld)", 
1238                              (long)pid.pid);
1239             }
1240             /* Don't perform idle maintenance when a child dies,
1241              * only do it when there's a timeout.  Remember only a
1242              * finite number of children can die, and it's pretty
1243              * pathological for a lot to die suddenly.
1244              */
1245             continue;
1246         }
1247         else if (remaining_children_to_start) {
1248             /* we hit a 1 second timeout in which none of the previous
1249              * generation of children needed to be reaped... so assume
1250              * they're all done, and pick up the slack if any is left.
1251              */
1252             remaining_children_to_start = \
1253                 startup_children(remaining_children_to_start);
1254             /* In any event we really shouldn't do the code below because
1255              * few of the servers we just started are in the IDLE state
1256              * yet, so we'd mistakenly create an extra server.
1257              */
1258             continue;
1259         }
1260
1261         perform_child_maintenance();
1262     }
1263 }
1264
1265 int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
1266 {
1267     int remaining_children_to_start;
1268     int i;
1269     apr_status_t rv;
1270     apr_size_t one = 1;
1271     ap_listen_rec *lr;
1272     apr_socket_t *sock = NULL;
1273     int fd;
1274
1275     ap_log_pid(pconf, ap_pid_fname);
1276
1277     first_server_limit = server_limit;
1278     first_thread_limit = thread_limit;
1279     if (changed_limit_at_restart) {
1280         ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
1281                      "WARNING: Attempt to change ServerLimit or ThreadLimit "
1282                      "ignored during restart");
1283         changed_limit_at_restart = 0;
1284     }
1285
1286     ap_server_conf = s;
1287
1288     if ((ap_accept_lock_mech == APR_LOCK_SYSVSEM) || 
1289         (ap_accept_lock_mech == APR_LOCK_POSIXSEM)) {
1290         ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
1291                      "Server configured for an accept lock mechanism that "
1292                      "cannot be used with perchild.  Falling back to FCNTL.");
1293         ap_accept_lock_mech = APR_LOCK_FCNTL;
1294     }
1295
1296     /* Initialize cross-process accept lock */
1297     ap_lock_fname = apr_psprintf(_pconf, "%s.%u",
1298                                  ap_server_root_relative(_pconf, ap_lock_fname),
1299                                  my_pid);
1300     rv = SAFE_ACCEPT(apr_proc_mutex_create(&process_accept_mutex,
1301                                      ap_lock_fname, ap_accept_lock_mech,
1302                                      _pconf));
1303     if (rv != APR_SUCCESS) {
1304         ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s,
1305                      "Couldn't create cross-process lock");
1306         return 1;
1307     }
1308
1309     if (!is_graceful) {
1310         if (ap_run_pre_mpm(s->process->pool, SB_SHARED) != OK) {
1311             return 1;
1312         }
1313     }
1314     /* Initialize the child table */
1315     if (!is_graceful) {
1316         for (i = 0; i < server_limit; i++) {
1317             ap_child_table[i].pid = 0;
1318         }
1319     }
1320
1321     /* We need to put the new listeners at the end of the ap_listeners
1322      * list.  If we don't, then the pool will be cleared before the
1323      * open_logs phase is called for the second time, and ap_listeners
1324      * will have only invalid data.  If that happens, then the sockets
1325      * that we opened using make_sock() will be lost, and the server
1326      * won't start.
1327      */
1328     for (lr = ap_listeners ; lr->next != NULL; lr = lr->next) {
1329         continue;
1330     }
1331
1332     apr_os_file_get(&fd, pipe_of_death_in);
1333     apr_os_sock_put(&sock, &fd, pconf);
1334     lr->next = apr_palloc(pconf, sizeof(*lr));
1335     lr->next->sd = sock;
1336     lr->next->active = 1;
1337     lr->next->accept_func = check_pipe_of_death;
1338     lr->next->next = NULL;
1339     lr = lr->next;
1340     num_listensocks++;
1341
1342     set_signals();
1343
1344     /* If we're doing a graceful_restart then we're going to see a lot
1345      * of children exiting immediately when we get into the main loop
1346      * below (because we just sent them AP_SIG_GRACEFUL).  This happens 
1347      * pretty rapidly... and for each one that exits we'll start a new one 
1348      * until we reach at least daemons_min_free.  But we may be permitted to
1349      * start more than that, so we'll just keep track of how many we're
1350      * supposed to start up without the 1 second penalty between each fork.
1351      */
1352     remaining_children_to_start = num_daemons;
1353     if (!is_graceful) {
1354         remaining_children_to_start = \
1355             startup_children(remaining_children_to_start);
1356     }
1357     else {
1358         /* give the system some time to recover before kicking into
1359          * exponential mode */
1360         hold_off_on_exponential_spawning = 10;
1361     }
1362
1363     ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
1364                  "%s configured -- resuming normal operations",
1365                  ap_get_server_version());
1366     ap_log_error(APLOG_MARK, APLOG_INFO, 0, ap_server_conf,
1367                  "Server built: %s", ap_get_server_built());
1368 #ifdef AP_MPM_WANT_SET_ACCEPT_LOCK_MECH
1369     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
1370                 "AcceptMutex: %s (default: %s)",
1371                 apr_proc_mutex_name(process_accept_mutex),
1372                 apr_proc_mutex_defname());
1373 #endif
1374     restart_pending = shutdown_pending = 0;
1375
1376     server_main_loop(remaining_children_to_start);
1377
1378     if (shutdown_pending) {
1379         /* Time to gracefully shut down:
1380          * Kill child processes, tell them to call child_exit, etc...
1381          */
1382         if (unixd_killpg(getpgrp(), SIGTERM) < 0) {
1383             ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
1384                          "killpg SIGTERM");
1385         }
1386         ap_reclaim_child_processes(1);      /* Start with SIGTERM */
1387
1388         if (!child_fatal) {
1389             /* cleanup pid file on normal shutdown */
1390             const char *pidfile = NULL;
1391             pidfile = ap_server_root_relative (pconf, ap_pid_fname);
1392             if (pidfile != NULL && unlink(pidfile) == 0) {
1393                 ap_log_error(APLOG_MARK, APLOG_INFO, 0,
1394                              ap_server_conf,
1395                              "removed PID file %s (pid=%ld)",
1396                              pidfile, (long)getpid());
1397             }
1398     
1399             ap_log_error(APLOG_MARK, APLOG_NOTICE, 0,
1400                          ap_server_conf, "caught SIGTERM, shutting down");
1401         }
1402         return 1;
1403     }
1404
1405     /* we've been told to restart */
1406     apr_signal(SIGHUP, SIG_IGN);
1407
1408     if (one_process) {
1409         /* not worth thinking about */
1410         return 1;
1411     }
1412
1413     if (is_graceful) {
1414         char char_of_death = '!';
1415
1416         ap_log_error(APLOG_MARK, APLOG_NOTICE, 0,
1417                      ap_server_conf, AP_SIG_GRACEFUL_STRING " received.  "
1418                      "Doing graceful restart");
1419
1420         /* This is mostly for debugging... so that we know what is still
1421          * gracefully dealing with existing request.
1422          */
1423     
1424         for (i = 0; i < num_daemons; ++i) {
1425             if (ap_child_table[i].pid) {
1426                 ap_child_table[i].status = SERVER_DYING;
1427             } 
1428         }
1429         /* give the children the signal to die */
1430         for (i = 0; i < num_daemons;) {
1431             if ((rv = apr_file_write(pipe_of_death_out, &char_of_death,
1432                                      &one)) != APR_SUCCESS) {
1433                 if (APR_STATUS_IS_EINTR(rv)) continue;
1434                 ap_log_error(APLOG_MARK, APLOG_WARNING, rv, ap_server_conf,
1435                              "write pipe_of_death");
1436             }
1437             i++;
1438         }
1439     }
1440     else {
1441         /* Kill 'em all.  Since the child acts the same on the parents SIGTERM 
1442          * and a SIGHUP, we may as well use the same signal, because some user
1443          * pthreads are stealing signals from us left and right.
1444          */
1445         if (unixd_killpg(getpgrp(), SIGTERM) < 0) {
1446             ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
1447                          "killpg SIGTERM");
1448         }
1449         ap_reclaim_child_processes(1);      /* Start with SIGTERM */
1450         ap_log_error(APLOG_MARK, APLOG_NOTICE, 0,
1451                      ap_server_conf, "SIGHUP received.  Attempting to restart");
1452     }
1453     return 0;
1454 }
1455
1456 /* This really should be a post_config hook, but the error log is already
1457  * redirected by that point, so we need to do this in the open_logs phase.
1458  */
1459 static int perchild_open_logs(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
1460 {
1461     apr_status_t rv;
1462
1463     pconf = p;
1464     ap_server_conf = s;
1465
1466     if ((num_listensocks = ap_setup_listeners(ap_server_conf)) < 1) {
1467         ap_log_error(APLOG_MARK, APLOG_ALERT|APLOG_STARTUP, 0,
1468                      NULL, "no listening sockets available, shutting down");
1469         return DONE;
1470     }
1471
1472     ap_log_pid(pconf, ap_pid_fname);
1473
1474     if ((rv = ap_mpm_pod_open(pconf, &pod))) {
1475         ap_log_error(APLOG_MARK, APLOG_CRIT|APLOG_STARTUP, rv, NULL,
1476                 "Could not open pipe-of-death.");
1477         return DONE;
1478     }
1479
1480     if ((rv = apr_file_pipe_create(&pipe_of_death_in, &pipe_of_death_out,
1481                                    pconf)) != APR_SUCCESS) {
1482         ap_log_error(APLOG_MARK, APLOG_ERR, rv,
1483                      (const server_rec*) ap_server_conf,
1484                      "apr_file_pipe_create (pipe_of_death)");
1485         exit(1);
1486     }
1487     if ((rv = apr_file_pipe_timeout_set(pipe_of_death_in, 0)) != APR_SUCCESS) {
1488         ap_log_error(APLOG_MARK, APLOG_ERR, rv,
1489                      (const server_rec*) ap_server_conf,
1490                      "apr_file_pipe_timeout_set (pipe_of_death)");
1491         exit(1);
1492     }
1493
1494     return OK;
1495 }
1496
1497 static int perchild_pre_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp)
1498 {
1499     static int restart_num = 0;
1500     int no_detach, debug, foreground;
1501     ap_directive_t *pdir;
1502     int i;
1503     int tmp_server_limit = DEFAULT_SERVER_LIMIT;
1504     int tmp_thread_limit = DEFAULT_THREAD_LIMIT;
1505     apr_status_t rv;
1506
1507     debug = ap_exists_config_define("DEBUG");
1508
1509     if (debug) {
1510         foreground = one_process = 1;
1511         no_detach = 0;
1512     }
1513     else {
1514         one_process = ap_exists_config_define("ONE_PROCESS");
1515         no_detach = ap_exists_config_define("NO_DETACH");
1516         foreground = ap_exists_config_define("FOREGROUND");
1517     }
1518
1519     /* sigh, want this only the second time around */
1520     if (restart_num++ == 1) {
1521         is_graceful = 0;
1522
1523         if (!one_process && !foreground) {
1524             rv = apr_proc_detach(no_detach ? APR_PROC_DETACH_FOREGROUND
1525                                            : APR_PROC_DETACH_DAEMONIZE);
1526             if (rv != APR_SUCCESS) {
1527                 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL,
1528                              "apr_proc_detach failed");
1529                 return HTTP_INTERNAL_SERVER_ERROR;
1530             }                  
1531         }
1532
1533         my_pid = getpid();
1534     }
1535
1536     unixd_pre_config(ptemp);
1537     ap_listen_pre_config();
1538     num_daemons = DEFAULT_NUM_DAEMON;
1539     threads_to_start = DEFAULT_START_THREAD;
1540     min_spare_threads = DEFAULT_MIN_SPARE_THREAD;
1541     max_spare_threads = DEFAULT_MAX_SPARE_THREAD;
1542     max_threads = thread_limit;
1543     ap_pid_fname = DEFAULT_PIDLOG;
1544     ap_lock_fname = DEFAULT_LOCKFILE;
1545     ap_max_requests_per_child = DEFAULT_MAX_REQUESTS_PER_CHILD;
1546     curr_child_num = 0;
1547 #ifdef AP_MPM_WANT_SET_MAX_MEM_FREE
1548         ap_max_mem_free = APR_ALLOCATOR_MAX_FREE_UNLIMITED;
1549 #endif
1550
1551     apr_cpystrn(ap_coredump_dir, ap_server_root, sizeof(ap_coredump_dir));
1552
1553     /* we need to know ServerLimit and ThreadLimit before we start processing
1554      * the tree because we need to already have allocated child_info_table
1555      */
1556     for (pdir = ap_conftree; pdir != NULL; pdir = pdir->next) {
1557         if (!strcasecmp(pdir->directive, "ServerLimit")) {
1558             if (atoi(pdir->args) > tmp_server_limit) {
1559                 tmp_server_limit = atoi(pdir->args);
1560                 if (tmp_server_limit > MAX_SERVER_LIMIT) {
1561                     tmp_server_limit = MAX_SERVER_LIMIT;
1562                 }
1563             }
1564         }
1565         else if (!strcasecmp(pdir->directive, "ThreadLimit")) {
1566             if (atoi(pdir->args) > tmp_thread_limit) {
1567                 tmp_thread_limit = atoi(pdir->args);
1568                 if (tmp_thread_limit > MAX_THREAD_LIMIT) {
1569                     tmp_thread_limit = MAX_THREAD_LIMIT;
1570                 }
1571             }
1572         }
1573     }
1574
1575     child_info_table = (child_info_t *)apr_pcalloc(p, tmp_server_limit * sizeof(child_info_t));
1576     for (i = 0; i < tmp_server_limit; i++) {
1577         child_info_table[i].uid = -1;
1578         child_info_table[i].gid = -1;
1579         child_info_table[i].input = -1;
1580         child_info_table[i].output = -1;
1581     }
1582
1583     return OK;
1584 }
1585
1586 static int pass_request(request_rec *r)
1587 {
1588     int rv;
1589     apr_socket_t *thesock = ap_get_module_config(r->connection->conn_config, &core_module);
1590     struct msghdr msg;
1591     struct cmsghdr *cmsg;
1592     int sfd;
1593     struct iovec iov[2];
1594     conn_rec *c = r->connection;
1595     apr_bucket_brigade *bb = apr_brigade_create(r->pool, c->bucket_alloc);
1596     apr_bucket_brigade *sockbb;
1597     char request_body[HUGE_STRING_LEN] = "\0";
1598     apr_size_t l = sizeof(request_body);
1599     perchild_header h;
1600     apr_bucket *sockbuck;
1601     perchild_server_conf *sconf = (perchild_server_conf *)
1602                             ap_get_module_config(r->server->module_config, 
1603                                                  &mpm_perchild_module);
1604
1605     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, 
1606                  "passing request to another child.  Vhost: %s, child %d %d",
1607                  apr_table_get(r->headers_in, "Host"), child_num, sconf->output);
1608     ap_get_brigade(r->connection->input_filters, bb, AP_MODE_EXHAUSTIVE, APR_NONBLOCK_READ,
1609                    0);
1610
1611     for (sockbuck = APR_BRIGADE_FIRST(bb); sockbuck != APR_BRIGADE_SENTINEL(bb);
1612          sockbuck = APR_BUCKET_NEXT(sockbuck)) {
1613         if (APR_BUCKET_IS_SOCKET(sockbuck)) {
1614             break;
1615         }
1616     }
1617     
1618     if (!sockbuck) {
1619     }
1620     sockbb = apr_brigade_split(bb, sockbuck); 
1621
1622     if (apr_brigade_flatten(bb, request_body, &l) != APR_SUCCESS) {
1623         ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, 
1624                      "Unable to flatten brigade, declining request");
1625         return DECLINED;
1626     }
1627
1628     apr_os_sock_get(&sfd, thesock);
1629
1630     h.p = r->pool;
1631     h.headers = apr_pstrcat(h.p, r->the_request, CRLF, "Host: ", r->hostname, 
1632                             CRLF, NULL);
1633     apr_table_do((int (*) (void *, const char *, const char *))
1634                  perchild_header_field, (void *) &h, r->headers_in, NULL); 
1635     h.headers = apr_pstrcat(h.p, h.headers, CRLF, NULL);
1636
1637     iov[0].iov_base = h.headers;
1638     iov[0].iov_len = strlen(h.headers) + 1;
1639     iov[1].iov_base = request_body;
1640     iov[1].iov_len = l + 1;
1641
1642     msg.msg_name = NULL;
1643     msg.msg_namelen = 0;
1644     msg.msg_iov = iov;
1645     msg.msg_iovlen = 2;
1646
1647     cmsg = apr_palloc(r->pool, sizeof(*cmsg) + sizeof(sfd));
1648     cmsg->cmsg_len = sizeof(*cmsg) + sizeof(sfd);
1649     cmsg->cmsg_level = SOL_SOCKET;
1650     cmsg->cmsg_type = SCM_RIGHTS;
1651
1652     memcpy(CMSG_DATA(cmsg), &sfd, sizeof(sfd));
1653
1654     msg.msg_control = cmsg;
1655     msg.msg_controllen = cmsg->cmsg_len;
1656
1657     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, 
1658                  "Writing message to %d, passing sd:  %d", sconf->output, sfd);
1659
1660     if ((rv = sendmsg(sconf->output, &msg, 0)) == -1) {
1661         apr_pool_destroy(r->pool);
1662         ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, 
1663                  "Writing message failed %d %d", rv, errno);
1664         return -1;
1665     }
1666
1667     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, 
1668                  "Writing message succeeded %d", rv);
1669
1670     apr_pool_destroy(r->pool);
1671     return 1;
1672 }
1673
1674 static char *make_perchild_socket(const char *fullsockname, int sd[2])
1675 {
1676     socketpair(PF_UNIX, SOCK_STREAM, 0, sd);
1677     return NULL;
1678 }
1679
1680 static int perchild_post_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
1681 {
1682     int i;
1683     server_rec *sr;
1684     perchild_server_conf *sconf;
1685     int def_sd[2];
1686
1687     def_sd[0] = -1;
1688     def_sd[1] = -1;
1689
1690     for (sr = s; sr; sr = sr->next) {
1691         sconf = (perchild_server_conf *)ap_get_module_config(sr->module_config,
1692                                                       &mpm_perchild_module);
1693
1694         if (sconf->input == -1) {
1695             sconf->fullsockname = apr_pstrcat(sr->process->pool, 
1696                                              sconf->sockname, ".DEFAULT", NULL);
1697             if (def_sd[0] == -1) {
1698                 if (!make_perchild_socket(sconf->fullsockname, def_sd)) {
1699                     /* log error */
1700                 }
1701             }
1702             sconf->input = def_sd[0];
1703             sconf->output = def_sd[1];
1704         }
1705     }
1706
1707     for (i = 0; i < num_daemons; i++) {
1708         if (child_info_table[i].uid == -1) {
1709             child_info_table[i].input = def_sd[0];
1710             child_info_table[i].output = def_sd[1];
1711         }
1712     }
1713
1714     thread_socket_table = (int *)apr_pcalloc(p, thread_limit * sizeof(int));
1715     for (i = 0; i < thread_limit; i++) {
1716         thread_socket_table[i] = AP_PERCHILD_THISCHILD;
1717     }
1718     ap_child_table = (ap_ctable *)apr_pcalloc(p, server_limit * sizeof(ap_ctable));
1719
1720     return OK;
1721 }
1722
1723 static int perchild_post_read(request_rec *r)
1724 {
1725     int thread_num = r->connection->id % thread_limit;
1726     perchild_server_conf *sconf = (perchild_server_conf *)
1727                             ap_get_module_config(r->server->module_config, 
1728                                                  &mpm_perchild_module);
1729
1730     if (thread_socket_table[thread_num] != AP_PERCHILD_THISCHILD) {
1731         apr_socket_t *csd = NULL;
1732
1733         apr_os_sock_put(&csd, &thread_socket_table[thread_num], 
1734                         r->connection->pool);
1735         ap_sock_disable_nagle(csd);
1736         ap_set_module_config(r->connection->conn_config, &core_module, csd);
1737         return OK;
1738     }
1739     else {
1740         ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, 
1741                      "Determining if request should be passed. "
1742                      "Child Num: %d, SD: %d, sd from table: %d, hostname from server: %s", child_num, 
1743                      sconf->input, child_info_table[child_num].input, 
1744                      r->server->server_hostname);
1745         /* sconf is the server config for this vhost, so if our socket
1746          * is not the same that was set in the config, then the request
1747          * needs to be passed to another child. */
1748         if (sconf->input != child_info_table[child_num].input) {
1749             ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, 
1750                          "Passing request.");
1751             if (pass_request(r) == -1) {
1752                 ap_log_error(APLOG_MARK, APLOG_ERR, 0,
1753                              ap_server_conf, "Could not pass request to proper "
1754                              "child, request will not be honored.");
1755             }
1756             longjmp(jmpbuffer, 1); 
1757         }
1758         return OK;
1759     }
1760     return OK;
1761 }
1762
1763 static void perchild_hooks(apr_pool_t *p)
1764 {
1765     /* The perchild open_logs phase must run before the core's, or stderr
1766      * will be redirected to a file, and the messages won't print to the
1767      * console.
1768      */
1769     static const char *const aszSucc[] = {"core.c", NULL};
1770     one_process = 0;
1771
1772     ap_hook_open_logs(perchild_open_logs, NULL, aszSucc, APR_HOOK_MIDDLE);
1773     ap_hook_pre_config(perchild_pre_config, NULL, NULL, APR_HOOK_MIDDLE); 
1774     ap_hook_post_config(perchild_post_config, NULL, NULL, APR_HOOK_MIDDLE); 
1775
1776     /* Both of these must be run absolutely first.  If this request isn't for 
1777      * this server then we need to forward it to the proper child.  No sense
1778      * tying up this server running more post_read request hooks if it is
1779      * just going to be forwarded along.  The process_connection hook allows
1780      * perchild to receive the passed request correctly, by automatically
1781      * filling in the core_input_filter's ctx pointer.
1782      */
1783     ap_hook_post_read_request(perchild_post_read, NULL, NULL,
1784                               APR_HOOK_REALLY_FIRST);
1785     ap_hook_process_connection(perchild_process_connection, NULL, NULL, 
1786                                APR_HOOK_REALLY_FIRST);
1787 }
1788
1789 static const char *set_num_daemons(cmd_parms *cmd, void *dummy,
1790                                    const char *arg) 
1791 {
1792     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
1793     if (err != NULL) {
1794         return err;
1795     }
1796
1797     num_daemons = atoi(arg);
1798     if (num_daemons > server_limit) {
1799        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, 
1800                     "WARNING: NumServers of %d exceeds ServerLimit value "
1801                     "of %d servers,", num_daemons, server_limit);
1802        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, 
1803                     " lowering NumServers to %d.  To increase, please "
1804                     "see the", server_limit);
1805        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, 
1806                     " ServerLimit directive.");
1807        num_daemons = server_limit;
1808     } 
1809     else if (num_daemons < 1) {
1810         ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, 
1811                      "WARNING: Require NumServers > 0, setting to 1");
1812         num_daemons = 1;
1813     }
1814     return NULL;
1815 }
1816
1817 static const char *set_threads_to_start(cmd_parms *cmd, void *dummy,
1818                                         const char *arg) 
1819 {
1820     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
1821     if (err != NULL) {
1822         return err;
1823     }
1824
1825     threads_to_start = atoi(arg);
1826     if (threads_to_start > thread_limit) {
1827         ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, 
1828                      "WARNING: StartThreads of %d exceeds ThreadLimit value"
1829                      " of %d threads,", threads_to_start,
1830                      thread_limit);
1831         ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, 
1832                      " lowering StartThreads to %d. To increase, please"
1833                      " see the", thread_limit);
1834         ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, 
1835                      " ThreadLimit directive.");
1836     }
1837     else if (threads_to_start < 1) {
1838         ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, 
1839                      "WARNING: Require StartThreads > 0, setting to 1");
1840         threads_to_start = 1;
1841     }
1842     return NULL;
1843 }
1844
1845 static const char *set_min_spare_threads(cmd_parms *cmd, void *dummy,
1846                                          const char *arg)
1847 {
1848     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
1849     if (err != NULL) {
1850         return err;
1851     }
1852
1853     min_spare_threads = atoi(arg);
1854     if (min_spare_threads <= 0) {
1855        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, 
1856                     "WARNING: detected MinSpareThreads set to non-positive.");
1857        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, 
1858                     "Resetting to 1 to avoid almost certain Apache failure.");
1859        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, 
1860                     "Please read the documentation.");
1861        min_spare_threads = 1;
1862     }
1863        
1864     return NULL;
1865 }
1866
1867 static const char *set_max_spare_threads(cmd_parms *cmd, void *dummy,
1868                                          const char *arg)
1869 {
1870     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
1871     if (err != NULL) {
1872         return err;
1873     }
1874
1875     max_spare_threads = atoi(arg);
1876     if (max_spare_threads >= thread_limit) {
1877        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, 
1878                     "WARNING: detected MinSpareThreads set higher than");
1879        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, 
1880                     "ThreadLimit. Resetting to %d", thread_limit);
1881        max_spare_threads = thread_limit;
1882     }
1883     return NULL;
1884 }
1885
1886 static const char *set_max_threads(cmd_parms *cmd, void *dummy, const char *arg)
1887 {
1888     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
1889     if (err != NULL) {
1890         return err;
1891     }
1892
1893     max_threads = atoi(arg);
1894     if (max_threads > thread_limit) {
1895        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, 
1896                     "WARNING: detected MaxThreadsPerChild set higher than");
1897        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, 
1898                     "ThreadLimit. Resetting to %d", thread_limit);
1899        max_threads = thread_limit;
1900     }
1901     return NULL;
1902 }
1903
1904 static const char *set_child_per_uid(cmd_parms *cmd, void *dummy, const char *u,
1905                                      const char *g, const char *num)
1906 {
1907     int i;
1908     int max_this_time = atoi(num) + curr_child_num;
1909     
1910
1911     for (i = curr_child_num; i < max_this_time; i++, curr_child_num++) {
1912         if (i > num_daemons) {
1913             return "Trying to use more child ID's than NumServers.  Increase "
1914                    "NumServers in your config file.";
1915         }
1916     
1917         child_info_table[i].uid = ap_uname2id(u);
1918         child_info_table[i].gid = ap_gname2id(g); 
1919
1920 #ifndef BIG_SECURITY_HOLE
1921         if (child_info_table[i].uid == 0 || child_info_table[i].gid == 0) {
1922             return "Assigning root user/group to a child.";
1923         }
1924 #endif
1925     }
1926     return NULL;
1927 }
1928
1929 static const char *assign_childuid(cmd_parms *cmd, void *dummy, const char *uid,
1930                                    const char *gid)
1931 {
1932     int i;
1933     int matching = 0;
1934     int u = ap_uname2id(uid);
1935     int g = ap_gname2id(gid);
1936     const char *errstr;
1937     int socks[2];
1938     perchild_server_conf *sconf = (perchild_server_conf *)
1939                             ap_get_module_config(cmd->server->module_config, 
1940                                                  &mpm_perchild_module);
1941
1942     sconf->fullsockname = apr_pstrcat(cmd->pool, sconf->sockname, ".", uid,
1943                                       ":", gid, NULL);
1944
1945     if ((errstr = make_perchild_socket(sconf->fullsockname, socks))) {
1946         return errstr;
1947     }
1948
1949     sconf->input = socks[0]; 
1950     sconf->output = socks[1];
1951
1952     for (i = 0; i < num_daemons; i++) {
1953         if (u == child_info_table[i].uid && g == child_info_table[i].gid) {
1954             child_info_table[i].input = sconf->input;
1955             child_info_table[i].output = sconf->output;
1956             matching++;
1957             ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, cmd->server, 
1958                          "filling out child_info_table; UID: %d, GID: %d, "
1959                          "SD: %d %d, OUTPUT: %d %d, Child Num: %d", 
1960                          child_info_table[i].uid, child_info_table[i].gid, 
1961                          sconf->input, child_info_table[i].input, sconf->output,
1962                          child_info_table[i].output, i);
1963         }
1964     }
1965
1966     if (!matching) {
1967         return "Unable to find process with matching uid/gid.";
1968     }
1969     return NULL;
1970 }
1971
1972 static const char *set_server_limit (cmd_parms *cmd, void *dummy, const char *arg) 
1973 {
1974     int tmp_server_limit;
1975     
1976     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
1977     if (err != NULL) {
1978         return err;
1979     }
1980
1981     tmp_server_limit = atoi(arg);
1982     /* you cannot change ServerLimit across a restart; ignore
1983      * any such attempts
1984      */
1985     if (first_server_limit &&
1986         tmp_server_limit != server_limit) {
1987         /* how do we log a message?  the error log is a bit bucket at this
1988          * point; we'll just have to set a flag so that ap_mpm_run()
1989          * logs a warning later
1990          */
1991         changed_limit_at_restart = 1;
1992         return NULL;
1993     }
1994     server_limit = tmp_server_limit;
1995     
1996     if (server_limit > MAX_SERVER_LIMIT) {
1997        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, 
1998                     "WARNING: ServerLimit of %d exceeds compile time limit "
1999                     "of %d servers,", server_limit, MAX_SERVER_LIMIT);
2000        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, 
2001                     " lowering ServerLimit to %d.", MAX_SERVER_LIMIT);
2002        server_limit = MAX_SERVER_LIMIT;
2003     } 
2004     else if (server_limit < 1) {
2005         ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, 
2006                      "WARNING: Require ServerLimit > 0, setting to 1");
2007         server_limit = 1;
2008     }
2009     return NULL;
2010 }
2011
2012 static const char *set_thread_limit (cmd_parms *cmd, void *dummy, const char *arg) 
2013 {
2014     int tmp_thread_limit;
2015     
2016     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
2017     if (err != NULL) {
2018         return err;
2019     }
2020
2021     tmp_thread_limit = atoi(arg);
2022     /* you cannot change ThreadLimit across a restart; ignore
2023      * any such attempts
2024      */
2025     if (first_thread_limit &&
2026         tmp_thread_limit != thread_limit) {
2027         /* how do we log a message?  the error log is a bit bucket at this
2028          * point; we'll just have to set a flag so that ap_mpm_run()
2029          * logs a warning later
2030          */
2031         changed_limit_at_restart = 1;
2032         return NULL;
2033     }
2034     thread_limit = tmp_thread_limit;
2035     
2036     if (thread_limit > MAX_THREAD_LIMIT) {
2037        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, 
2038                     "WARNING: ThreadLimit of %d exceeds compile time limit "
2039                     "of %d servers,", thread_limit, MAX_THREAD_LIMIT);
2040        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, 
2041                     " lowering ThreadLimit to %d.", MAX_THREAD_LIMIT);
2042        thread_limit = MAX_THREAD_LIMIT;
2043     } 
2044     else if (thread_limit < 1) {
2045         ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, 
2046                      "WARNING: Require ThreadLimit > 0, setting to 1");
2047         thread_limit = 1;
2048     }
2049     return NULL;
2050 }
2051
2052 static const command_rec perchild_cmds[] = {
2053 UNIX_DAEMON_COMMANDS,
2054 LISTEN_COMMANDS,
2055 AP_INIT_TAKE1("NumServers", set_num_daemons, NULL, RSRC_CONF,
2056               "Number of children alive at the same time"),
2057 AP_INIT_TAKE1("StartThreads", set_threads_to_start, NULL, RSRC_CONF,
2058               "Number of threads each child creates"),
2059 AP_INIT_TAKE1("MinSpareThreads", set_min_spare_threads, NULL, RSRC_CONF,
2060               "Minimum number of idle threads per child, to handle "
2061               "request spikes"),
2062 AP_INIT_TAKE1("MaxSpareThreads", set_max_spare_threads, NULL, RSRC_CONF,
2063               "Maximum number of idle threads per child"),
2064 AP_INIT_TAKE1("MaxThreadsPerChild", set_max_threads, NULL, RSRC_CONF,
2065               "Maximum number of threads per child"),
2066 AP_INIT_TAKE3("ChildperUserID", set_child_per_uid, NULL, RSRC_CONF,
2067               "Specify a User and Group for a specific child process."),
2068 AP_INIT_TAKE2("AssignUserID", assign_childuid, NULL, RSRC_CONF,
2069               "Tie a virtual host to a specific child process."),
2070 AP_INIT_TAKE1("ServerLimit", set_server_limit, NULL, RSRC_CONF,
2071               "Maximum value of NumServers for this run of Apache"),
2072 AP_INIT_TAKE1("ThreadLimit", set_thread_limit, NULL, RSRC_CONF,
2073               "Maximum worker threads in a server for this run of Apache"),
2074 { NULL }
2075 };
2076
2077 static void *perchild_create_config(apr_pool_t *p, server_rec *s)
2078 {
2079     perchild_server_conf *c = (perchild_server_conf *)
2080                                   apr_pcalloc(p, sizeof(perchild_server_conf));
2081
2082     c->input = -1;
2083     c->output = -1;
2084     return c;
2085 }
2086
2087 module AP_MODULE_DECLARE_DATA mpm_perchild_module = {
2088     MPM20_MODULE_STUFF,
2089     ap_mpm_rewrite_args,        /* hook to run before apache parses args */
2090     NULL,                       /* create per-directory config structure */
2091     NULL,                       /* merge per-directory config structures */
2092     perchild_create_config,     /* create per-server config structure */
2093     NULL,                       /* merge per-server config structures */
2094     perchild_cmds,              /* command apr_table_t */
2095     perchild_hooks              /* register_hooks */
2096 };
2097