prefork.c revision b82089c85a796d6e047ccf2c97e872adec1475d7
69cbd335b8c18c32569dfd8a62e7c56e2e1724b5gryzor/* ====================================================================
69cbd335b8c18c32569dfd8a62e7c56e2e1724b5gryzor * The Apache Software License, Version 1.1
a52bc627e27a94219f06896ac183d90deb79ad31lgentis * Copyright (c) 2000 The Apache Software Foundation. All rights
69cbd335b8c18c32569dfd8a62e7c56e2e1724b5gryzor * reserved.
69cbd335b8c18c32569dfd8a62e7c56e2e1724b5gryzor * Redistribution and use in source and binary forms, with or without
69cbd335b8c18c32569dfd8a62e7c56e2e1724b5gryzor * modification, are permitted provided that the following conditions
69cbd335b8c18c32569dfd8a62e7c56e2e1724b5gryzor * 1. Redistributions of source code must retain the above copyright
69cbd335b8c18c32569dfd8a62e7c56e2e1724b5gryzor * notice, this list of conditions and the following disclaimer.
69cbd335b8c18c32569dfd8a62e7c56e2e1724b5gryzor * 2. Redistributions in binary form must reproduce the above copyright
69cbd335b8c18c32569dfd8a62e7c56e2e1724b5gryzor * notice, this list of conditions and the following disclaimer in
69cbd335b8c18c32569dfd8a62e7c56e2e1724b5gryzor * the documentation and/or other materials provided with the
69cbd335b8c18c32569dfd8a62e7c56e2e1724b5gryzor * distribution.
69cbd335b8c18c32569dfd8a62e7c56e2e1724b5gryzor * 3. The end-user documentation included with the redistribution,
69cbd335b8c18c32569dfd8a62e7c56e2e1724b5gryzor * if any, must include the following acknowledgment:
69cbd335b8c18c32569dfd8a62e7c56e2e1724b5gryzor * "This product includes software developed by the
69cbd335b8c18c32569dfd8a62e7c56e2e1724b5gryzor * Apache Software Foundation (http://www.apache.org/)."
69cbd335b8c18c32569dfd8a62e7c56e2e1724b5gryzor * Alternately, this acknowledgment may appear in the software itself,
69cbd335b8c18c32569dfd8a62e7c56e2e1724b5gryzor * if and wherever such third-party acknowledgments normally appear.
69cbd335b8c18c32569dfd8a62e7c56e2e1724b5gryzor * 4. The names "Apache" and "Apache Software Foundation" must
69cbd335b8c18c32569dfd8a62e7c56e2e1724b5gryzor * not be used to endorse or promote products derived from this
69cbd335b8c18c32569dfd8a62e7c56e2e1724b5gryzor * software without prior written permission. For written
69cbd335b8c18c32569dfd8a62e7c56e2e1724b5gryzor * permission, please contact apache@apache.org.
69cbd335b8c18c32569dfd8a62e7c56e2e1724b5gryzor * 5. Products derived from this software may not be called "Apache",
69cbd335b8c18c32569dfd8a62e7c56e2e1724b5gryzor * nor may "Apache" appear in their name, without prior written
69cbd335b8c18c32569dfd8a62e7c56e2e1724b5gryzor * permission of the Apache Software Foundation.
69cbd335b8c18c32569dfd8a62e7c56e2e1724b5gryzor * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
69cbd335b8c18c32569dfd8a62e7c56e2e1724b5gryzor * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
69cbd335b8c18c32569dfd8a62e7c56e2e1724b5gryzor * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
69cbd335b8c18c32569dfd8a62e7c56e2e1724b5gryzor * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
69cbd335b8c18c32569dfd8a62e7c56e2e1724b5gryzor * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
69cbd335b8c18c32569dfd8a62e7c56e2e1724b5gryzor * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
69cbd335b8c18c32569dfd8a62e7c56e2e1724b5gryzor * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
69cbd335b8c18c32569dfd8a62e7c56e2e1724b5gryzor * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
3841a292dc897875faf23e639807abcc90082f3clgentis * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
3841a292dc897875faf23e639807abcc90082f3clgentis * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
3841a292dc897875faf23e639807abcc90082f3clgentis * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3841a292dc897875faf23e639807abcc90082f3clgentis * SUCH DAMAGE.
3841a292dc897875faf23e639807abcc90082f3clgentis * ====================================================================
3841a292dc897875faf23e639807abcc90082f3clgentis * This software consists of voluntary contributions made by many
3841a292dc897875faf23e639807abcc90082f3clgentis * individuals on behalf of the Apache Software Foundation. For more
3841a292dc897875faf23e639807abcc90082f3clgentis * information on the Apache Software Foundation, please see
3841a292dc897875faf23e639807abcc90082f3clgentis * Portions of this software are based upon public domain software
3841a292dc897875faf23e639807abcc90082f3clgentis * originally written at the National Center for Supercomputing Applications,
3841a292dc897875faf23e639807abcc90082f3clgentis * University of Illinois, Urbana-Champaign.
3841a292dc897875faf23e639807abcc90082f3clgentis * httpd.c: simple http daemon for answering WWW file requests
3841a292dc897875faf23e639807abcc90082f3clgentis * 03-21-93 Rob McCool wrote original code (up to NCSA HTTPd 1.3)
3841a292dc897875faf23e639807abcc90082f3clgentis * 03-06-95 blong
3841a292dc897875faf23e639807abcc90082f3clgentis * changed server number for child-alone processes to 0 and changed name
3841a292dc897875faf23e639807abcc90082f3clgentis * of processes
3841a292dc897875faf23e639807abcc90082f3clgentis * 03-10-95 blong
3841a292dc897875faf23e639807abcc90082f3clgentis * Added numerous speed hacks proposed by Robert S. Thau (rst@ai.mit.edu)
3841a292dc897875faf23e639807abcc90082f3clgentis * including set group before fork, and call gettime before to fork
3841a292dc897875faf23e639807abcc90082f3clgentis * to set up libraries.
3841a292dc897875faf23e639807abcc90082f3clgentis * 04-14-95 rst / rh
3841a292dc897875faf23e639807abcc90082f3clgentis * Brandon's code snarfed from NCSA 1.4, but tinkered to work with the
3841a292dc897875faf23e639807abcc90082f3clgentis * Apache server, and also to have child processes do accept() directly.
3841a292dc897875faf23e639807abcc90082f3clgentis * April-July '95 rst
69cbd335b8c18c32569dfd8a62e7c56e2e1724b5gryzor * Extensive rework for Apache.
69cbd335b8c18c32569dfd8a62e7c56e2e1724b5gryzor/* TODO: this is a cobbled together prefork MPM example... it should mostly
69cbd335b8c18c32569dfd8a62e7c56e2e1724b5gryzor * TODO: behave like apache-1.3... here's a short list of things I think
69cbd335b8c18c32569dfd8a62e7c56e2e1724b5gryzor * TODO: need cleaning up still:
69cbd335b8c18c32569dfd8a62e7c56e2e1724b5gryzor * TODO: - clean up scoreboard stuff when we figure out how to do it in 2.0
69cbd335b8c18c32569dfd8a62e7c56e2e1724b5gryzor#include <bstring.h> /* for IRIX, FD_SET calls bzero() */
69cbd335b8c18c32569dfd8a62e7c56e2e1724b5gryzor/* config globals */
static int ap_max_requests_per_child=0;
static char *ap_lock_fname;
static int ap_daemons_to_start=0;
static int ap_daemons_min_free=0;
static int ap_daemons_max_free=0;
static int ap_daemons_limit=0;
static int ap_extended_status = 0;
static int listenmaxfd;
static int one_process = 0;
#ifndef MULTITHREAD
static int my_child_num;
#ifdef TPF
int tpf_child = 0;
#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()
#define ap_check_signals()
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) {
return APR_SUCCESS;
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()
#include "apr_shmem.h"
return APR_SUCCESS;
const char *fname;
if (ap_shm_init(&scoreboard_shm, SCOREBOARD_SIZE + NEW_SCOREBOARD_SIZE + 40, fname, p) != APR_SUCCESS) {
int running_gen = 0;
if (ap_scoreboard_image)
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(HAVE_GETTIMEOFDAY)
#ifdef HAVE_TIMES
#if !defined(HAVE_GETTIMEOFDAY)
#ifdef HAVE_TIMES
int actual_pid;
for (i = 0; i < max_daemons_limit; ++i)
#ifndef MULTITHREAD
int i, status;
int not_dead_yet;
not_dead_yet = 0;
for (i = 0; i < max_daemons_limit; ++i) {
++not_dead_yet;
switch (tries) {
0, server_conf,
pid);
0, server_conf,
pid);
pid);
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;
#ifdef APR_HAS_OTHER_CHILD
return NULL;
return ret;
#ifdef NEED_WAITPID
return ret;
return NULL;
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 requests_this_child;
int ap_graceful_stop_signalled(void)
if (deferred_die ||
int sockdes;
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)
goto got_listener;
if (!lr)
usr1_just_die = 0;
if (deferred_die) {
clean_child_exit(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 ENETDOWN
case ENETDOWN:
#ifdef TPF
case EINACT:
if (ap_graceful_stop_signalled()) {
clean_child_exit(0);
#ifdef TPF
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
int pid;
pid);
case SIGTERM:
case SIGHUP:
case SIGUSR1:
case SIGKILL:
#ifdef SYS_SIGLIST
#ifdef WCOREDUMP
0, server_conf,
0, server_conf,
#ifdef WCOREDUMP
int sockdes;
for (i = 0; i < STATUSES_PER_CONNECTION; i++) {
if (maintain_connection_status) {
server_conf = s;
if (setup_listeners(s)) {
if (!is_graceful) {
#ifdef SCOREBOARD_FILE
set_signals();
if (!is_graceful) {
int child_slot;
if (child_slot >= 0) {
#ifdef APR_HAS_OTHER_CHILD
else if (is_graceful) {
0, server_conf,
else if (remaining_children_to_start) {
#ifdef TPF
if (shutdown_pending) {
0, server_conf,
if (one_process) {
if (is_graceful) {
#ifndef SCOREBOARD_FILE
#ifndef SCOREBOARD_FILE
for (i = 0; i < ap_daemons_limit; ++i) {
if (!is_graceful) {
static int restart_num = 0;
is_graceful = 0;
if (!one_process) {
unixd_detach();
ap_extended_status = 0;
static void prefork_hooks(void)
INIT_SIGLIST();
#ifdef AUX3
(void) set42sig();
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;
while (i < STATUSES_PER_CONNECTION) {
return NULL;
long *array_slot;
for (i = 0; i < max_daemons_limit; i++) {
*array_slot = i;
return connection_list;
char **array_slot;
while (i < STATUSES_PER_CONNECTION) {
return key_list;
const char *value)
if (!maintain_connection_status) return;
while (i < STATUSES_PER_CONNECTION) {
if (i >= STATUSES_PER_CONNECTION) {
for (i = 0; i < max_daemons_limit; i++) {
for (j = 0; j < STATUSES_PER_CONNECTION; j++) {
return server_status;
{ NULL }