]> granicus.if.org Git - apache/blob - server/mpm/mpmt_pthread/mpmt_pthread.c
Fix some warnings when configured with --enable-maintainer-mode.
[apache] / server / mpm / mpmt_pthread / mpmt_pthread.c
1 /* ====================================================================
2  * Copyright (c) 1995-1999 The Apache Group.  All rights reserved.
3  * 
4  * Redistribution and use in source and binary forms, with or without 
5  * modification, are permitted provided that the following conditions 
6  * are met: 
7  * 
8  * 1. Redistributions of source code must retain the above copyright 
9  *    notice, this list of conditions and the following disclaimer.  
10  * 
11  * 2. Redistributions in binary form must reproduce the above copyright 
12  *    notice, this list of conditions and the following disclaimer in 
13  *    the documentation and/or other materials provided with the 
14  *    distribution. 
15  * 
16  * 3. All advertising materials mentioning features or use of this 
17  *    software must display the following acknowledgment: 
18  *    "This product includes software developed by the Apache Group 
19  *    for use in the Apache HTTP server project (http://www.apache.org/)." 
20  * 
21  * 4. The names "Apache Server" and "Apache Group" must not be used to 
22  *    endorse or promote products derived from this software without 
23  *    prior written permission. For written permission, please contact 
24  *    apache@apache.org. 
25  * 
26  * 5. Products derived from this software may not be called "Apache" 
27  *    nor may "Apache" appear in their names without prior written 
28  *    permission of the Apache Group. 
29  * 
30  * 6. Redistributions of any form whatsoever must retain the following 
31  *    acknowledgment: 
32  *    "This product includes software developed by the Apache Group 
33  *    for use in the Apache HTTP server project (http://www.apache.org/)." 
34  * 
35  * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY 
36  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
37  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
38  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE APACHE GROUP OR 
39  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
40  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
41  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
42  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
43  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
44  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
45  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
46  * OF THE POSSIBILITY OF SUCH DAMAGE. 
47  * ==================================================================== 
48  * 
49  * This software consists of voluntary contributions made by many 
50  * individuals on behalf of the Apache Group and was originally based 
51  * on public domain software written at the National Center for 
52  * Supercomputing Applications, University of Illinois, Urbana-Champaign. 
53  * For more information on the Apache Group and the Apache HTTP server 
54  * project, please see <http://www.apache.org/>. 
55  * 
56  */ 
57  
58 #define CORE_PRIVATE 
59  
60 #include "apr_portable.h"
61 #include "httpd.h" 
62 #include "http_main.h" 
63 #include "http_log.h" 
64 #include "http_config.h"        /* for read_config */ 
65 #include "http_core.h"          /* for get_remote_host */ 
66 #include "http_connection.h"
67 #include "ap_mpm.h"
68 #include "unixd.h"
69 #include "iol_socket.h"
70 #include "ap_listen.h"
71 #include "scoreboard.h" 
72
73 #include <netinet/tcp.h> 
74 #include <pthread.h>
75 #include <signal.h>
76
77 /*
78  * Actual definitions of config globals
79  */
80
81 int ap_threads_per_child=0;         /* Worker threads per child */
82 int ap_max_requests_per_child=0;
83 static char *ap_pid_fname=NULL;
84 static char *ap_scoreboard_fname=NULL;
85 static int ap_daemons_to_start=0;
86 static int min_spare_threads=0;
87 static int max_spare_threads=0;
88 static int ap_daemons_limit=0;
89 static time_t ap_restart_time=0;
90 API_VAR_EXPORT int ap_extended_status = 0;
91 static int workers_may_exit = 0;
92 static int requests_this_child;
93 static int num_listensocks = 0;
94 static ap_socket_t **listensocks;
95
96 /* The structure used to pass unique initialization info to each thread */
97 typedef struct {
98     int pid;
99     int tid;
100     int sd;
101     ap_context_t *tpool; /* "pthread" would be confusing */
102 } proc_info;
103
104 /*
105  * The max child slot ever assigned, preserved across restarts.  Necessary
106  * to deal with MaxClients changes across SIGWINCH restarts.  We use this
107  * value to optimize routines that have to scan the entire scoreboard.
108  */
109 static int max_daemons_limit = -1;
110
111 static char ap_coredump_dir[MAX_STRING_LEN];
112
113 static int pipe_of_death[2];
114 static pthread_mutex_t pipe_of_death_mutex;
115
116 /* *Non*-shared http_main globals... */
117
118 static server_rec *server_conf;
119
120 /* one_process --- debugging mode variable; can be set from the command line
121  * with the -X flag.  If set, this gets you the child_main loop running
122  * in the process which originally started up (no detach, no make_child),
123  * which is a pretty nice debugging environment.  (You'll get a SIGHUP
124  * early in standalone_main; just continue through.  This is the server
125  * trying to kill off any child processes which it might have lying
126  * around --- Apache doesn't keep track of their pids, it just sends
127  * SIGHUP to the process group, ignoring it in the root process.
128  * Continue through and you'll be fine.).
129  */
130
131 static int one_process = 0;
132
133 #ifdef DEBUG_SIGSTOP
134 int raise_sigstop_flags;
135 #endif
136
137 #ifdef HAS_OTHER_CHILD
138 /* used to maintain list of children which aren't part of the scoreboard */
139 typedef struct other_child_rec other_child_rec;
140 struct other_child_rec {
141     other_child_rec *next;
142     int pid;
143     void (*maintenance) (int, void *, ap_wait_t);
144     void *data;
145     int write_fd;
146 };
147 static other_child_rec *other_children;
148 #endif
149
150 static ap_context_t *pconf;             /* Pool for config stuff */
151 static ap_context_t *pchild;            /* Pool for httpd child stuff */
152
153 static int my_pid; /* Linux getpid() doesn't work except in main thread. Use
154                       this instead */
155 /* Keep track of the number of worker threads currently active */
156 static int worker_thread_count;
157 static pthread_mutex_t worker_thread_count_mutex;
158
159 /* Locks for accept serialization */
160 static pthread_mutex_t thread_accept_mutex = PTHREAD_MUTEX_INITIALIZER;
161 static ap_lock_t *process_accept_mutex;
162 static char *lock_fname;
163
164 #ifdef NO_SERIALIZED_ACCEPT
165 #define SAFE_ACCEPT(stmt) APR_SUCCESS
166 #else
167 #define SAFE_ACCEPT(stmt) (stmt)
168 #endif
169
170
171 /* Global, alas, so http_core can talk to us */
172 enum server_token_type ap_server_tokens = SrvTk_FULL;
173
174 API_EXPORT(const server_rec *) ap_get_server_conf(void)
175 {
176     return (server_conf);
177 }
178
179 API_EXPORT(int) ap_get_max_daemons(void)
180 {
181     return max_daemons_limit;
182 }
183
184 /* a clean exit from a child with proper cleanup */ 
185 static void clean_child_exit(int code) __attribute__ ((noreturn));
186 void clean_child_exit(int code)
187 {
188     if (pchild) {
189         ap_destroy_pool(pchild);
190     }
191     exit(code);
192 }
193
194 /*****************************************************************
195  * dealing with other children
196  */
197
198 #ifdef HAS_OTHER_CHILD
199 API_EXPORT(void) ap_register_other_child(int pid,
200                        void (*maintenance) (int reason, void *, ap_wait_t status),
201                           void *data, int write_fd)
202 {
203     other_child_rec *ocr;
204
205     ocr = ap_palloc(pconf, sizeof(*ocr));
206     ocr->pid = pid;
207     ocr->maintenance = maintenance;
208     ocr->data = data;
209     ocr->write_fd = write_fd;
210     ocr->next = other_children;
211     other_children = ocr;
212 }
213
214 /* note that since this can be called by a maintenance function while we're
215  * scanning the other_children list, all scanners should protect themself
216  * by loading ocr->next before calling any maintenance function.
217  */
218 API_EXPORT(void) ap_unregister_other_child(void *data)
219 {
220     other_child_rec **pocr, *nocr;
221
222     for (pocr = &other_children; *pocr; pocr = &(*pocr)->next) {
223         if ((*pocr)->data == data) {
224             nocr = (*pocr)->next;
225             (*(*pocr)->maintenance) (OC_REASON_UNREGISTER, (*pocr)->data, -1);
226             *pocr = nocr;
227             /* XXX: um, well we've just wasted some space in pconf ? */
228             return;
229         }
230     }
231 }
232
233 /* test to ensure that the write_fds are all still writable, otherwise
234  * invoke the maintenance functions as appropriate */
235 static void probe_writable_fds(void)
236 {
237     return;
238 #if 0
239     fd_set writable_fds;
240     int fd_max;
241     other_child_rec *ocr, *nocr;
242     struct timeval tv;
243     int rc;
244
245     if (other_children == NULL)
246         return;
247
248     fd_max = 0;
249     FD_ZERO(&writable_fds);
250     do {
251         for (ocr = other_children; ocr; ocr = ocr->next) {
252             if (ocr->write_fd == -1)
253                 continue;
254             FD_SET(ocr->write_fd, &writable_fds);
255             if (ocr->write_fd > fd_max) {
256                 fd_max = ocr->write_fd;
257             }
258         }
259         if (fd_max == 0)
260             return;
261
262         tv.tv_sec = 0;
263         tv.tv_usec = 0;
264         rc = ap_select(fd_max + 1, NULL, &writable_fds, NULL, &tv);
265     } while (rc == -1 && errno == EINTR);
266
267     if (rc == -1) {
268         /* XXX: uhh this could be really bad, we could have a bad file
269          * descriptor due to a bug in one of the maintenance routines */
270         ap_log_unixerr("probe_writable_fds", "select",
271                     "could not probe writable fds", server_conf);
272         return;
273     }
274     if (rc == 0)
275         return;
276
277     for (ocr = other_children; ocr; ocr = nocr) {
278         nocr = ocr->next;
279         if (ocr->write_fd == -1)
280             continue;
281         if (FD_ISSET(ocr->write_fd, &writable_fds))
282             continue;
283         (*ocr->maintenance) (OC_REASON_UNWRITABLE, ocr->data, -1);
284     }
285 #endif
286 }
287
288 /* possibly reap an other_child, return 0 if yes, -1 if not */
289 static int reap_other_child(int pid, ap_wait_t status)
290 {
291     other_child_rec *ocr, *nocr;
292
293     for (ocr = other_children; ocr; ocr = nocr) {
294         nocr = ocr->next;
295         if (ocr->pid != pid)
296             continue;
297         ocr->pid = -1;
298         (*ocr->maintenance) (OC_REASON_DEATH, ocr->data, status);
299         return 0;
300     }
301     return -1;
302 }
303 #endif
304
305 static void reclaim_child_processes(int terminate)
306 {
307     int i, status;
308     long int waittime = 1024 * 16;      /* in usecs */
309     struct timeval tv;
310     int waitret, tries;
311     int not_dead_yet;
312 #ifdef HAS_OTHER_CHILD
313     other_child_rec *ocr, *nocr;
314 #endif
315
316     ap_sync_scoreboard_image();
317
318     for (tries = terminate ? 4 : 1; tries <= 9; ++tries) {
319         /* don't want to hold up progress any more than 
320          * necessary, but we need to allow children a few moments to exit.
321          * Set delay with an exponential backoff.
322          */
323         tv.tv_sec = waittime / 1000000;
324         tv.tv_usec = waittime % 1000000;
325         waittime = waittime * 4;
326         ap_select(0, NULL, NULL, NULL, &tv);
327
328         /* now see who is done */
329         not_dead_yet = 0;
330         for (i = 0; i < max_daemons_limit; ++i) {
331             int pid = ap_scoreboard_image->parent[i].pid;
332
333             if (pid == my_pid || pid == 0)
334                 continue;
335
336             waitret = waitpid(pid, &status, WNOHANG);
337             if (waitret == pid || waitret == -1) {
338                 ap_scoreboard_image->parent[i].pid = 0;
339                 continue;
340             }
341             ++not_dead_yet;
342             switch (tries) {
343             case 1:     /*  16ms */
344             case 2:     /*  82ms */
345                 break;
346             case 3:     /* 344ms */
347             case 4:     /*  16ms */
348             case 5:     /*  82ms */
349             case 6:     /* 344ms */
350             case 7:     /* 1.4sec */
351                 /* ok, now it's being annoying */
352                 ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING,
353                             0, server_conf,
354                    "child process %d still did not exit, sending a SIGTERM",
355                             pid);
356                 kill(pid, SIGTERM);
357                 break;
358             case 8:     /*  6 sec */
359                 /* die child scum */
360                 ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, server_conf,
361                    "child process %d still did not exit, sending a SIGKILL",
362                             pid);
363                 kill(pid, SIGKILL);
364                 break;
365             case 9:     /* 14 sec */
366                 /* gave it our best shot, but alas...  If this really 
367                  * is a child we are trying to kill and it really hasn't
368                  * exited, we will likely fail to bind to the port
369                  * after the restart.
370                  */
371                 ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, server_conf,
372                             "could not make child process %d exit, "
373                             "attempting to continue anyway", pid);
374                 break;
375             }
376         }
377 #ifdef HAS_OTHER_CHILD
378         for (ocr = other_children; ocr; ocr = nocr) {
379             nocr = ocr->next;
380             if (ocr->pid == -1)
381                 continue;
382
383             waitret = waitpid(ocr->pid, &status, WNOHANG);
384             if (waitret == ocr->pid) {
385                 ocr->pid = -1;
386                 (*ocr->maintenance) (OC_REASON_DEATH, ocr->data, status);
387             }
388             else if (waitret == 0) {
389                 (*ocr->maintenance) (OC_REASON_RESTART, ocr->data, -1);
390                 ++not_dead_yet;
391             }
392             else if (waitret == -1) {
393                 /* uh what the heck? they didn't call unregister? */
394                 ocr->pid = -1;
395                 (*ocr->maintenance) (OC_REASON_LOST, ocr->data, -1);
396             }
397         }
398 #endif
399         if (!not_dead_yet) {
400             /* nothing left to wait for */
401             break;
402         }
403     }
404 }
405
406 /* Finally, this routine is used by the caretaker process to wait for
407  * a while...
408  */
409
410 /* number of calls to wait_or_timeout between writable probes */
411 #ifndef INTERVAL_OF_WRITABLE_PROBES
412 #define INTERVAL_OF_WRITABLE_PROBES 10
413 #endif
414 static int wait_or_timeout_counter;
415
416 static int wait_or_timeout(ap_wait_t *status)
417 {
418     struct timeval tv;
419     int ret;
420
421     ++wait_or_timeout_counter;
422     if (wait_or_timeout_counter == INTERVAL_OF_WRITABLE_PROBES) {
423         wait_or_timeout_counter = 0;
424 #ifdef HAS_OTHER_CHILD
425         probe_writable_fds();
426 #endif
427     }
428     ret = waitpid(-1, status, WNOHANG);
429     if (ret == -1 && errno == EINTR) {
430         return -1;
431     }
432     if (ret > 0) {
433         return ret;
434     }
435     tv.tv_sec = SCOREBOARD_MAINTENANCE_INTERVAL / 1000000;
436     tv.tv_usec = SCOREBOARD_MAINTENANCE_INTERVAL % 1000000;
437     ap_select(0, NULL, NULL, NULL, &tv);
438     return -1;
439 }
440
441 /* handle all varieties of core dumping signals */
442 static void sig_coredump(int sig)
443 {
444     chdir(ap_coredump_dir);
445     signal(sig, SIG_DFL);
446     kill(my_pid, sig);
447     /* At this point we've got sig blocked, because we're still inside
448      * the signal handler.  When we leave the signal handler it will
449      * be unblocked, and we'll take the signal... and coredump or whatever
450      * is appropriate for this particular Unix.  In addition the parent
451      * will see the real signal we received -- whereas if we called
452      * abort() here, the parent would only see SIGABRT.
453      */
454 }
455
456 static void just_die(int sig)
457 {
458     clean_child_exit(0);
459 }
460
461 /*****************************************************************
462  * Connection structures and accounting...
463  */
464
465 /* volatile just in case */
466 static int volatile shutdown_pending;
467 static int volatile restart_pending;
468 static int volatile is_graceful;
469 ap_generation_t volatile ap_my_generation;
470
471 /*
472  * ap_start_shutdown() and ap_start_restart(), below, are a first stab at
473  * functions to initiate shutdown or restart without relying on signals. 
474  * Previously this was initiated in sig_term() and restart() signal handlers, 
475  * but we want to be able to start a shutdown/restart from other sources --
476  * e.g. on Win32, from the service manager. Now the service manager can
477  * call ap_start_shutdown() or ap_start_restart() as appropiate.  Note that
478  * these functions can also be called by the child processes, since global
479  * variables are no longer used to pass on the required action to the parent.
480  *
481  * These should only be called from the parent process itself, since the
482  * parent process will use the shutdown_pending and restart_pending variables
483  * to determine whether to shutdown or restart. The child process should
484  * call signal_parent() directly to tell the parent to die -- this will
485  * cause neither of those variable to be set, which the parent will
486  * assume means something serious is wrong (which it will be, for the
487  * child to force an exit) and so do an exit anyway.
488  */
489
490 void ap_start_shutdown(void)
491 {
492     if (shutdown_pending == 1) {
493         /* Um, is this _probably_ not an error, if the user has
494          * tried to do a shutdown twice quickly, so we won't
495          * worry about reporting it.
496          */
497         return;
498     }
499     shutdown_pending = 1;
500 }
501
502 /* do a graceful restart if graceful == 1 */
503 void ap_start_restart(int graceful)
504 {
505
506     if (restart_pending == 1) {
507         /* Probably not an error - don't bother reporting it */
508         return;
509     }
510     restart_pending = 1;
511     is_graceful = graceful;
512 }
513
514 static void sig_term(int sig)
515 {
516     ap_start_shutdown();
517 }
518
519 static void restart(int sig)
520 {
521 #ifndef WIN32
522     ap_start_restart(sig == SIGWINCH);
523 #else
524     ap_start_restart(1);
525 #endif
526 }
527
528 static void set_signals(void)
529 {
530 #ifndef NO_USE_SIGACTION
531     struct sigaction sa;
532
533     sigemptyset(&sa.sa_mask);
534     sa.sa_flags = 0;
535
536     if (!one_process) {
537         sa.sa_handler = sig_coredump;
538 #if defined(SA_ONESHOT)
539         sa.sa_flags = SA_ONESHOT;
540 #elif defined(SA_RESETHAND)
541         sa.sa_flags = SA_RESETHAND;
542 #endif
543         if (sigaction(SIGSEGV, &sa, NULL) < 0)
544             ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGSEGV)");
545 #ifdef SIGBUS
546         if (sigaction(SIGBUS, &sa, NULL) < 0)
547             ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGBUS)");
548 #endif
549 #ifdef SIGABORT
550         if (sigaction(SIGABORT, &sa, NULL) < 0)
551             ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGABORT)");
552 #endif
553 #ifdef SIGABRT
554         if (sigaction(SIGABRT, &sa, NULL) < 0)
555             ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGABRT)");
556 #endif
557 #ifdef SIGILL
558         if (sigaction(SIGILL, &sa, NULL) < 0)
559             ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGILL)");
560 #endif
561         sa.sa_flags = 0;
562     }
563     sa.sa_handler = sig_term;
564     if (sigaction(SIGTERM, &sa, NULL) < 0)
565         ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGTERM)");
566 #ifdef SIGINT
567     if (sigaction(SIGINT, &sa, NULL) < 0)
568         ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGINT)");
569 #endif
570 #ifdef SIGXCPU
571     sa.sa_handler = SIG_DFL;
572     if (sigaction(SIGXCPU, &sa, NULL) < 0)
573         ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGXCPU)");
574 #endif
575 #ifdef SIGXFSZ
576     sa.sa_handler = SIG_DFL;
577     if (sigaction(SIGXFSZ, &sa, NULL) < 0)
578         ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGXFSZ)");
579 #endif
580 #ifdef SIGPIPE
581     sa.sa_handler = SIG_IGN;
582     if (sigaction(SIGPIPE, &sa, NULL) < 0)
583         ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGPIPE)");
584 #endif
585
586     /* we want to ignore HUPs and WINCH while we're busy processing one */
587     sigaddset(&sa.sa_mask, SIGHUP);
588     sigaddset(&sa.sa_mask, SIGWINCH);
589     sa.sa_handler = restart;
590     if (sigaction(SIGHUP, &sa, NULL) < 0)
591         ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGHUP)");
592     if (sigaction(SIGWINCH, &sa, NULL) < 0)
593         ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGWINCH)");
594 #else
595     if (!one_process) {
596         signal(SIGSEGV, sig_coredump);
597 #ifdef SIGBUS
598         signal(SIGBUS, sig_coredump);
599 #endif /* SIGBUS */
600 #ifdef SIGABORT
601         signal(SIGABORT, sig_coredump);
602 #endif /* SIGABORT */
603 #ifdef SIGABRT
604         signal(SIGABRT, sig_coredump);
605 #endif /* SIGABRT */
606 #ifdef SIGILL
607         signal(SIGILL, sig_coredump);
608 #endif /* SIGILL */
609 #ifdef SIGXCPU
610         signal(SIGXCPU, SIG_DFL);
611 #endif /* SIGXCPU */
612 #ifdef SIGXFSZ
613         signal(SIGXFSZ, SIG_DFL);
614 #endif /* SIGXFSZ */
615     }
616
617     signal(SIGTERM, sig_term);
618 #ifdef SIGHUP
619     signal(SIGHUP, restart);
620 #endif /* SIGHUP */
621 #ifdef SIGWINCH
622     signal(SIGWINCH, restart);
623 #endif /* SIGWINCH */
624 #ifdef SIGPIPE
625     signal(SIGPIPE, SIG_IGN);
626 #endif /* SIGPIPE */
627
628 #endif
629 }
630
631 static void process_child_status(int pid, ap_wait_t status)
632 {
633     /* Child died... if it died due to a fatal error,
634         * we should simply bail out.
635         */
636     if ((WIFEXITED(status)) &&
637         WEXITSTATUS(status) == APEXIT_CHILDFATAL) {
638         ap_log_error(APLOG_MARK, APLOG_ALERT|APLOG_NOERRNO, 0, server_conf,
639                         "Child %d returned a Fatal error... \n"
640                         "Apache is exiting!",
641                         pid);
642         exit(APEXIT_CHILDFATAL);
643     }
644     if (WIFSIGNALED(status)) {
645         switch (WTERMSIG(status)) {
646         case SIGTERM:
647         case SIGHUP:
648         case SIGUSR1:
649         case SIGKILL:
650             break;
651         default:
652 #ifdef SYS_SIGLIST
653 #ifdef WCOREDUMP
654             if (WCOREDUMP(status)) {
655                 ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE,
656                              0, server_conf,
657                              "child pid %d exit signal %s (%d), "
658                              "possible coredump in %s",
659                              pid, (WTERMSIG(status) >= NumSIG) ? "" : 
660                              SYS_SIGLIST[WTERMSIG(status)], WTERMSIG(status),
661                              ap_coredump_dir);
662             }
663             else {
664 #endif
665                 ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE,
666                              0, server_conf,
667                              "child pid %d exit signal %s (%d)", pid,
668                              SYS_SIGLIST[WTERMSIG(status)], WTERMSIG(status));
669 #ifdef WCOREDUMP
670             }
671 #endif
672 #else
673             ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE,
674                          server_conf,
675                          "child pid %d exit signal %d",
676                          pid, WTERMSIG(status));
677 #endif
678         }
679     }
680 }
681
682 static int setup_listeners(server_rec *s)
683 {
684     ap_listen_rec *lr;
685     int num_listeners = 0;
686     if (ap_listen_open(s->process, s->port)) {
687        return 0;
688     }
689     for (lr = ap_listeners; lr; lr = lr->next) {
690         num_listeners++;
691     }
692     return num_listeners;
693 }
694
695 /*****************************************************************
696  * Here follows a long bunch of generic server bookkeeping stuff...
697  */
698
699 #if defined(TCP_NODELAY) && !defined(MPE) && !defined(TPF)
700 static void sock_disable_nagle(int s) 
701 {
702     /* The Nagle algorithm says that we should delay sending partial
703      * packets in hopes of getting more data.  We don't want to do
704      * this; we are not telnet.  There are bad interactions between
705      * persistent connections and Nagle's algorithm that have very severe
706      * performance penalties.  (Failing to disable Nagle is not much of a
707      * problem with simple HTTP.)
708      *
709      * In spite of these problems, failure here is not a shooting offense.
710      */
711     int just_say_no = 1;
712
713     if (setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (char *) &just_say_no,
714                    sizeof(int)) < 0) {
715         ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf,
716                     "setsockopt: (TCP_NODELAY)");
717     }
718 }
719
720 #else
721 #define sock_disable_nagle(s)   /* NOOP */
722 #endif
723
724 int ap_graceful_stop_signalled(void)
725 {
726     /* XXX - Does this really work? - Manoj */
727     return is_graceful;
728 }
729
730 /*****************************************************************
731  * Child process main loop.
732  */
733
734 static void process_socket(ap_context_t *p, ap_socket_t *sock, int my_child_num, int my_thread_num)
735 {
736     BUFF *conn_io;
737     conn_rec *current_conn;
738     ap_iol *iol;
739     long conn_id = my_child_num * HARD_THREAD_LIMIT + my_thread_num;
740     int csd;
741
742     (void) ap_get_os_sock(&csd, sock);
743
744     sock_disable_nagle(csd);
745
746     iol = unix_attach_socket(sock);
747     if (iol == NULL) {
748         if (errno == EBADF) {
749             ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, NULL,
750                 "filedescriptor (%u) larger than FD_SETSIZE (%u) "
751                 "found, you probably need to rebuild Apache with a "
752                 "larger FD_SETSIZE", csd, FD_SETSIZE);
753         }
754         else {
755             ap_log_error(APLOG_MARK, APLOG_WARNING, errno, NULL,
756                 "error attaching to socket");
757         }
758         ap_close_socket(sock);
759         return;
760     }
761
762     (void) ap_update_child_status(my_child_num, my_thread_num,  
763                                   SERVER_BUSY_READ, (request_rec *) NULL);
764     conn_io = ap_bcreate(p, B_RDWR);
765     ap_bpush_iol(conn_io, iol);
766
767     current_conn = ap_new_apr_connection(p, server_conf, conn_io, sock,
768                                          conn_id);
769
770     ap_process_connection(current_conn);
771 }
772 /* Sets workers_may_exit if we received a character on the pipe_of_death */
773 static void check_pipe_of_death(void)
774 {
775     pthread_mutex_lock(&pipe_of_death_mutex);
776     if (!workers_may_exit) {
777         ap_status_t ret;
778         char pipe_read_char;
779         int n=1;
780
781         ret = ap_recv(listensocks[0], &pipe_read_char, &n);
782         if (ret == APR_EAGAIN) {
783             /* It lost the lottery. It must continue to suffer
784              * through a life of servitude. */
785         }
786         else {
787             /* It won the lottery (or something else is very
788              * wrong). Embrace death with open arms. */
789             workers_may_exit = 1;
790         }
791     }
792     pthread_mutex_unlock(&pipe_of_death_mutex);
793 }
794
795 static void * worker_thread(void * dummy)
796 {
797     proc_info * ti = dummy;
798     int process_slot = ti->pid;
799     int thread_slot = ti->tid;
800     ap_context_t *tpool = ti->tpool;
801     ap_socket_t *csd = NULL;
802     ap_context_t *ptrans;               /* Pool for per-transaction stuff */
803     ap_socket_t *sd = NULL;
804     int n;
805     int curr_pollfd, last_pollfd = 0;
806     ap_pollfd_t *pollset;
807     ap_status_t rv;
808
809     free(ti);
810
811     ap_create_context(&ptrans, tpool);
812
813     pthread_mutex_lock(&worker_thread_count_mutex);
814     worker_thread_count++;
815     pthread_mutex_unlock(&worker_thread_count_mutex);
816
817     ap_setup_poll(&pollset, num_listensocks+1, tpool);
818     for(n=0 ; n <= num_listensocks ; ++n)
819         ap_add_poll_socket(pollset, listensocks[n], APR_POLLIN);
820
821     /* TODO: Switch to a system where threads reuse the results from earlier
822        poll calls - manoj */
823     while (!workers_may_exit) {
824         workers_may_exit |= (ap_max_requests_per_child != 0) && (requests_this_child <= 0);
825         if (workers_may_exit) break;
826
827         (void) ap_update_child_status(process_slot, thread_slot, SERVER_READY, 
828                                       (request_rec *) NULL);
829         pthread_mutex_lock(&thread_accept_mutex);
830         if (workers_may_exit) {
831             pthread_mutex_unlock(&thread_accept_mutex);
832             break;
833         }
834         if ((rv = SAFE_ACCEPT(ap_lock(process_accept_mutex)))
835             != APR_SUCCESS) {
836             ap_log_error(APLOG_MARK, APLOG_EMERG, rv, server_conf,
837                          "ap_lock failed. Attempting to shutdown "
838                          "process gracefully.");
839             workers_may_exit = 1;
840         }
841
842         while (!workers_may_exit) {
843             ap_status_t ret;
844             ap_int16_t event;
845
846             ret = ap_poll(pollset, &n, -1);
847             if (ret != APR_SUCCESS) {
848                 if (ret == APR_EINTR) {
849                     continue;
850                 }
851
852                 /* poll() will only return errors in catastrophic
853                  * circumstances. Let's try exiting gracefully, for now. */
854                 ap_log_error(APLOG_MARK, APLOG_ERR, errno, (const server_rec *)
855                              ap_get_server_conf(), "poll: (listen)");
856                 workers_may_exit = 1;
857             }
858
859             if (workers_may_exit) break;
860
861             ap_get_revents(&event, listensocks[0], pollset);
862             if (event & APR_POLLIN) {
863                 /* A process got a signal on the shutdown pipe. Check if we're
864                  * the lucky process to die. */
865                 check_pipe_of_death();
866                 continue;
867             }
868
869             if (num_listensocks == 1) {
870                 sd = ap_listeners->sd;
871                 goto got_fd;
872             }
873             else {
874                 /* find a listener */
875                 curr_pollfd = last_pollfd;
876                 do {
877                     curr_pollfd++;
878                     if (curr_pollfd > num_listensocks) {
879                         curr_pollfd = 1;
880                     }
881                     /* XXX: Should we check for POLLERR? */
882                     ap_get_revents(&event, listensocks[curr_pollfd], pollset);
883                     if (event & APR_POLLIN) {
884                         last_pollfd = curr_pollfd;
885                         sd=listensocks[curr_pollfd];
886                         goto got_fd;
887                     }
888                 } while (curr_pollfd != last_pollfd);
889             }
890         }
891     got_fd:
892         if (!workers_may_exit) {
893             ap_accept(&csd, sd, ptrans);
894             if ((rv = SAFE_ACCEPT(ap_unlock(process_accept_mutex)))
895                 != APR_SUCCESS) {
896                 ap_log_error(APLOG_MARK, APLOG_EMERG, rv, server_conf,
897                              "ap_unlock failed. Attempting to shutdown "
898                              "process gracefully.");
899                 workers_may_exit = 1;
900             }
901             pthread_mutex_unlock(&thread_accept_mutex);
902             process_socket(ptrans, csd, process_slot, thread_slot);
903             requests_this_child--;
904         }
905         else {
906             if ((rv = SAFE_ACCEPT(ap_unlock(process_accept_mutex)))
907                 != APR_SUCCESS) {
908                 ap_log_error(APLOG_MARK, APLOG_EMERG, rv, server_conf,
909                              "ap_unlock failed. Attempting to shutdown "
910                              "process gracefully.");
911                 workers_may_exit = 1;
912             }
913             pthread_mutex_unlock(&thread_accept_mutex);
914             break;
915         }
916         ap_clear_pool(ptrans);
917     }
918
919     ap_destroy_pool(tpool);
920     ap_update_child_status(process_slot, thread_slot, SERVER_DEAD,
921         (request_rec *) NULL);
922     pthread_mutex_lock(&worker_thread_count_mutex);
923     worker_thread_count--;
924     if (worker_thread_count == 0) {
925         /* All the threads have exited, now finish the shutdown process
926          * by signalling the sigwait thread */
927         kill(my_pid, SIGTERM);
928     }
929     pthread_mutex_unlock(&worker_thread_count_mutex);
930
931     return NULL;
932 }
933
934
935 static void child_main(int child_num_arg)
936 {
937     sigset_t sig_mask;
938     int signal_received;
939     pthread_t thread;
940     pthread_attr_t thread_attr;
941     int i;
942     int my_child_num = child_num_arg;
943     proc_info *my_info = NULL;
944     ap_listen_rec *lr;
945     ap_status_t rv;
946
947
948     my_pid = getpid();
949     ap_create_context(&pchild, pconf);
950
951     /*stuff to do before we switch id's, so we have permissions.*/
952     reopen_scoreboard(pchild);
953
954     rv = SAFE_ACCEPT(ap_child_init_lock(&process_accept_mutex, lock_fname,
955                      pchild));
956     if (rv != APR_SUCCESS) {
957         ap_log_error(APLOG_MARK, APLOG_EMERG, rv, server_conf,
958                      "Couldn't initialize cross-process lock in child");
959         clean_child_exit(APEXIT_CHILDFATAL);
960     }
961
962     if (unixd_setup_child()) {
963         clean_child_exit(APEXIT_CHILDFATAL);
964     }
965
966     ap_child_init_hook(pchild, server_conf);
967
968     /*done with init critical section */
969
970     /* All threads should mask signals out, accoring to sigwait(2) man page */
971     sigfillset(&sig_mask);
972
973     if (pthread_sigmask(SIG_SETMASK, &sig_mask, NULL) != 0) {
974         ap_log_error(APLOG_MARK, APLOG_ALERT, errno, server_conf, "pthread_sigmask");
975     }
976
977     requests_this_child = ap_max_requests_per_child;
978     
979     /* Set up the pollfd array */
980     listensocks = ap_palloc(pchild,
981                             sizeof(*listensocks) * (num_listensocks + 1));
982     ap_create_tcp_socket(&listensocks[0], pchild);
983     ap_put_os_sock(&listensocks[0], &pipe_of_death[0], pchild);
984     for (lr = ap_listeners, i = 1; i <= num_listensocks; lr = lr->next, ++i)
985         listensocks[i]=lr->sd;
986
987     /* Setup worker threads */
988
989     worker_thread_count = 0;
990     pthread_mutex_init(&worker_thread_count_mutex, NULL);
991     pthread_mutex_init(&pipe_of_death_mutex, NULL);
992     pthread_attr_init(&thread_attr);
993     pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
994     for (i=0; i < ap_threads_per_child; i++) {
995
996         my_info = (proc_info *)malloc(sizeof(proc_info));
997         if (my_info == NULL) {
998             ap_log_error(APLOG_MARK, APLOG_ALERT, errno, server_conf,
999                          "malloc: out of memory");
1000             clean_child_exit(APEXIT_CHILDFATAL);
1001         }
1002         my_info->pid = my_child_num;
1003         my_info->tid = i;
1004         my_info->sd = 0;
1005         ap_create_context(&my_info->tpool, pchild);
1006         
1007         /* We are creating threads right now */
1008         (void) ap_update_child_status(my_child_num, i, SERVER_STARTING, 
1009                                       (request_rec *) NULL);
1010 #ifndef NO_THREADS
1011         if (pthread_create(&thread, &thread_attr, worker_thread, my_info)) {
1012             ap_log_error(APLOG_MARK, APLOG_ALERT, errno, server_conf,
1013                          "pthread_create: unable to create worker thread");
1014             /* In case system resources are maxxed out, we don't want
1015                Apache running away with the CPU trying to fork over and
1016                over and over again if we exit. */
1017             sleep(10);
1018             clean_child_exit(APEXIT_CHILDFATAL);
1019         }
1020 #else
1021         worker_thread(my_info);
1022         /* The SIGTERM shouldn't let us reach this point, but just in case... */
1023         clean_child_exit(APEXIT_OK);
1024 #endif
1025
1026         /* We let each thread update it's own scoreboard entry.  This is done
1027          * because it let's us deal with tid better.
1028          */
1029     }
1030
1031     pthread_attr_destroy(&thread_attr);
1032
1033     /* This thread will be the one responsible for handling signals */
1034     sigemptyset(&sig_mask);
1035     sigaddset(&sig_mask, SIGTERM);
1036     sigaddset(&sig_mask, SIGINT);
1037     sigwait(&sig_mask, &signal_received);
1038     switch (signal_received) {
1039         case SIGTERM:
1040         case SIGINT:
1041             just_die(signal_received);
1042             break;
1043         default:
1044             ap_log_error(APLOG_MARK, APLOG_ALERT, errno, server_conf,
1045             "received impossible signal: %d", signal_received);
1046             just_die(SIGTERM);
1047     }
1048 }
1049
1050 static int make_child(server_rec *s, int slot, time_t now) 
1051 {
1052     int pid;
1053
1054     if (slot + 1 > max_daemons_limit) {
1055         max_daemons_limit = slot + 1;
1056     }
1057
1058     if (one_process) {
1059         set_signals();
1060         ap_scoreboard_image->parent[slot].pid = getpid();
1061         child_main(slot);
1062     }
1063
1064     /* Tag this slot as occupied so that perform_idle_server_maintenance
1065      * doesn't try to steal it */
1066     (void) ap_update_child_status(slot, 0, SERVER_STARTING, (request_rec *) NULL);
1067
1068     if ((pid = fork()) == -1) {
1069         ap_log_error(APLOG_MARK, APLOG_ERR, errno, s, "fork: Unable to fork new process");
1070
1071         /* fork didn't succeed. Fix the scoreboard or else
1072          * it will say SERVER_STARTING forever and ever
1073          */
1074         (void) ap_update_child_status(slot, 0, SERVER_DEAD, (request_rec *) NULL);
1075
1076         /* In case system resources are maxxed out, we don't want
1077            Apache running away with the CPU trying to fork over and
1078            over and over again. */
1079         sleep(10);
1080
1081         return -1;
1082     }
1083
1084     if (!pid) {
1085 #ifdef AIX_BIND_PROCESSOR
1086       /* By default, AIX binds to a single processor.  This bit unbinds
1087          children which will then bind to another CPU.
1088       */
1089 #include <sys/processor.h>
1090         int status = bindprocessor(BINDPROCESS, (int)getpid(),
1091                                PROCESSOR_CLASS_ANY);
1092         if (status != OK)
1093             ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, server_conf,
1094                          "processor unbind failed %d", status);
1095 #endif
1096
1097         RAISE_SIGSTOP(MAKE_CHILD);
1098
1099         signal(SIGTERM, just_die);
1100         child_main(slot);
1101
1102         return 0;
1103     }
1104     /* else */
1105     ap_scoreboard_image->parent[slot].pid = pid;
1106     return 0;
1107 }
1108
1109 /* start up a bunch of children */
1110 static void startup_children(int number_to_start)
1111 {
1112     int i;
1113
1114     for (i = 0; number_to_start && i < ap_daemons_limit; ++i) {
1115         if (ap_scoreboard_image->parent[i].pid != 0) {
1116             continue;
1117         }
1118         if (make_child(server_conf, i, 0) < 0) {
1119             break;
1120         }
1121         --number_to_start;
1122     }
1123 }
1124
1125
1126 /*
1127  * idle_spawn_rate is the number of children that will be spawned on the
1128  * next maintenance cycle if there aren't enough idle servers.  It is
1129  * doubled up to MAX_SPAWN_RATE, and reset only when a cycle goes by
1130  * without the need to spawn.
1131  */
1132 static int idle_spawn_rate = 1;
1133 #ifndef MAX_SPAWN_RATE
1134 #define MAX_SPAWN_RATE  (32)
1135 #endif
1136 static int hold_off_on_exponential_spawning;
1137
1138 static void perform_idle_server_maintenance(void)
1139 {
1140     int i, j;
1141     int idle_thread_count;
1142     thread_score *ss;
1143     time_t now = 0;
1144     int free_length;
1145     int free_slots[MAX_SPAWN_RATE];
1146     int last_non_dead;
1147     int total_non_dead;
1148
1149     /* initialize the free_list */
1150     free_length = 0;
1151
1152     idle_thread_count = 0;
1153     last_non_dead = -1;
1154     total_non_dead = 0;
1155
1156     ap_sync_scoreboard_image();
1157     for (i = 0; i < ap_daemons_limit; ++i) {
1158         /* Initialization to satisfy the compiler. It doesn't know
1159          * that ap_threads_per_child is always > 0 */
1160         int status = SERVER_DEAD;
1161         int any_dying_threads = 0;
1162         int all_dead_threads = 1;
1163         int idle_thread_addition = 0;
1164
1165         if (i >= max_daemons_limit && free_length == idle_spawn_rate)
1166             break;
1167         for (j = 0; j < ap_threads_per_child; j++) {
1168             ss = &ap_scoreboard_image->servers[i][j];
1169             status = ss->status;
1170
1171             any_dying_threads = any_dying_threads || (status == SERVER_DEAD)
1172                                     || (status == SERVER_GRACEFUL);
1173             all_dead_threads = all_dead_threads && (status == SERVER_DEAD);
1174
1175             /* We consider a starting server as idle because we started it
1176              * at least a cycle ago, and if it still hasn't finished starting
1177              * then we're just going to swamp things worse by forking more.
1178              * So we hopefully won't need to fork more if we count it.
1179              * This depends on the ordering of SERVER_READY and SERVER_STARTING.
1180              */
1181             if (status <= SERVER_READY) {
1182                 ++idle_thread_addition;
1183             }
1184         }
1185         if (all_dead_threads && free_length < idle_spawn_rate) {
1186             free_slots[free_length] = i;
1187             ++free_length;
1188         }
1189         if (!all_dead_threads) {
1190             last_non_dead = i;
1191         }
1192         if (!any_dying_threads) {
1193             ++total_non_dead;
1194             idle_thread_count += idle_thread_addition;
1195         }
1196     }
1197     max_daemons_limit = last_non_dead + 1;
1198
1199     if (idle_thread_count > max_spare_threads) {
1200         /* Kill off one child */
1201         char char_of_death = '!';
1202         if (write(pipe_of_death[1], &char_of_death, 1) == -1) {
1203             ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "write pipe_of_death");
1204         }
1205         idle_spawn_rate = 1;
1206     }
1207     else if (idle_thread_count < min_spare_threads) {
1208         /* terminate the free list */
1209         if (free_length == 0) {
1210             /* only report this condition once */
1211             static int reported = 0;
1212             
1213             if (!reported) {
1214                 ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, server_conf,
1215                              "server reached MaxClients setting, consider"
1216                              " raising the MaxClients setting");
1217                 reported = 1;
1218             }
1219             idle_spawn_rate = 1;
1220         }
1221         else {
1222             
1223             if (idle_spawn_rate >= 8) {
1224                 ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0, server_conf,
1225                              "server seems busy, (you may need "
1226                              "to increase StartServers, ThreadsPerChild "
1227                              "or Min/MaxSparetThreads), "
1228                              "spawning %d children, there are around %d idle "
1229                              "threads, and %d total children", idle_spawn_rate,
1230                              idle_thread_count, total_non_dead);
1231             }
1232             for (i = 0; i < free_length; ++i) {
1233                 make_child(server_conf, free_slots[i], now);
1234             }
1235             /* the next time around we want to spawn twice as many if this
1236              * wasn't good enough, but not if we've just done a graceful
1237              */
1238             if (hold_off_on_exponential_spawning) {
1239                 --hold_off_on_exponential_spawning;
1240             }
1241             else if (idle_spawn_rate < MAX_SPAWN_RATE) {
1242                 idle_spawn_rate *= 2;
1243             }
1244         }
1245     }
1246     else {
1247       idle_spawn_rate = 1;
1248     }
1249 }
1250
1251 static void server_main_loop(int remaining_children_to_start)
1252 {
1253     int child_slot;
1254     ap_wait_t status;
1255     int pid;
1256     int i;
1257
1258     while (!restart_pending && !shutdown_pending) {
1259         pid = wait_or_timeout(&status);
1260         
1261         if (pid >= 0) {
1262             process_child_status(pid, status);
1263             /* non-fatal death... note that it's gone in the scoreboard. */
1264             child_slot = find_child_by_pid(pid);
1265             if (child_slot >= 0) {
1266                 for (i = 0; i < ap_threads_per_child; i++)
1267                     ap_update_child_status(child_slot, i, SERVER_DEAD, (request_rec *) NULL);
1268                 
1269                 if (remaining_children_to_start
1270                     && child_slot < ap_daemons_limit) {
1271                     /* we're still doing a 1-for-1 replacement of dead
1272                      * children with new children
1273                      */
1274                     make_child(server_conf, child_slot, time(NULL));
1275                     --remaining_children_to_start;
1276                 }
1277 #ifdef HAS_OTHER_CHILD
1278             }
1279             else if (reap_other_child(pid, status) == 0) {
1280                 /* handled */
1281 #endif
1282             }
1283             else if (is_graceful) {
1284                 /* Great, we've probably just lost a slot in the
1285                     * scoreboard.  Somehow we don't know about this
1286                     * child.
1287                     */
1288                 ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, server_conf,
1289                             "long lost child came home! (pid %d)", pid);
1290             }
1291             /* Don't perform idle maintenance when a child dies,
1292              * only do it when there's a timeout.  Remember only a
1293              * finite number of children can die, and it's pretty
1294              * pathological for a lot to die suddenly.
1295              */
1296             continue;
1297         }
1298         else if (remaining_children_to_start) {
1299             /* we hit a 1 second timeout in which none of the previous
1300              * generation of children needed to be reaped... so assume
1301              * they're all done, and pick up the slack if any is left.
1302              */
1303             startup_children(remaining_children_to_start);
1304             remaining_children_to_start = 0;
1305             /* In any event we really shouldn't do the code below because
1306              * few of the servers we just started are in the IDLE state
1307              * yet, so we'd mistakenly create an extra server.
1308              */
1309             continue;
1310         }
1311
1312         perform_idle_server_maintenance();
1313     }
1314 }
1315
1316 int ap_mpm_run(ap_context_t *_pconf, ap_context_t *plog, server_rec *s)
1317 {
1318     int remaining_children_to_start;
1319     ap_status_t rv;
1320
1321     pconf = _pconf;
1322     server_conf = s;
1323     if (pipe(pipe_of_death) == -1) {
1324         ap_log_error(APLOG_MARK, APLOG_ERR, errno,
1325                      (const server_rec*) server_conf,
1326                      "pipe: (pipe_of_death)");
1327         exit(1);
1328     }
1329 /*  XXXXXX  Removed because these functions don't exist anymore.  When
1330     These pipes are changed to apr_types, these functions won't be needed
1331     anyway.
1332     ap_note_cleanups_for_fd(pconf, pipe_of_death[0]);
1333     ap_note_cleanups_for_fd(pconf, pipe_of_death[1]);
1334 */
1335
1336     if (fcntl(pipe_of_death[0], F_SETFD, O_NONBLOCK) == -1) {
1337         ap_log_error(APLOG_MARK, APLOG_ERR, errno,
1338                      (const server_rec*) server_conf,
1339                      "fcntl: O_NONBLOCKing (pipe_of_death)");
1340         exit(1);
1341     }
1342     server_conf = s;
1343     if ((num_listensocks = setup_listeners(server_conf)) < 1) {
1344         /* XXX: hey, what's the right way for the mpm to indicate a fatal error? */
1345         ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ALERT, 0, s,
1346             "no listening sockets available, shutting down");
1347         return 1;
1348     }
1349     ap_log_pid(pconf, ap_pid_fname);
1350
1351     /* Initialize cross-process accept lock */
1352     lock_fname = ap_psprintf(_pconf, "%s.%lu",
1353                              ap_server_root_relative(_pconf, lock_fname),
1354                              my_pid);
1355     rv = ap_create_lock(&process_accept_mutex, APR_MUTEX, APR_CROSS_PROCESS,
1356                    lock_fname, _pconf);
1357     if (rv != APR_SUCCESS) {
1358         ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s,
1359                      "Couldn't create cross-process lock");
1360         return 1;
1361     }
1362
1363
1364     if (!is_graceful) {
1365         reinit_scoreboard(pconf);
1366     }
1367
1368     set_signals();
1369     /* Don't thrash... */
1370     if (max_spare_threads < min_spare_threads + ap_threads_per_child)
1371         max_spare_threads = min_spare_threads + ap_threads_per_child;
1372
1373     /* If we're doing a graceful_restart then we're going to see a lot
1374      * of children exiting immediately when we get into the main loop
1375      * below (because we just sent them SIGWINCH).  This happens pretty
1376      * rapidly... and for each one that exits we'll start a new one until
1377      * we reach at least daemons_min_free.  But we may be permitted to
1378      * start more than that, so we'll just keep track of how many we're
1379      * supposed to start up without the 1 second penalty between each fork.
1380      */
1381     remaining_children_to_start = ap_daemons_to_start;
1382     if (remaining_children_to_start > ap_daemons_limit) {
1383         remaining_children_to_start = ap_daemons_limit;
1384     }
1385     if (!is_graceful) {
1386         startup_children(remaining_children_to_start);
1387         remaining_children_to_start = 0;
1388     }
1389     else {
1390         /* give the system some time to recover before kicking into
1391             * exponential mode */
1392         hold_off_on_exponential_spawning = 10;
1393     }
1394
1395     ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, server_conf,
1396                 "%s configured -- resuming normal operations",
1397                 ap_get_server_version());
1398     ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0, server_conf,
1399                 "Server built: %s", ap_get_server_built());
1400     restart_pending = shutdown_pending = 0;
1401
1402     server_main_loop(remaining_children_to_start);
1403
1404     if (shutdown_pending) {
1405         /* Time to gracefully shut down:
1406          * Kill child processes, tell them to call child_exit, etc...
1407          */
1408         if (unixd_killpg(getpgrp(), SIGTERM) < 0) {
1409             ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "killpg SIGTERM");
1410         }
1411         reclaim_child_processes(1);             /* Start with SIGTERM */
1412     
1413         /* cleanup pid file on normal shutdown */
1414         {
1415             const char *pidfile = NULL;
1416             pidfile = ap_server_root_relative (pconf, ap_pid_fname);
1417             if ( pidfile != NULL && unlink(pidfile) == 0)
1418                 ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0,
1419                          server_conf,
1420                          "removed PID file %s (pid=%ld)",
1421                          pidfile, (long)getpid());
1422         }
1423     
1424         ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, server_conf,
1425             "caught SIGTERM, shutting down");
1426     
1427         return 1;
1428     }
1429
1430     /* we've been told to restart */
1431     signal(SIGHUP, SIG_IGN);
1432
1433     if (one_process) {
1434         /* not worth thinking about */
1435         return 1;
1436     }
1437
1438     /* advance to the next generation */
1439     /* XXX: we really need to make sure this new generation number isn't in
1440      * use by any of the children.
1441      */
1442     ++ap_my_generation;
1443     ap_scoreboard_image->global.running_generation = ap_my_generation;
1444     update_scoreboard_global();
1445
1446     if (is_graceful) {
1447         int i, j;
1448         char char_of_death = '!';
1449
1450         ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, server_conf,
1451                     "SIGWINCH received.  Doing graceful restart");
1452
1453         /* give the children the signal to die */
1454         for (i = 0; i < ap_daemons_limit;) {
1455             if (write(pipe_of_death[1], &char_of_death, 1) == -1) {
1456                 if (errno == EINTR) continue;
1457                 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "write pipe_of_death");
1458             }
1459             i++;
1460         }
1461
1462         /* This is mostly for debugging... so that we know what is still
1463          * gracefully dealing with existing request.
1464          */
1465         
1466         for (i = 0; i < ap_daemons_limit; ++i) {
1467             for (j = 0; j < ap_threads_per_child; j++) { 
1468                 if (ap_scoreboard_image->servers[i][j].status != SERVER_DEAD) {
1469                     ap_scoreboard_image->servers[i][j].status = SERVER_GRACEFUL;
1470                 }
1471             } 
1472         }
1473     }
1474     else {
1475       /* Kill 'em all.  Since the child acts the same on the parents SIGTERM 
1476        * and a SIGHUP, we may as well use the same signal, because some user
1477        * pthreads are stealing signals from us left and right.
1478        */
1479         if (unixd_killpg(getpgrp(), SIGTERM) < 0) {
1480             ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "killpg SIGTERM");
1481         }
1482         reclaim_child_processes(1);             /* Start with SIGTERM */
1483         ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, server_conf,
1484                     "SIGHUP received.  Attempting to restart");
1485     }
1486     if (!is_graceful) {
1487         ap_restart_time = time(NULL); 
1488     }
1489     return 0;
1490 }
1491
1492 static void mpmt_pthread_pre_config(ap_context_t *pconf, ap_context_t *plog, ap_context_t *ptemp)
1493 {
1494     static int restart_num = 0;
1495
1496     one_process = !!getenv("ONE_PROCESS");
1497
1498     /* sigh, want this only the second time around */
1499     if (restart_num++ == 1) {
1500         is_graceful = 0;
1501
1502         if (!one_process) {
1503             unixd_detach();
1504         }
1505         my_pid = getpid();
1506     }
1507
1508     unixd_pre_config();
1509     ap_listen_pre_config();
1510     ap_daemons_to_start = DEFAULT_START_DAEMON;
1511     min_spare_threads = DEFAULT_MIN_FREE_DAEMON * DEFAULT_THREADS_PER_CHILD;
1512     max_spare_threads = DEFAULT_MAX_FREE_DAEMON * DEFAULT_THREADS_PER_CHILD;
1513     ap_daemons_limit = HARD_SERVER_LIMIT;
1514     ap_threads_per_child = DEFAULT_THREADS_PER_CHILD;
1515     ap_pid_fname = DEFAULT_PIDLOG;
1516     ap_scoreboard_fname = DEFAULT_SCOREBOARD;
1517     lock_fname = DEFAULT_LOCKFILE;
1518     ap_max_requests_per_child = DEFAULT_MAX_REQUESTS_PER_CHILD;
1519     ap_extended_status = 0;
1520
1521     ap_cpystrn(ap_coredump_dir, ap_server_root, sizeof(ap_coredump_dir));
1522 }
1523
1524 static void mpmt_pthread_hooks(void)
1525 {
1526     ap_hook_pre_config(mpmt_pthread_pre_config,NULL,NULL,HOOK_MIDDLE);
1527     INIT_SIGLIST()
1528     one_process = 0;
1529 }
1530
1531
1532 static const char *set_pidfile(cmd_parms *cmd, void *dummy, char *arg) 
1533 {
1534     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
1535     if (err != NULL) {
1536         return err;
1537     }
1538
1539     if (cmd->server->is_virtual) {
1540         return "PidFile directive not allowed in <VirtualHost>";
1541     }
1542     ap_pid_fname = arg;
1543     return NULL;
1544 }
1545
1546 static const char *set_scoreboard(cmd_parms *cmd, void *dummy, char *arg) 
1547 {
1548     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
1549     if (err != NULL) {
1550         return err;
1551     }
1552
1553     ap_scoreboard_fname = arg;
1554     return NULL;
1555 }
1556
1557 static const char *set_lockfile(cmd_parms *cmd, void *dummy, char *arg) 
1558 {
1559     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
1560     if (err != NULL) {
1561         return err;
1562     }
1563
1564     lock_fname = arg;
1565     return NULL;
1566 }
1567
1568 static const char *set_daemons_to_start(cmd_parms *cmd, void *dummy, char *arg) 
1569 {
1570     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
1571     if (err != NULL) {
1572         return err;
1573     }
1574
1575     ap_daemons_to_start = atoi(arg);
1576     return NULL;
1577 }
1578
1579 static const char *set_min_spare_threads(cmd_parms *cmd, void *dummy, char *arg)
1580 {
1581     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
1582     if (err != NULL) {
1583         return err;
1584     }
1585
1586     min_spare_threads = atoi(arg);
1587     if (min_spare_threads <= 0) {
1588        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
1589                     "WARNING: detected MinSpareThreads set to non-positive.");
1590        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
1591                     "Resetting to 1 to avoid almost certain Apache failure.");
1592        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
1593                     "Please read the documentation.");
1594        min_spare_threads = 1;
1595     }
1596        
1597     return NULL;
1598 }
1599
1600 static const char *set_max_spare_threads(cmd_parms *cmd, void *dummy, char *arg)
1601 {
1602     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
1603     if (err != NULL) {
1604         return err;
1605     }
1606
1607     max_spare_threads = atoi(arg);
1608     return NULL;
1609 }
1610
1611 static const char *set_server_limit (cmd_parms *cmd, void *dummy, char *arg) 
1612 {
1613     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
1614     if (err != NULL) {
1615         return err;
1616     }
1617
1618     ap_daemons_limit = atoi(arg);
1619     if (ap_daemons_limit > HARD_SERVER_LIMIT) {
1620        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
1621                     "WARNING: MaxClients of %d exceeds compile time limit "
1622                     "of %d servers,", ap_daemons_limit, HARD_SERVER_LIMIT);
1623        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
1624                     " lowering MaxClients to %d.  To increase, please "
1625                     "see the", HARD_SERVER_LIMIT);
1626        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
1627                     " HARD_SERVER_LIMIT define in src/include/httpd.h.");
1628        ap_daemons_limit = HARD_SERVER_LIMIT;
1629     } 
1630     else if (ap_daemons_limit < 1) {
1631         ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, "WARNING: Require MaxClients > 0, setting to 1\n");
1632         ap_daemons_limit = 1;
1633     }
1634     return NULL;
1635 }
1636
1637 static const char *set_threads_per_child (cmd_parms *cmd, void *dummy, char *arg) 
1638 {
1639     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
1640     if (err != NULL) {
1641         return err;
1642     }
1643
1644     ap_threads_per_child = atoi(arg);
1645     if (ap_threads_per_child > HARD_THREAD_LIMIT) {
1646         ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
1647                      "WARNING: ThreadsPerChild of %d exceeds compile time"
1648                      "limit of %d threads,", ap_threads_per_child,
1649                      HARD_THREAD_LIMIT);
1650         ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
1651                      " lowering ThreadsPerChild to %d. To increase, please"
1652                      "see the", HARD_THREAD_LIMIT);
1653         ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
1654                      " HARD_THREAD_LIMIT define in src/include/httpd.h.");
1655     }
1656     else if (ap_threads_per_child < 1) {
1657         ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
1658                      "WARNING: Require ThreadsPerChild > 0, setting to 1");
1659         ap_threads_per_child = 1;
1660     }
1661     return NULL;
1662 }
1663
1664 static const char *set_max_requests(cmd_parms *cmd, void *dummy, char *arg) 
1665 {
1666     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
1667     if (err != NULL) {
1668         return err;
1669     }
1670
1671     ap_max_requests_per_child = atoi(arg);
1672
1673     return NULL;
1674 }
1675
1676 static const char *set_coredumpdir (cmd_parms *cmd, void *dummy, char *arg) 
1677 {
1678     struct stat finfo;
1679     const char *fname;
1680     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
1681     if (err != NULL) {
1682         return err;
1683     }
1684
1685     fname = ap_server_root_relative(cmd->pool, arg);
1686     if ((stat(fname, &finfo) == -1) || !S_ISDIR(finfo.st_mode)) {
1687         return ap_pstrcat(cmd->pool, "CoreDumpDirectory ", fname, 
1688                           " does not exist or is not a directory", NULL);
1689     }
1690     ap_cpystrn(ap_coredump_dir, fname, sizeof(ap_coredump_dir));
1691     return NULL;
1692 }
1693
1694 static const command_rec mpmt_pthread_cmds[] = {
1695 UNIX_DAEMON_COMMANDS
1696 LISTEN_COMMANDS
1697 { "PidFile", set_pidfile, NULL, RSRC_CONF, TAKE1,
1698     "A file for logging the server process ID"},
1699 { "ScoreBoardFile", set_scoreboard, NULL, RSRC_CONF, TAKE1,
1700     "A file for Apache to maintain runtime process management information"},
1701 { "LockFile", set_lockfile, NULL, RSRC_CONF, TAKE1,
1702     "The lockfile used when Apache needs to lock the accept() call"},
1703 { "StartServers", set_daemons_to_start, NULL, RSRC_CONF, TAKE1,
1704   "Number of child processes launched at server startup" },
1705 { "MinSpareThreads", set_min_spare_threads, NULL, RSRC_CONF, TAKE1,
1706   "Minimum number of idle children, to handle request spikes" },
1707 { "MaxSpareThreads", set_max_spare_threads, NULL, RSRC_CONF, TAKE1,
1708   "Maximum number of idle children" },
1709 { "MaxClients", set_server_limit, NULL, RSRC_CONF, TAKE1,
1710   "Maximum number of children alive at the same time" },
1711 { "ThreadsPerChild", set_threads_per_child, NULL, RSRC_CONF, TAKE1,
1712   "Number of threads each child creates" },
1713 { "MaxRequestsPerChild", set_max_requests, NULL, RSRC_CONF, TAKE1,
1714   "Maximum number of requests a particular child serves before dying." },
1715 { "CoreDumpDirectory", set_coredumpdir, NULL, RSRC_CONF, TAKE1,
1716   "The location of the directory Apache changes to before dumping core" },
1717 { NULL }
1718 };
1719
1720 module MODULE_VAR_EXPORT mpm_mpmt_pthread_module = {
1721     STANDARD20_MODULE_STUFF,
1722     NULL,                       /* create per-directory config structure */
1723     NULL,                       /* merge per-directory config structures */
1724     NULL,                       /* create per-server config structure */
1725     NULL,                       /* merge per-server config structures */
1726     mpmt_pthread_cmds,          /* command ap_table_t */
1727     NULL,                       /* handlers */
1728     mpmt_pthread_hooks          /* register_hooks */
1729 };
1730