prefork.c revision fda1a61aacb6950953b7393b845b0639d8e87359
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele/* Licensed to the Apache Software Foundation (ASF) under one or more
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * contributor license agreements. See the NOTICE file distributed with
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * this work for additional information regarding copyright ownership.
5f5d1b4cc970b7f06ff8ef6526128e9a27303d88nd * The ASF licenses this file to You under the Apache License, Version 2.0
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * (the "License"); you may not use this file except in compliance with
1aa933455fcd538b1ee573f4566e1a78a89fce77nd * the License. You may obtain a copy of the License at
db479b48bd4d75423ed4a45e15b75089d1a8ad72fielding * Unless required by applicable law or agreed to in writing, software
db479b48bd4d75423ed4a45e15b75089d1a8ad72fielding * distributed under the License is distributed on an "AS IS" BASIS,
db479b48bd4d75423ed4a45e15b75089d1a8ad72fielding * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1aa933455fcd538b1ee573f4566e1a78a89fce77nd * See the License for the specific language governing permissions and
1aa933455fcd538b1ee573f4566e1a78a89fce77nd * limitations under the License.
aa8cf57195dfb7fa3d0baedf81f8be377946cea8slive/* Limit on the total --- clients will be locked out if more servers than
aa8cf57195dfb7fa3d0baedf81f8be377946cea8slive * this are needed. It is intended solely to keep the server from crashing
aa8cf57195dfb7fa3d0baedf81f8be377946cea8slive * when things get out of hand.
aa8cf57195dfb7fa3d0baedf81f8be377946cea8slive * We keep a hard maximum number of servers, for two reasons --- first off,
c6f41bc69d643835804e7e831776d3d46c6f5962slive * in case something goes seriously wrong, we want to stop the fork bomb
c6f41bc69d643835804e7e831776d3d46c6f5962slive * short of actually crashing the machine we're running on by filling some
c6f41bc69d643835804e7e831776d3d46c6f5962slive * kernel table. Secondly, it keeps the size of the scoreboard file small
c6f41bc69d643835804e7e831776d3d46c6f5962slive * enough that we can read the whole thing without worrying too much about
d7604f90897d9b08b227c127ff5392393178911crpluem * the overhead.
aa8cf57195dfb7fa3d0baedf81f8be377946cea8slive/* Admin can't tune ServerLimit beyond MAX_SERVER_LIMIT. We want
263168fdb45221efa79580de89bdde883b7561f7sf * some sort of compile-time limit to help catch typos.
d7604f90897d9b08b227c127ff5392393178911crpluem/* config globals */
d7604f90897d9b08b227c127ff5392393178911crpluemstatic int server_limit = 0;
c6f41bc69d643835804e7e831776d3d46c6f5962slive/* data retained by prefork across load/unload of the module
c6f41bc69d643835804e7e831776d3d46c6f5962slive * allocated on first call to pre-config hook; located on
06d77ae37da42a6f8bbea25b7d7f8b6629245629slive * subsequent calls to pre-config hook
c6f41bc69d643835804e7e831776d3d46c6f5962slivetypedef struct prefork_retained_data {
aa8cf57195dfb7fa3d0baedf81f8be377946cea8slive#define MPM_CHILD_PID(i) (ap_scoreboard_image->parent[i].pid)
aa8cf57195dfb7fa3d0baedf81f8be377946cea8slive * The max child slot ever assigned, preserved across restarts. Necessary
aa8cf57195dfb7fa3d0baedf81f8be377946cea8slive * to deal with MaxClients changes across AP_SIG_GRACEFUL restarts. We
3fa816e4832a1c70600bdfd6fc5ef60e9f1c18bbsf * use this value to optimize routines that have to scan the entire scoreboard.
aa8cf57195dfb7fa3d0baedf81f8be377946cea8slive/* one_process --- debugging mode variable; can be set from the command line
aa8cf57195dfb7fa3d0baedf81f8be377946cea8slive * with the -X flag. If set, this gets you the child_main loop running
aa8cf57195dfb7fa3d0baedf81f8be377946cea8slive * in the process which originally started up (no detach, no make_child),
aa8cf57195dfb7fa3d0baedf81f8be377946cea8slive * which is a pretty nice debugging environment. (You'll get a SIGHUP
67f57b90aea98fc792b6c6e67bd27ee35f7d026bigalic * early in standalone_main; just continue through. This is the server
d7604f90897d9b08b227c127ff5392393178911crpluem * trying to kill off any child processes which it might have lying
aa8cf57195dfb7fa3d0baedf81f8be377946cea8slive * around --- Apache doesn't keep track of their pids, it just sends
67f57b90aea98fc792b6c6e67bd27ee35f7d026bigalic * SIGHUP to the process group, ignoring it in the root process.
ad93f15b0bef55041347cdbad447d94296eb89f2nilgun * Continue through and you'll be fine.).
67f57b90aea98fc792b6c6e67bd27ee35f7d026bigalicstatic int one_process = 0;
aa8cf57195dfb7fa3d0baedf81f8be377946cea8slivestatic apr_pool_t *pchild; /* Pool for httpd child stuff */
aa8cf57195dfb7fa3d0baedf81f8be377946cea8slivestatic pid_t ap_my_pid; /* it seems silly to call getpid all the time */
aa8cf57195dfb7fa3d0baedf81f8be377946cea8slivestatic volatile int die_now = 0;
ad93f15b0bef55041347cdbad447d94296eb89f2nilgun * change directory for gprof to plop the gmon.out file
ad93f15b0bef55041347cdbad447d94296eb89f2nilgun * configure in httpd.conf:
ad93f15b0bef55041347cdbad447d94296eb89f2nilgun * GprofDir $RuntimeDir/ -> $ServerRoot/$RuntimeDir/gmon.out
ad93f15b0bef55041347cdbad447d94296eb89f2nilgun * GprofDir $RuntimeDir/% -> $ServerRoot/$RuntimeDir/gprof.$pid/gmon.out
ad93f15b0bef55041347cdbad447d94296eb89f2nilgunstatic void chdir_for_gprof(void)
ad93f15b0bef55041347cdbad447d94296eb89f2nilgun ap_get_module_config(ap_server_conf->module_config, &core_module);
ad93f15b0bef55041347cdbad447d94296eb89f2nilgun const char *use_dir;
ad93f15b0bef55041347cdbad447d94296eb89f2nilgun use_dir = ap_server_root_relative(pconf, buf ? buf : dir);
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele if(res != APR_SUCCESS && !APR_STATUS_IS_EEXIST(res)) {
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele ap_log_error(APLOG_MARK, APLOG_ERR, res, ap_server_conf,
ad93f15b0bef55041347cdbad447d94296eb89f2nilgun use_dir = ap_server_root_relative(pconf, DEFAULT_REL_RUNTIMEDIR);
a1ef40892ffa2b44fc249423c5b6c42a74a84c68nd/* a clean exit from a child with proper cleanup */
ad93f15b0bef55041347cdbad447d94296eb89f2nilgunstatic void clean_child_exit(int code) __attribute__ ((noreturn));
ad93f15b0bef55041347cdbad447d94296eb89f2nilgunstatic void accept_mutex_on(void)
ad93f15b0bef55041347cdbad447d94296eb89f2nilgun ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, NULL, "%s", msg);
ad93f15b0bef55041347cdbad447d94296eb89f2nilgun ap_log_error(APLOG_MARK, APLOG_EMERG, rv, NULL, "%s", msg);
10a304fc5348d394375b98ae10ca9b137fd10cafkessstatic void accept_mutex_off(void)
ad93f15b0bef55041347cdbad447d94296eb89f2nilgun apr_status_t rv = apr_proc_mutex_unlock(accept_mutex);
ad93f15b0bef55041347cdbad447d94296eb89f2nilgun const char *msg = "couldn't release the accept mutex";
ad93f15b0bef55041347cdbad447d94296eb89f2nilgun ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, NULL, "%s", msg);
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele /* don't exit here... we have a connection to
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * process, after which point we'll see that the
ad93f15b0bef55041347cdbad447d94296eb89f2nilgun * generation changed and we'll exit cleanly
ad93f15b0bef55041347cdbad447d94296eb89f2nilgun ap_log_error(APLOG_MARK, APLOG_EMERG, rv, NULL, "%s", msg);
ad93f15b0bef55041347cdbad447d94296eb89f2nilgun/* On some architectures it's safe to do unserialized accept()s in the single
ad93f15b0bef55041347cdbad447d94296eb89f2nilgun * Listen case. But it's never safe to do it in the case where there's
ad93f15b0bef55041347cdbad447d94296eb89f2nilgun * multiple Listen statements. Define SINGLE_LISTEN_UNSERIALIZED_ACCEPT
ad93f15b0bef55041347cdbad447d94296eb89f2nilgun * when it's safe in the single Listen case.
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele#define SAFE_ACCEPT(stmt) do {if (ap_listeners->next) {stmt;}} while(0)
4ab980a06412fd86f52a6d054fb7e26de155c530erikabelestatic apr_status_t prefork_query(int query_code, int *result)
df321386f1d9ed17a3e5e6468807996a12890d50gryzorstatic apr_status_t prefork_note_child_killed(int childnum)
df321386f1d9ed17a3e5e6468807996a12890d50gryzorstatic const char *prefork_get_name(void)
df321386f1d9ed17a3e5e6468807996a12890d50gryzor return "prefork";
df321386f1d9ed17a3e5e6468807996a12890d50gryzor/*****************************************************************
df321386f1d9ed17a3e5e6468807996a12890d50gryzor * Connection structures and accounting...
ad93f15b0bef55041347cdbad447d94296eb89f2nilgun /* For a graceful stop, we want the child to exit when done */
ad93f15b0bef55041347cdbad447d94296eb89f2nilgun/* volatile just in case */
4ab980a06412fd86f52a6d054fb7e26de155c530erikabelestatic int volatile shutdown_pending;
4ab980a06412fd86f52a6d054fb7e26de155c530erikabelestatic int volatile restart_pending;
4ab980a06412fd86f52a6d054fb7e26de155c530erikabelestatic int volatile is_graceful;
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele /* Um, is this _probably_ not an error, if the user has
ad93f15b0bef55041347cdbad447d94296eb89f2nilgun * tried to do a shutdown twice quickly, so we won't
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * worry about reporting it.
ad93f15b0bef55041347cdbad447d94296eb89f2nilgun/* restart() is the signal handler for SIGHUP and AP_SIG_GRACEFUL
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * in the parent process, unless running in ONE_PROCESS mode
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele /* Probably not an error - don't bother reporting it */
ad93f15b0bef55041347cdbad447d94296eb89f2nilgunstatic void set_signals(void)
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGTERM)");
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele if (sigaction(AP_SIG_GRACEFUL_STOP, &sa, NULL) < 0)
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
ad93f15b0bef55041347cdbad447d94296eb89f2nilgun ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGINT)");
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGXCPU)");
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGXFSZ)");
ad93f15b0bef55041347cdbad447d94296eb89f2nilgun ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGPIPE)");
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele /* we want to ignore HUPs and AP_SIG_GRACEFUL while we're busy
ad93f15b0bef55041347cdbad447d94296eb89f2nilgun * processing one
ad93f15b0bef55041347cdbad447d94296eb89f2nilgun ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGHUP)");
ad93f15b0bef55041347cdbad447d94296eb89f2nilgun ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(" AP_SIG_GRACEFUL_STRING ")");
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele#endif /* SIGXCPU */
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele#endif /* SIGXFSZ */
ad93f15b0bef55041347cdbad447d94296eb89f2nilgun#endif /* SIGHUP */
ad93f15b0bef55041347cdbad447d94296eb89f2nilgun#endif /* AP_SIG_GRACEFUL */
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele#endif /* AP_SIG_GRACEFUL */
e8811b6d38f756b325446ded5d96857d13856511takashi#endif /* SIGPIPE */
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele/*****************************************************************
ad93f15b0bef55041347cdbad447d94296eb89f2nilgun * Child process main loop.
4ab980a06412fd86f52a6d054fb7e26de155c530erikabele * The following vars are static to avoid getting clobbered by longjmp();
d4e64150011f0e4a1f1ad316b2723fdde2febe2aigalic * they are really private to child_main.
4ab980a06412fd86f52a6d054fb7e26de155c530erikabelestatic int num_listensocks = 0;
int last_poll_idx = 0;
requests_this_child = 0;
#if APR_HAS_THREADS
void *csd;
if ((ap_max_requests_per_child > 0
clean_child_exit(0);
else if (die_now) {
clean_child_exit(0);
last_poll_idx = 0;
goto got_fd;
current_conn = ap_run_create_connection(ptrans, ap_server_conf, csd, my_child_num, sbh, bucket_alloc);
if (current_conn) {
#if APR_HAS_THREADS
else if (my_generation !=
clean_child_exit(0);
int pid;
if (one_process) {
#ifdef SIGQUIT
#ifdef _OSD_POSIX
if (!pid) {
#ifdef HAVE_BINDPROCESSOR
#ifndef MAX_SPAWN_RATE
static int hold_off_on_exponential_spawning;
int to_kill;
int idle_count;
int free_length;
int last_non_dead;
int total_non_dead;
free_length = 0;
idle_count = 0;
total_non_dead = 0;
for (i = 0; i < ap_daemons_limit; ++i) {
int status;
++free_length;
++ idle_count;
to_kill = i;
last_non_dead = i;
if (free_length == 0) {
static int reported = 0;
if (!reported) {
"to increase StartServers, or Min/MaxSpareServers), "
for (i = 0; i < free_length; ++i) {
int index;
if (!is_graceful) {
set_signals();
if (one_process) {
if (!is_graceful) {
int child_slot;
if (child_slot >= 0) {
else if (remaining_children_to_start
else if (is_graceful) {
0, ap_server_conf,
else if (remaining_children_to_start) {
0, ap_server_conf,
} else if (shutdown_pending) {
int active_children;
active_children = 0;
0, ap_server_conf,
if (ap_graceful_shutdown_timeout) {
shutdown_pending = 0;
active_children = 0;
if (one_process) {
if (is_graceful) {
int startup = 0;
int level_flags = 0;
pconf = p;
return DONE;
return DONE;
return OK;
if (debug) {
no_detach = 0;
if (!retained) {
is_graceful = 0;
return HTTP_INTERNAL_SERVER_ERROR;
ap_extended_status = 0;
return OK;
int startup = 0;
if (startup) {
if (startup) {
if (startup) {
if (startup) {
if (ap_daemons_to_start < 0) {
if (startup) {
if (startup) {
return OK;
return err;
return NULL;
return err;
return NULL;
return err;
return NULL;
return err;
return NULL;
return err;
return NULL;
{ NULL }