prefork.c revision 00a9373468bf0622b0dfa823374a8543eab5df55
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster/* Copyright 1999-2005 The Apache Software Foundation or its licensors, as
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * applicable.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Licensed under the Apache License, Version 2.0 (the "License");
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * you may not use this file except in compliance with the License.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * You may obtain a copy of the License at
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Unless required by applicable law or agreed to in writing, software
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * distributed under the License is distributed on an "AS IS" BASIS,
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * See the License for the specific language governing permissions and
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * limitations under the License.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#include "http_core.h" /* for get_remote_host */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#include <bstring.h> /* for IRIX, FD_SET calls bzero() */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#include <sys/processor.h> /* for bindprocessor() */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster/* Limit on the total --- clients will be locked out if more servers than
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * this are needed. It is intended solely to keep the server from crashing
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * when things get out of hand.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * We keep a hard maximum number of servers, for two reasons --- first off,
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * in case something goes seriously wrong, we want to stop the fork bomb
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * short of actually crashing the machine we're running on by filling some
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * kernel table. Secondly, it keeps the size of the scoreboard file small
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * enough that we can read the whole thing without worrying too much about
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * the overhead.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster/* Admin can't tune ServerLimit beyond MAX_SERVER_LIMIT. We want
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * some sort of compile-time limit to help catch typos.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster/* config globals */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterint ap_threads_per_child=0; /* Worker threads per child */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * The max child slot ever assigned, preserved across restarts. Necessary
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * to deal with MaxClients changes across AP_SIG_GRACEFUL restarts. We
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * use this value to optimize routines that have to scan the entire scoreboard.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster/* one_process --- debugging mode variable; can be set from the command line
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * with the -X flag. If set, this gets you the child_main loop running
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * in the process which originally started up (no detach, no make_child),
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * which is a pretty nice debugging environment. (You'll get a SIGHUP
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * early in standalone_main; just continue through. This is the server
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * trying to kill off any child processes which it might have lying
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * around --- Apache doesn't keep track of their pids, it just sends
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * SIGHUP to the process group, ignoring it in the root process.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Continue through and you'll be fine.).
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterstatic int one_process = 0;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterstatic apr_pool_t *pconf; /* Pool for config stuff */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterstatic apr_pool_t *pchild; /* Pool for httpd child stuff */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterstatic pid_t ap_my_pid; /* it seems silly to call getpid all the time */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#endif /* TPF */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterstatic int die_now = 0;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * change directory for gprof to plop the gmon.out file
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * configure in httpd.conf:
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * GprofDir $RuntimeDir/ -> $ServerRoot/$RuntimeDir/gmon.out
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * GprofDir $RuntimeDir/% -> $ServerRoot/$RuntimeDir/gprof.$pid/gmon.out
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterstatic void chdir_for_gprof(void)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster ap_get_module_config(ap_server_conf->module_config, &core_module);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster apr_snprintf(buf, sizeof(buf), "%sgprof.%d", dir, (int)getpid());
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster use_dir = ap_server_root_relative(pconf, buf[0] ? buf : dir);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if(res != APR_SUCCESS && !APR_STATUS_IS_EEXIST(res)) {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster ap_log_error(APLOG_MARK, APLOG_ERR, res, ap_server_conf,
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster use_dir = ap_server_root_relative(pconf, DEFAULT_REL_RUNTIMEDIR);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster/* XXX - I don't know if TPF will ever use this module or not, so leave
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * the ap_check_signals calls in but disable them - manoj */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster/* a clean exit from a child with proper cleanup */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterstatic void clean_child_exit(int code) __attribute__ ((noreturn));
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterstatic void accept_mutex_on(void)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster apr_status_t rv = apr_proc_mutex_lock(accept_mutex);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster const char *msg = "couldn't grab the accept mutex";
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster ap_scoreboard_image->global->running_generation) {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, NULL, "%s", msg);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster ap_log_error(APLOG_MARK, APLOG_EMERG, rv, NULL, "%s", msg);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterstatic void accept_mutex_off(void)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster apr_status_t rv = apr_proc_mutex_unlock(accept_mutex);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster const char *msg = "couldn't release the accept mutex";
if (ap_my_generation !=
switch(query_code){
case AP_MPMQ_MAX_DAEMON_USED:
return APR_SUCCESS;
case AP_MPMQ_IS_THREADED:
return APR_SUCCESS;
case AP_MPMQ_IS_FORKED:
return APR_SUCCESS;
return APR_SUCCESS;
return APR_SUCCESS;
case AP_MPMQ_MAX_THREADS:
*result = 0;
return APR_SUCCESS;
return APR_SUCCESS;
*result = 0;
return APR_SUCCESS;
return APR_SUCCESS;
*result = 0;
return APR_SUCCESS;
return APR_SUCCESS;
case AP_MPMQ_MAX_DAEMONS:
return APR_SUCCESS;
case AP_MPMQ_MPM_STATE:
return APR_SUCCESS;
return APR_ENOTIMPL;
#if defined(NEED_WAITPID)
int n, pid;
for (n = 0; n < ap_max_daemons_limit; ++n) {
*exitcode = 0;
return(pid);
clean_child_exit(0);
static int volatile shutdown_pending;
static int volatile restart_pending;
static int volatile is_graceful;
static void set_signals(void)
#ifndef NO_USE_SIGACTION
if (!one_process) {
#ifndef NO_USE_SIGACTION
#ifdef AP_SIG_GRACEFUL_STOP
#ifdef SIGINT
#ifdef SIGXCPU
#ifdef SIGXFSZ
#ifdef SIGPIPE
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(" AP_SIG_GRACEFUL_STRING ")");
if (!one_process) {
#ifdef SIGXCPU
#ifdef 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 }