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