prefork.c revision f6aa8572a3986fcc2cfed30ce1730aca0c14df72
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd/* Copyright 1999-2005 The Apache Software Foundation or its licensors, as
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * applicable.
15b0d99a66145e797cbe368bff5e44d5653be5e5nd * Licensed under the Apache License, Version 2.0 (the "License");
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * you may not use this file except in compliance with the License.
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * You may obtain a copy of the License at
031b91a62d25106ae69d4693475c79618dd5e884fielding * Unless required by applicable law or agreed to in writing, software
031b91a62d25106ae69d4693475c79618dd5e884fielding * distributed under the License is distributed on an "AS IS" BASIS,
031b91a62d25106ae69d4693475c79618dd5e884fielding * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * See the License for the specific language governing permissions and
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * limitations under the License.
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd/* Limit on the total --- clients will be locked out if more servers than
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * this are needed. It is intended solely to keep the server from crashing
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * when things get out of hand.
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * We keep a hard maximum number of servers, for two reasons --- first off,
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * in case something goes seriously wrong, we want to stop the fork bomb
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * short of actually crashing the machine we're running on by filling some
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * kernel table. Secondly, it keeps the size of the scoreboard file small
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * enough that we can read the whole thing without worrying too much about
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * the overhead.
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd/* Admin can't tune ServerLimit beyond MAX_SERVER_LIMIT. We want
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * some sort of compile-time limit to help catch typos.
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd/* config globals */
41e3d6b4e67a52c6570c0412c3e5526278cf07d7ndint ap_threads_per_child=0; /* Worker threads per child */
41e3d6b4e67a52c6570c0412c3e5526278cf07d7ndstatic int first_server_limit = 0;
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * The max child slot ever assigned, preserved across restarts. Necessary
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * to deal with MaxClients changes across AP_SIG_GRACEFUL restarts. We
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * use this value to optimize routines that have to scan the entire scoreboard.
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd/* one_process --- debugging mode variable; can be set from the command line
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * with the -X flag. If set, this gets you the child_main loop running
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * in the process which originally started up (no detach, no make_child),
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * which is a pretty nice debugging environment. (You'll get a SIGHUP
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * early in standalone_main; just continue through. This is the server
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * trying to kill off any child processes which it might have lying
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * around --- Apache doesn't keep track of their pids, it just sends
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * SIGHUP to the process group, ignoring it in the root process.
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * Continue through and you'll be fine.).
41e3d6b4e67a52c6570c0412c3e5526278cf07d7ndstatic int one_process = 0;
41e3d6b4e67a52c6570c0412c3e5526278cf07d7ndstatic apr_pool_t *pchild; /* Pool for httpd child stuff */
41e3d6b4e67a52c6570c0412c3e5526278cf07d7ndstatic pid_t ap_my_pid; /* it seems silly to call getpid all the time */
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd#endif /* TPF */
41e3d6b4e67a52c6570c0412c3e5526278cf07d7ndstatic int die_now = 0;
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * change directory for gprof to plop the gmon.out file
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * configure in httpd.conf:
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * GprofDir $RuntimeDir/ -> $ServerRoot/$RuntimeDir/gmon.out
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * GprofDir $RuntimeDir/% -> $ServerRoot/$RuntimeDir/gprof.$pid/gmon.out
41e3d6b4e67a52c6570c0412c3e5526278cf07d7ndstatic void chdir_for_gprof(void)
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd ap_get_module_config(ap_server_conf->module_config, &core_module);
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd const char *use_dir;
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd use_dir = ap_server_root_relative(pconf, buf ? buf : dir);
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd use_dir = ap_server_root_relative(pconf, DEFAULT_REL_RUNTIMEDIR);
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd/* XXX - I don't know if TPF will ever use this module or not, so leave
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * the ap_check_signals calls in but disable them - manoj */
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd/* a clean exit from a child with proper cleanup */
41e3d6b4e67a52c6570c0412c3e5526278cf07d7ndstatic void clean_child_exit(int code) __attribute__ ((noreturn));
41e3d6b4e67a52c6570c0412c3e5526278cf07d7ndstatic void accept_mutex_on(void)
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, NULL, "%s", msg);
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd ap_log_error(APLOG_MARK, APLOG_EMERG, rv, NULL, "%s", msg);
41e3d6b4e67a52c6570c0412c3e5526278cf07d7ndstatic void accept_mutex_off(void)
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, NULL, "%s", msg);
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd /* don't exit here... we have a connection to
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * process, after which point we'll see that the
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * generation changed and we'll exit cleanly
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd ap_log_error(APLOG_MARK, APLOG_EMERG, rv, NULL, "%s", msg);
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd/* On some architectures it's safe to do unserialized accept()s in the single
4d7a2e153c599946b6afbe7bf883f477fcab7e53kess * Listen case. But it's never safe to do it in the case where there's
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * multiple Listen statements. Define SINGLE_LISTEN_UNSERIALIZED_ACCEPT
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * when it's safe in the single Listen case.
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd#define SAFE_ACCEPT(stmt) do {if (ap_listeners->next) {stmt;}} while(0)
41e3d6b4e67a52c6570c0412c3e5526278cf07d7ndAP_DECLARE(apr_status_t) ap_mpm_query(int query_code, int *result)
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd Systems without a real waitpid sometimes lose a child's exit while waiting
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd for another. Search through the scoreboard for missing children.
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd for (n = 0; n < ap_max_daemons_limit; ++n) {
4d7a2e153c599946b6afbe7bf883f477fcab7e53kess if (ap_scoreboard_image->servers[n][0].status != SERVER_DEAD &&
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd kill((pid = ap_scoreboard_image->parent[n].pid), 0) == -1) {
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd ap_update_child_status_from_indexes(n, 0, SERVER_DEAD, NULL);
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd /* just mark it as having a successful exit status */
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd/*****************************************************************
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * Connection structures and accounting...
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd /* For a graceful stop, we want the child to exit when done */
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd/* volatile just in case */
41e3d6b4e67a52c6570c0412c3e5526278cf07d7ndstatic int volatile shutdown_pending;
41e3d6b4e67a52c6570c0412c3e5526278cf07d7ndstatic int volatile restart_pending;
41e3d6b4e67a52c6570c0412c3e5526278cf07d7ndstatic int volatile is_graceful;
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd /* Um, is this _probably_ not an error, if the user has
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * tried to do a shutdown twice quickly, so we won't
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * worry about reporting it.
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd/* restart() is the signal handler for SIGHUP and AP_SIG_GRACEFUL
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * in the parent process, unless running in ONE_PROCESS mode
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd /* Probably not an error - don't bother reporting it */
41e3d6b4e67a52c6570c0412c3e5526278cf07d7ndstatic void set_signals(void)
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGTERM)");
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGINT)");
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGXCPU)");
b51bf223f42d43ca6b1b33c95124edcfa5a871a4nd ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGXFSZ)");
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGPIPE)");
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd /* we want to ignore HUPs and AP_SIG_GRACEFUL while we're busy
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * processing one
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGHUP)");
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(" AP_SIG_GRACEFUL_STRING ")");
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd#endif /* SIGXCPU */
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd#endif /* SIGXFSZ */
#ifdef SIGHUP
#ifdef AP_SIG_GRACEFUL
#ifdef AP_SIG_GRACEFUL_STOP
#ifdef SIGPIPE
static int requests_this_child;
static int num_listensocks = 0;
int ap_graceful_stop_signalled(void)
int last_poll_idx = 0;
requests_this_child = 0;
if (unixd_setup_child()) {
while (!die_now) {
void *csd;
if ((ap_max_requests_per_child > 0
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) {
else if (ap_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) {
#ifdef TPF
int index;
if (changed_limit_at_restart) {
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) {
#ifdef TPF
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) {
pconf = p;
ap_server_conf = s;
return DONE;
return DONE;
return OK;
static int restart_num = 0;
if (debug) {
no_detach = 0;
is_graceful = 0;
return HTTP_INTERNAL_SERVER_ERROR;
ap_extended_status = 0;
#ifdef AP_MPM_WANT_SET_MAX_MEM_FREE
return OK;
#ifdef AUX3
(void) set42sig();
return err;
return NULL;
return err;
if (ap_daemons_min_free <= 0) {
return NULL;
return err;
return NULL;
return err;
return NULL;
int tmp_server_limit;
return err;
if (first_server_limit &&
return NULL;
return NULL;
{ NULL }