prefork.c revision 546ab7ed4cd7df920aef1b4d6487d95d6036ebc6
8da1125022af61370e7105ca9c6447d5944cb8fctrawick/* ====================================================================
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd * Copyright (c) 1995-1999 The Apache Group. All rights reserved.
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd * Redistribution and use in source and binary forms, with or without
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd * modification, are permitted provided that the following conditions
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd * are met:
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd * 1. Redistributions of source code must retain the above copyright
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd * notice, this list of conditions and the following disclaimer.
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd * 2. Redistributions in binary form must reproduce the above copyright
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd * notice, this list of conditions and the following disclaimer in
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd * the documentation and/or other materials provided with the
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd * distribution.
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd * 3. All advertising materials mentioning features or use of this
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd * software must display the following acknowledgment:
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd * "This product includes software developed by the Apache Group
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd * for use in the Apache HTTP server project (http://www.apache.org/)."
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd * 4. The names "Apache Server" and "Apache Group" must not be used to
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd * endorse or promote products derived from this software without
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd * prior written permission. For written permission, please contact
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd * apache@apache.org.
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd * 5. Products derived from this software may not be called "Apache"
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd * nor may "Apache" appear in their names without prior written
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd * permission of the Apache Group.
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd * 6. Redistributions of any form whatsoever must retain the following
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd * acknowledgment:
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd * "This product includes software developed by the Apache Group
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd * for use in the Apache HTTP server project (http://www.apache.org/)."
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd * OF THE POSSIBILITY OF SUCH DAMAGE.
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd * ====================================================================
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd * This software consists of voluntary contributions made by many
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd * individuals on behalf of the Apache Group and was originally based
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd * on public domain software written at the National Center for
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd * Supercomputing Applications, University of Illinois, Urbana-Champaign.
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd * For more information on the Apache Group and the Apache HTTP server
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd * project, please see <http://www.apache.org/>.
626cbbae0d87d1e58fabf969ef6c55e3f5fcd544humbedooh * httpd.c: simple http daemon for answering WWW file requests
fd961f7871d2a909f75baf2769652e59c360f16etrawick * 03-21-93 Rob McCool wrote original code (up to NCSA HTTPd 1.3)
fd961f7871d2a909f75baf2769652e59c360f16etrawick * 03-06-95 blong
fd961f7871d2a909f75baf2769652e59c360f16etrawick * changed server number for child-alone processes to 0 and changed name
fd961f7871d2a909f75baf2769652e59c360f16etrawick * of processes
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd * 03-10-95 blong
626cbbae0d87d1e58fabf969ef6c55e3f5fcd544humbedooh * Added numerous speed hacks proposed by Robert S. Thau (rst@ai.mit.edu)
2fae9d127f7143fabe8f73958eb9bde31df17d41coar * including set group before fork, and call gettime before to fork
49c1d45abbd5add003287667aa1e934444fa4974rjung * to set up libraries.
49c1d45abbd5add003287667aa1e934444fa4974rjung * 04-14-95 rst / rh
626cbbae0d87d1e58fabf969ef6c55e3f5fcd544humbedooh * Brandon's code snarfed from NCSA 1.4, but tinkered to work with the
626cbbae0d87d1e58fabf969ef6c55e3f5fcd544humbedooh * Apache server, and also to have child processes do accept() directly.
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd * April-July '95 rst
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd * Extensive rework for Apache.
acdffc097350a5d03964bf52b79d6cf9e0609974trawick/* TODO: this is a cobbled together prefork MPM example... it should mostly
acdffc097350a5d03964bf52b79d6cf9e0609974trawick * TODO: behave like apache-1.3... here's a short list of things I think
2792ea4d5c772a6bc19dece2e098b8125bf7184cjim * TODO: need cleaning up still:
2792ea4d5c772a6bc19dece2e098b8125bf7184cjim * TODO: - use ralf's mm stuff for the shared mem and mutexes
2792ea4d5c772a6bc19dece2e098b8125bf7184cjim * TODO: - clean up scoreboard stuff when we figure out how to do it in 2.0
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd/* config globals */
9f07b6dc343a4e3eba5f4c47050a77441723ce89ndstatic char *ap_lock_fname;
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd * The max child slot ever assigned, preserved across restarts. Necessary
8da1125022af61370e7105ca9c6447d5944cb8fctrawick * to deal with MaxClients changes across SIGUSR1 restarts. We use this
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd * value to optimize routines that have to scan the entire scoreboard.
5d01f40ffd657dd2ac567aacd93cabd162ddfa79coar/* *Non*-shared http_main globals... */
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd/* one_process --- debugging mode variable; can be set from the command line
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd * with the -X flag. If set, this gets you the child_main loop running
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd * in the process which originally started up (no detach, no make_child),
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd * which is a pretty nice debugging environment. (You'll get a SIGHUP
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd * early in standalone_main; just continue through. This is the server
4da61833a1cbbca94094f9653fd970582b97a72etrawick * trying to kill off any child processes which it might have lying
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd * around --- Apache doesn't keep track of their pids, it just sends
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd * SIGHUP to the process group, ignoring it in the root process.
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd * Continue through and you'll be fine.).
9f07b6dc343a4e3eba5f4c47050a77441723ce89ndstatic int one_process = 0;
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd/* used to maintain list of children which aren't part of the scoreboard */
4da61833a1cbbca94094f9653fd970582b97a72etrawickstatic int my_pid; /* it seems silly to call getpid all the time */
9f07b6dc343a4e3eba5f4c47050a77441723ce89nd#endif /* TPF */
#ifdef GPROF
* configure in httpd.conf:
* GprofDir logs/ -> $ServerRoot/logs/gmon.out
* GprofDir logs/% -> $ServerRoot/logs/gprof.$pid/gmon.out
static void chdir_for_gprof(void)
if(dir) {
#define chdir_for_gprof()
if (pchild) {
#if defined (USE_USLOCK_SERIALIZED_ACCEPT)
#include <ulocks.h>
#define accept_mutex_child_init(x)
static void accept_mutex_on(void)
static void accept_mutex_off(void)
#include <pthread.h>
static int have_accept_mutex;
&& have_accept_mutex) {
int fd;
static void accept_mutex_on(void)
int err;
static void accept_mutex_off(void)
int err;
have_accept_mutex = 0;
#ifdef NEED_UNION_SEMUN
union semun {
long val;
if (sem_id < 0)
#define accept_mutex_child_init(x)
if (sem_id < 0) {
if (!getuid()) {
static void accept_mutex_on(void)
static void accept_mutex_off(void)
#define accept_mutex_child_init(x)
static void accept_mutex_on(void)
int ret;
if (ret < 0) {
static void accept_mutex_off(void)
int ret;
if (ret < 0) {
static void accept_mutex_on(void)
int ret;
if (ret < 0) {
static void accept_mutex_off(void)
if (rc != 0) {
if (rc != 0) {
static void accept_mutex_on(void)
if (rc != 0) {
static void accept_mutex_off(void)
if (rc != 0) {
static int tpf_core_held;
if(tpf_core_held)
#define accept_mutex_init(x)
tpf_core_held = 0;
static void accept_mutex_on(void)
static void accept_mutex_off(void)
tpf_core_held = 0;
#if !defined(MULTITHREAD)
#define NO_SERIALIZED_ACCEPT
#define accept_mutex_child_init(x)
#define accept_mutex_init(x)
#define accept_mutex_on()
#define accept_mutex_off()
#ifdef HAS_OTHER_CHILD
static void probe_writable_fds(void)
int fd_max;
int rc;
fd_max = 0;
if (fd_max == 0)
if (rc == 0)
#if defined(USE_OS2_SCOREBOARD)
void *mem;
Heap_t h;
if (rc != 0)
return NULL;
if (h == NULL)
return (caddr_t) h;
if (rc != 0) {
return BaseAddress;
caddr_t m;
int rc;
if (rc != 0) {
caddr_t m;
int rc;
* in httpd.conf to cut "logs/" from it. With default setup actual name
* will be "/dev/shmem/logs.apache_status".
* of ap_config.h
static void cleanup_shared_mem(void *d)
caddr_t m;
int fd;
caddr_t m;
#if defined(MAP_ANON)
#ifdef CONVEXOS11
int fd;
#ifdef MOVEBREAK
char *obrk;
#ifdef LINUX
#ifdef MOVEBREAK
shmid);
#ifdef MOVEBREAK
static void cleanup_scoreboard_heap()
int rv;
if (!ap_scoreboard_image) {
#define SCOREBOARD_FILE
if (rv > 0) {
if (rv > 0) {
#ifdef TPF
int running_gen = 0;
if (ap_scoreboard_image)
#ifndef SCOREBOARD_FILE
setup_shared_mem(p);
#ifdef SCOREBOARD_FILE
#ifdef SCOREBOARD_FILE
int old_status;
if (child_num < 0)
if (ap_extended_status) {
#ifdef SCOREBOARD_FILE
sizeof(parent_score));
return old_status;
static void update_scoreboard_global(void)
#ifdef SCOREBOARD_FILE
if (child_num < 0)
#if defined(NO_GETTIMEOFDAY)
#ifndef NO_TIMES
#if defined(NO_GETTIMEOFDAY)
#ifndef NO_TIMES
for (i = 0; i < max_daemons_limit; ++i)
#ifndef MULTITHREAD
int i, status;
int not_dead_yet;
#ifdef HAS_OTHER_CHILD
not_dead_yet = 0;
for (i = 0; i < max_daemons_limit; ++i) {
++not_dead_yet;
switch (tries) {
pid);
pid);
pid);
#ifdef HAS_OTHER_CHILD
else if (waitret == 0) {
++not_dead_yet;
if (!not_dead_yet) {
#if defined(NEED_WAITPID)
int n, pid;
for (n = 0; n < max_daemons_limit; ++n) {
return(pid);
#ifndef INTERVAL_OF_WRITABLE_PROBES
static int wait_or_timeout_counter;
int ret;
#ifdef HAS_OTHER_CHILD
if (ret > 0) {
return ret;
#ifdef NEED_WAITPID
return ret;
#if defined(NSIG)
static void siglist_init(void)
int sig;
#ifdef SIGHUP
#ifdef SIGINT
#ifdef SIGQUIT
#ifdef SIGILL
#ifdef SIGTRAP
#ifdef SIGIOT
#ifdef SIGABRT
#ifdef SIGEMT
#ifdef SIGFPE
#ifdef SIGKILL
#ifdef SIGBUS
#ifdef SIGSEGV
#ifdef SIGSYS
#ifdef SIGPIPE
#ifdef SIGALRM
#ifdef SIGTERM
#ifdef SIGUSR1
#ifdef SIGUSR2
#ifdef SIGCLD
#ifdef SIGCHLD
#ifdef SIGPWR
#ifdef SIGWINCH
#ifdef SIGURG
#ifdef SIGPOLL
#ifdef SIGIO
#ifdef SIGSTOP
#ifdef SIGTSTP
#ifdef SIGCONT
#ifdef SIGTTIN
#ifdef SIGTTOU
#ifdef SIGVTALRM
#ifdef SIGPROF
#ifdef SIGXCPU
#ifdef SIGXFSZ
clean_child_exit(0);
static int volatile deferred_die;
static int volatile usr1_just_die;
if (usr1_just_die) {
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) {
#if defined(SA_ONESHOT)
#ifdef SIGBUS
#ifdef SIGABORT
#ifdef SIGABRT
#ifdef SIGILL
#ifdef SIGINT
#ifdef SIGXCPU
#ifdef SIGXFSZ
#ifdef SIGPIPE
if (!one_process) {
#ifdef SIGBUS
#ifdef SIGABORT
#ifdef SIGABRT
#ifdef SIGILL
#ifdef SIGXCPU
#ifdef SIGXFSZ
#ifdef SIGHUP
#ifdef SIGUSR1
#ifdef SIGPIPE
static void sock_disable_nagle(int s)
static int srv;
static int csd;
static int requests_this_child;
int ap_graceful_stop_signalled(void)
if (deferred_die ||
requests_this_child = 0;
if (unixd_setup_child()) {
#ifdef OS2
/* Stop Ctrl-C/Ctrl-Break signals going to child processes */
unsigned long ulTimes;
while (!ap_graceful_stop_signalled()) {
if ((ap_max_requests_per_child > 0
clean_child_exit(0);
if (srv <= 0)
if (!lr) {
usr1_just_die = 0;
if (deferred_die) {
clean_child_exit(0);
if (csd >= 0)
switch (errno) {
#ifdef EPROTO
case EPROTO:
#ifdef ECONNABORTED
case ECONNABORTED:
#ifdef ECONNRESET
case ECONNRESET:
#ifdef ETIMEDOUT
case ETIMEDOUT:
#ifdef EHOSTUNREACH
case EHOSTUNREACH:
#ifdef ENETUNREACH
case ENETUNREACH:
#ifdef TPF
case EINACT:
if (ap_graceful_stop_signalled()) {
clean_child_exit(0);
#ifdef TPF
my_child_num, 0);
int pid;
if (one_process) {
#ifdef SIGQUIT
#ifdef _OSD_POSIX
if (!pid) {
#ifdef AIX_BIND_PROCESSOR
#ifdef SCOREBOARD_FILE
sizeof(parent_score));
#ifndef MAX_SPAWN_RATE
static int hold_off_on_exponential_spawning;
static void perform_idle_server_maintenance(void)
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
pid);
case SIGTERM:
case SIGHUP:
case SIGUSR1:
case SIGKILL:
#ifdef SYS_SIGLIST
#ifdef WCOREDUMP
#ifdef WCOREDUMP
server_conf = s;
if (!is_graceful) {
#ifdef SCOREBOARD_FILE
set_signals();
if (!is_graceful) {
int child_slot;
if (pid >= 0) {
if (child_slot >= 0) {
#ifdef HAS_OTHER_CHILD
else if (is_graceful) {
else if (remaining_children_to_start) {
#ifdef TPF
if (shutdown_pending) {
if (one_process) {
if (is_graceful) {
#ifndef SCOREBOARD_FILE
#ifndef SCOREBOARD_FILE
for (i = 0; i < ap_daemons_limit; ++i) {
if (!is_graceful) {
INIT_SIGLIST();
#ifdef AUX3
(void) set42sig();
static int restart_num = 0;
is_graceful = 0;
if (!one_process) {
unixd_detach();
ap_extended_status = 0;
return err;
return NULL;
return err;
return NULL;
return err;
return NULL;
return err;
return NULL;
return err;
if (ap_daemons_min_free <= 0) {
return NULL;
return err;
return NULL;
return err;
return NULL;
return err;
return NULL;
const char *fname;
return err;
return NULL;
struct ap_thread_mutex {
int dummy;
{ NULL }