perchild.c revision 4cfd7921c87712adaf1c77d62898c478c4c79828
0b152383e04dbeb10dba29bcdfaa0981e4d9df27Simon Ulbricht/* ====================================================================
0b152383e04dbeb10dba29bcdfaa0981e4d9df27Simon Ulbricht * The Apache Software License, Version 1.1
0b152383e04dbeb10dba29bcdfaa0981e4d9df27Simon Ulbricht * Copyright (c) 2000 The Apache Software Foundation. All rights
0b152383e04dbeb10dba29bcdfaa0981e4d9df27Simon Ulbricht * Redistribution and use in source and binary forms, with or without
0b152383e04dbeb10dba29bcdfaa0981e4d9df27Simon Ulbricht * modification, are permitted provided that the following conditions
0b152383e04dbeb10dba29bcdfaa0981e4d9df27Simon Ulbricht * 1. Redistributions of source code must retain the above copyright
0b152383e04dbeb10dba29bcdfaa0981e4d9df27Simon Ulbricht * notice, this list of conditions and the following disclaimer.
2643008447e30b6025f742eb6a661f38be756b1eSimon Ulbricht * 2. Redistributions in binary form must reproduce the above copyright
9da6e0cb2ea6e43f5b09dcd2a9af5468a5d0fcf4Christian Maeder * notice, this list of conditions and the following disclaimer in
2643008447e30b6025f742eb6a661f38be756b1eSimon Ulbricht * the documentation and/or other materials provided with the
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * distribution.
d815d2b83e945875100ceca322ebd50d96714206Simon Ulbricht * 3. The end-user documentation included with the redistribution,
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * if any, must include the following acknowledgment:
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * "This product includes software developed by the
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * Apache Software Foundation (http://www.apache.org/)."
abea93ed557b22ea833e1524ee5ca11afc12208aSimon Ulbricht * Alternately, this acknowledgment may appear in the software itself,
a210c2e5add831cd438183c8602ed8e610922beaSimon Ulbricht * if and wherever such third-party acknowledgments normally appear.
a210c2e5add831cd438183c8602ed8e610922beaSimon Ulbricht * 4. The names "Apache" and "Apache Software Foundation" must
6150196e8d99f7161a622fdc1a872fecd378195fSimon Ulbricht * not be used to endorse or promote products derived from this
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * software without prior written permission. For written
9da6e0cb2ea6e43f5b09dcd2a9af5468a5d0fcf4Christian Maeder * permission, please contact apache@apache.org.
3209c34f23fb83a86fbbdd6501db6d4bfb949a57Simon Ulbricht * 5. Products derived from this software may not be called "Apache",
2643008447e30b6025f742eb6a661f38be756b1eSimon Ulbricht * nor may "Apache" appear in their name, without prior written
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * permission of the Apache Software Foundation.
a210c2e5add831cd438183c8602ed8e610922beaSimon Ulbricht * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
a210c2e5add831cd438183c8602ed8e610922beaSimon Ulbricht * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
a210c2e5add831cd438183c8602ed8e610922beaSimon Ulbricht * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
9da6e0cb2ea6e43f5b09dcd2a9af5468a5d0fcf4Christian Maeder * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
9da6e0cb2ea6e43f5b09dcd2a9af5468a5d0fcf4Christian Maeder * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
9da6e0cb2ea6e43f5b09dcd2a9af5468a5d0fcf4Christian Maeder * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9da6e0cb2ea6e43f5b09dcd2a9af5468a5d0fcf4Christian Maeder * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
9da6e0cb2ea6e43f5b09dcd2a9af5468a5d0fcf4Christian Maeder * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
9da6e0cb2ea6e43f5b09dcd2a9af5468a5d0fcf4Christian Maeder * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
9da6e0cb2ea6e43f5b09dcd2a9af5468a5d0fcf4Christian Maeder * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
9da6e0cb2ea6e43f5b09dcd2a9af5468a5d0fcf4Christian Maeder * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
9da6e0cb2ea6e43f5b09dcd2a9af5468a5d0fcf4Christian Maeder * SUCH DAMAGE.
abea93ed557b22ea833e1524ee5ca11afc12208aSimon Ulbricht * ====================================================================
9da6e0cb2ea6e43f5b09dcd2a9af5468a5d0fcf4Christian Maeder * This software consists of voluntary contributions made by many
9da6e0cb2ea6e43f5b09dcd2a9af5468a5d0fcf4Christian Maeder * individuals on behalf of the Apache Software Foundation. For more
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * information on the Apache Software Foundation, please see
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * Portions of this software are based upon public domain software
abea93ed557b22ea833e1524ee5ca11afc12208aSimon Ulbricht * originally written at the National Center for Supercomputing Applications,
abea93ed557b22ea833e1524ee5ca11afc12208aSimon Ulbricht * University of Illinois, Urbana-Champaign.
432ac7c08e2592af0660e026051ffb052e88a100Simon Ulbricht#include "http_config.h" /* for read_config */
432ac7c08e2592af0660e026051ffb052e88a100Simon Ulbricht#include "http_core.h" /* for get_remote_host */
a210c2e5add831cd438183c8602ed8e610922beaSimon Ulbricht * Actual definitions of config globals
a210c2e5add831cd438183c8602ed8e610922beaSimon Ulbrichtstatic int threads_to_start = 0; /* Worker threads per child */
a210c2e5add831cd438183c8602ed8e610922beaSimon UlbrichtAPI_VAR_EXPORT const char *ap_scoreboard_fname=NULL;
abea93ed557b22ea833e1524ee5ca11afc12208aSimon Ulbrichttypedef struct {
abea93ed557b22ea833e1524ee5ca11afc12208aSimon Ulbricht const char *sockname; /* The base name for the socket */
abea93ed557b22ea833e1524ee5ca11afc12208aSimon Ulbricht const char *fullsockname; /* socket base name + extension */
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht/* Tables used to determine the user and group each child process should
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * run as. The hash table is used to correlate a server name with a child
a210c2e5add831cd438183c8602ed8e610922beaSimon Ulbrichtstatic child_info_t child_info_table[HARD_SERVER_LIMIT];
a210c2e5add831cd438183c8602ed8e610922beaSimon Ulbrichtstatic int thread_socket_table[HARD_THREAD_LIMIT];
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbrichtstruct ap_ctable ap_child_table[HARD_SERVER_LIMIT];
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * The max child slot ever assigned, preserved across restarts. Necessary
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * to deal with NumServers changes across SIGWINCH restarts. We use this
a210c2e5add831cd438183c8602ed8e610922beaSimon Ulbricht * value to optimize routines that have to scan the entire child table.
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * XXX - It might not be worth keeping this code in. There aren't very
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * many child processes in this MPM.
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht/* *Non*-shared http_main globals... */
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht/* one_process --- debugging mode variable; can be set from the command line
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * with the -X flag. If set, this gets you the child_main loop running
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * in the process which originally started up (no detach, no make_child),
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * which is a pretty nice debugging environment. (You'll get a SIGHUP
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * early in standalone_main; just continue through. This is the server
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * trying to kill off any child processes which it might have lying
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * around --- Apache doesn't keep track of their pids, it just sends
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * SIGHUP to the process group, ignoring it in the root process.
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * Continue through and you'll be fine.).
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbrichtstatic apr_pool_t *pconf; /* Pool for config stuff */
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbrichtstatic apr_pool_t *pchild; /* Pool for httpd child stuff */
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbrichtstatic apr_pool_t *thread_pool_parent; /* Parent of per-thread pools */
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbrichtstatic pthread_mutex_t thread_pool_parent_mutex;
1651c7f5055453e18a8c34f96c333e2aa702a34eSimon Ulbrichtstatic unsigned int my_pid; /* Linux getpid() doesn't work except in
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht main thread. Use this instead */
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht/* Keep track of the number of worker threads currently active */
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbrichtstatic pthread_mutex_t worker_thread_count_mutex;
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbrichtstatic int worker_thread_free_ids[HARD_THREAD_LIMIT];
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht/* Keep track of the number of idle worker threads */
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbrichtstatic pthread_mutex_t idle_thread_count_mutex;
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht/* Locks for accept serialization */
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht#endif /* NO_SERIALIZED_ACCEPT */
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbrichtstatic const char *lock_fname;
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbrichtstatic pthread_mutex_t thread_accept_mutex = PTHREAD_MUTEX_INITIALIZER;
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht/* a clean exit from a child with proper cleanup */
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht/* handle all varieties of core dumping signals */
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht /* At this point we've got sig blocked, because we're still inside
1651c7f5055453e18a8c34f96c333e2aa702a34eSimon Ulbricht * the signal handler. When we leave the signal handler it will
1651c7f5055453e18a8c34f96c333e2aa702a34eSimon Ulbricht * be unblocked, and we'll take the signal... and coredump or whatever
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * is appropriate for this particular Unix. In addition the parent
a210c2e5add831cd438183c8602ed8e610922beaSimon Ulbricht * will see the real signal we received -- whereas if we called
1651c7f5055453e18a8c34f96c333e2aa702a34eSimon Ulbricht * abort() here, the parent would only see SIGABRT.
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht/*****************************************************************
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * Connection structures and accounting...
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht/* volatile just in case */
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbrichtstatic int volatile shutdown_pending;
987c9ee1092c7fd8b53242abefe4f3cf8e9a1011Simon Ulbrichtstatic int volatile restart_pending;
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbrichtstatic int volatile is_graceful;
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * ap_start_shutdown() and ap_start_restart(), below, are a first stab at
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * functions to initiate shutdown or restart without relying on signals.
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * Previously this was initiated in sig_term() and restart() signal handlers,
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * but we want to be able to start a shutdown/restart from other sources --
a210c2e5add831cd438183c8602ed8e610922beaSimon Ulbricht * e.g. on Win32, from the service manager. Now the service manager can
1651c7f5055453e18a8c34f96c333e2aa702a34eSimon Ulbricht * call ap_start_shutdown() or ap_start_restart() as appropiate. Note that
a210c2e5add831cd438183c8602ed8e610922beaSimon Ulbricht * these functions can also be called by the child processes, since global
1651c7f5055453e18a8c34f96c333e2aa702a34eSimon Ulbricht * variables are no longer used to pass on the required action to the parent.
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * These should only be called from the parent process itself, since the
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * parent process will use the shutdown_pending and restart_pending variables
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * to determine whether to shutdown or restart. The child process should
a210c2e5add831cd438183c8602ed8e610922beaSimon Ulbricht * call signal_parent() directly to tell the parent to die -- this will
a210c2e5add831cd438183c8602ed8e610922beaSimon Ulbricht * cause neither of those variable to be set, which the parent will
53d3b5d18cae658f0e54872ade90ab5259b52b95Simon Ulbricht * assume means something serious is wrong (which it will be, for the
53d3b5d18cae658f0e54872ade90ab5259b52b95Simon Ulbricht * child to force an exit) and so do an exit anyway.
53d3b5d18cae658f0e54872ade90ab5259b52b95Simon Ulbricht /* Um, is this _probably_ not an error, if the user has
7c84f8fd92ed59eb2b9a674e6b1ea93c0f945006Simon Ulbricht * tried to do a shutdown twice quickly, so we won't
53d3b5d18cae658f0e54872ade90ab5259b52b95Simon Ulbricht * worry about reporting it.
53d3b5d18cae658f0e54872ade90ab5259b52b95Simon Ulbricht/* do a graceful restart if graceful == 1 */
987c9ee1092c7fd8b53242abefe4f3cf8e9a1011Simon Ulbricht /* Probably not an error - don't bother reporting it */
if (is_graceful) {
#ifndef WIN32
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 SIGWINCH
#ifdef SIGPIPE
int ap_graceful_stop_signalled(void)
return is_graceful;
int csd;
conn_id);
static void *worker_thread(void *);
static int start_thread(void)
int rc;
#ifdef PTHREAD_SETS_ERRNO
static int reported = 0;
if (!reported) {
static void check_pipe_of_death(void)
if (!workers_may_exit) {
int ret;
char pipe_read_char;
int srv;
for(n=0 ; n <= num_listenfds ; ++n) {
while (!workers_may_exit) {
if (workers_may_exit) break;
if (!thread_just_started) {
thread_just_started = 0;
if (workers_may_exit) {
!= APR_SUCCESS) {
while (!workers_may_exit) {
if (workers_may_exit) break;
goto got_from_other_child;
goto got_fd;
curr_pollfd++;
goto got_fd;
if (!workers_may_exit) {
!= APR_SUCCESS) {
if (!start_thread()) {
!= APR_SUCCESS) {
if (worker_thread_count == 0) {
return NULL;
if (!geteuid()) {
const char *name;
(unsigned)uid);
(unsigned)gid);
return unixd_setup_child();
if (!geteuid() && (
#ifdef _OSD_POSIX
int signal_received;
pchild));
#ifdef SIGPROCMASK_SETS_THREAD_MASK
#ifdef PTHREAD_SETS_ERRNO
worker_thread_count = 0;
for (i = 0; i < max_threads; i++) {
worker_thread_free_ids[i] = i;
for (i=0; i < threads_to_start; i++) {
if (!start_thread()) {
switch (signal_received) {
case SIGTERM:
case SIGINT:
int pid;
if (one_process) {
set_signals();
if (!pid) {
#ifdef AIX_BIND_PROCESSOR
return number_to_start;
#ifndef MAX_SPAWN_RATE
static int hold_off_on_exponential_spawning;
static void perform_child_maintenance(void)
int free_length;
free_length = 0;
for (i = 0; i < num_daemons; ++i) {
++free_length;
last_non_dead = i;
if (free_length > 0) {
for (i = 0; i < free_length; ++i) {
int child_slot;
for (i = 0; i < ap_max_daemons_limit; ++i) {
child_slot = i;
for (j = 0; j < HARD_THREAD_LIMIT; j++) {
if (child_slot >= 0) {
else if (is_graceful) {
else if (remaining_children_to_start) {
ap_server_conf = s;
!= APR_SUCCESS) {
ap_server_conf = s;
my_pid);
if (!is_graceful) {
if (!is_graceful) {
for (i = 0; i < HARD_SERVER_LIMIT; i++) {
set_signals();
if (!is_graceful) {
if (shutdown_pending) {
if (one_process) {
if (is_graceful) {
for (i = 0; i < num_daemons; ++i) {
for (i = 0; i < num_daemons;) {
static int restart_num = 0;
int no_detach = 0;
is_graceful = 0;
apr_detach();
curr_child_num = 0;
for (i = 0; i < HARD_SERVER_LIMIT; i++) {
for (i = 0; i < HARD_THREAD_LIMIT; i++) {
int sfd;
return NULL;
for (i = 0; i < num_daemons; i++) {
return OK;
return OK;
return OK;
static void perchild_hooks(void)
one_process = 0;
return err;
return NULL;
return err;
return NULL;
return err;
return NULL;
return err;
return NULL;
return err;
return NULL;
return err;
if (min_spare_threads <= 0) {
return NULL;
return err;
return NULL;
return err;
return NULL;
return err;
return NULL;
return err;
return NULL;
const char *fname;
return err;
return NULL;
const char *g, const char *num)
if (i > num_daemons) {
return NULL;
const char *gid)
const char *errstr;
return errstr;
for (i = 0; i < num_daemons; i++) {
return NULL;
{ NULL }
perchild_server_conf *c =