prefork.c revision cccd31fa4a72fe23cc3249c06db181b274a55a69
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek/* ====================================================================
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek * The Apache Software License, Version 1.1
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek * Copyright (c) 2000 The Apache Software Foundation. All rights
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek * Redistribution and use in source and binary forms, with or without
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek * modification, are permitted provided that the following conditions
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek * 1. Redistributions of source code must retain the above copyright
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek * notice, this list of conditions and the following disclaimer.
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek * 2. Redistributions in binary form must reproduce the above copyright
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek * notice, this list of conditions and the following disclaimer in
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek * the documentation and/or other materials provided with the
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek * distribution.
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek * 3. The end-user documentation included with the redistribution,
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek * if any, must include the following acknowledgment:
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek * "This product includes software developed by the
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek * Apache Software Foundation (http://www.apache.org/)."
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek * Alternately, this acknowledgment may appear in the software itself,
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek * if and wherever such third-party acknowledgments normally appear.
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek * 4. The names "Apache" and "Apache Software Foundation" must
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek * not be used to endorse or promote products derived from this
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek * software without prior written permission. For written
cc2d77d5218c188119fa954c856e858cbde76947Pavel Březina * permission, please contact apache@apache.org.
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek * 5. Products derived from this software may not be called "Apache",
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek * nor may "Apache" appear in their name, without prior written
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek * permission of the Apache Software Foundation.
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38ebc764eeb7693e0c4f0894d6687e54fbba871bJakub Hrozek * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
e15a9f81eb33066937710d7dee6976a3646d119cJakub Hrozek * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek * SUCH DAMAGE.
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek * ====================================================================
33df734b39538eeb870b118b7feea76f90bb004bJakub Hrozek * This software consists of voluntary contributions made by many
33df734b39538eeb870b118b7feea76f90bb004bJakub Hrozek * individuals on behalf of the Apache Software Foundation. For more
33df734b39538eeb870b118b7feea76f90bb004bJakub Hrozek * information on the Apache Software Foundation, please see
33df734b39538eeb870b118b7feea76f90bb004bJakub Hrozek * Portions of this software are based upon public domain software
33df734b39538eeb870b118b7feea76f90bb004bJakub Hrozek * originally written at the National Center for Supercomputing Applications,
33df734b39538eeb870b118b7feea76f90bb004bJakub Hrozek * University of Illinois, Urbana-Champaign.
33df734b39538eeb870b118b7feea76f90bb004bJakub Hrozek * httpd.c: simple http daemon for answering WWW file requests
#include "apr.h"
#include "apr_portable.h"
#include "apr_strings.h"
#include "apr_thread_proc.h"
#if APR_HAVE_STDIO_H
#define CORE_PRIVATE
#include "ap_config.h"
#include "httpd.h"
#include "mpm_default.h"
#include "mpm_status.h"
#include "http_main.h"
#include "http_log.h"
#include "http_config.h"
#include "http_connection.h"
#include "scoreboard.h"
#include "ap_mpm.h"
#include "unixd.h"
#include "mpm_common.h"
#include "ap_listen.h"
#include "ap_mmn.h"
#ifdef HAVE_SYS_TYPES_H
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#ifdef HAVE_NETINET_TCP_H
#ifdef HAVE_BSTRING_H
#ifdef HAVE_STRINGS_H
#include <strings.h>
#ifdef HAVE_TIME_H
#include <time.h>
#include <signal.h>
static int ap_max_requests_per_child=0;
static const 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 (rv) {
if (rv) {
static void accept_mutex_on(void)
static void accept_mutex_off(void)
#include "apr_shmem.h"
return APR_SUCCESS;
const char *fname;
if (apr_shm_init(&scoreboard_shm, SCOREBOARD_SIZE + NEW_SCOREBOARD_SIZE + 80, fname, p) != APR_SUCCESS) {
int running_gen = 0;
if (ap_scoreboard_image)
setup_shared_mem(p);
#ifdef SCOREBOARD_FILE
return ap_max_daemons_limit;
#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)
for (i = 0; i < ap_max_daemons_limit; ++i)
#if defined(NEED_WAITPID)
int n, pid;
for (n = 0; n < ap_max_daemons_limit; ++n) {
return(pid);
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 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 (stat) {
#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 sockdes;
for (i = 0; i < STATUSES_PER_CONNECTION; i++) {
if (maintain_connection_status) {
ap_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) {
else if (is_graceful) {
0, ap_server_conf,
else if (remaining_children_to_start) {
#ifdef TPF
if (shutdown_pending) {
0, ap_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;
int no_detach = 0;
is_graceful = 0;
apr_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 < ap_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 < ap_max_daemons_limit; i++) {
for (j = 0; j < STATUSES_PER_CONNECTION; j++) {
return server_status;
{ NULL }