prefork.c revision 4e0e544abc732ca30b5f58c387a93d877cf51e24
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq/* ====================================================================
78cd48acd325773619d78ac0d7263a99a8922faend * The Apache Software License, Version 1.1
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding *
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * Copyright (c) 2000 The Apache Software Foundation. All rights
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * reserved.
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd *
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * Redistribution and use in source and binary forms, with or without
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * modification, are permitted provided that the following conditions
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * are met:
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd *
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * 1. Redistributions of source code must retain the above copyright
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * notice, this list of conditions and the following disclaimer.
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd *
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * 2. Redistributions in binary form must reproduce the above copyright
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * notice, this list of conditions and the following disclaimer in
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * the documentation and/or other materials provided with the
7708bd70088b64148d7d78fd84ede43ced63c713minfrin * distribution.
7708bd70088b64148d7d78fd84ede43ced63c713minfrin *
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * 3. The end-user documentation included with the redistribution,
36a72c96fc2dda27eadbae8a108fa428cc1419c1wrowe * if any, must include the following acknowledgment:
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * "This product includes software developed by the
1723d9ccdd3b647f5b7bae44cab9ab3eca7a4874dougm * Apache Software Foundation (http://www.apache.org/)."
2555a6b5da21d61804f47084d8fcc98eb4acbc42wrowe * Alternately, this acknowledgment may appear in the software itself,
2555a6b5da21d61804f47084d8fcc98eb4acbc42wrowe * if and wherever such third-party acknowledgments normally appear.
70535d6421eb979ac79d8f49d31cd94d75dd8b2fjorton *
2555a6b5da21d61804f47084d8fcc98eb4acbc42wrowe * 4. The names "Apache" and "Apache Software Foundation" must
2555a6b5da21d61804f47084d8fcc98eb4acbc42wrowe * not be used to endorse or promote products derived from this
2555a6b5da21d61804f47084d8fcc98eb4acbc42wrowe * software without prior written permission. For written
2555a6b5da21d61804f47084d8fcc98eb4acbc42wrowe * permission, please contact apache@apache.org.
1723d9ccdd3b647f5b7bae44cab9ab3eca7a4874dougm *
e9501b71b8a1e76384cb010b1e41e76a1e47aacctrawick * 5. Products derived from this software may not be called "Apache",
e9501b71b8a1e76384cb010b1e41e76a1e47aacctrawick * nor may "Apache" appear in their name, without prior written
e9501b71b8a1e76384cb010b1e41e76a1e47aacctrawick * permission of the Apache Software Foundation.
6335eb31f0f0ed54628a04ed32946360b8b77684minfrin *
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * SUCH DAMAGE.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * ====================================================================
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding *
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * This software consists of voluntary contributions made by many
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * individuals on behalf of the Apache Software Foundation. For more
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * information on the Apache Software Foundation, please see
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq * <http://www.apache.org/>.
a812b025d139f465a31c76fc02ed162ed5271b03nd *
a812b025d139f465a31c76fc02ed162ed5271b03nd * Portions of this software are based upon public domain software
a812b025d139f465a31c76fc02ed162ed5271b03nd * originally written at the National Center for Supercomputing Applications,
a812b025d139f465a31c76fc02ed162ed5271b03nd * University of Illinois, Urbana-Champaign.
a812b025d139f465a31c76fc02ed162ed5271b03nd */
a812b025d139f465a31c76fc02ed162ed5271b03nd
a812b025d139f465a31c76fc02ed162ed5271b03nd/*
a812b025d139f465a31c76fc02ed162ed5271b03nd * httpd.c: simple http daemon for answering WWW file requests
a812b025d139f465a31c76fc02ed162ed5271b03nd *
a812b025d139f465a31c76fc02ed162ed5271b03nd *
a812b025d139f465a31c76fc02ed162ed5271b03nd * 03-21-93 Rob McCool wrote original code (up to NCSA HTTPd 1.3)
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq *
a812b025d139f465a31c76fc02ed162ed5271b03nd * 03-06-95 blong
00211b036b78699ace57a6d800a52e6c2d57652fnd * changed server number for child-alone processes to 0 and changed name
00211b036b78699ace57a6d800a52e6c2d57652fnd * of processes
00211b036b78699ace57a6d800a52e6c2d57652fnd *
a812b025d139f465a31c76fc02ed162ed5271b03nd * 03-10-95 blong
a812b025d139f465a31c76fc02ed162ed5271b03nd * Added numerous speed hacks proposed by Robert S. Thau (rst@ai.mit.edu)
a812b025d139f465a31c76fc02ed162ed5271b03nd * including set group before fork, and call gettime before to fork
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq * to set up libraries.
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq *
a812b025d139f465a31c76fc02ed162ed5271b03nd * 04-14-95 rst / rh
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe * Brandon's code snarfed from NCSA 1.4, but tinkered to work with the
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe * Apache server, and also to have child processes do accept() directly.
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe *
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe * April-July '95 rst
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe * Extensive rework for Apache.
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe */
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe/* TODO: this is a cobbled together prefork MPM example... it should mostly
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe * TODO: behave like apache-1.3... here's a short list of things I think
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe * TODO: need cleaning up still:
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe * TODO: - clean up scoreboard stuff when we figure out how to do it in 2.0
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe */
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe#define CORE_PRIVATE
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe#include "ap_config.h"
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe#include "apr_portable.h"
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe#include "apr_thread_proc.h"
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe#include "httpd.h"
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe#include "mpm_default.h"
9621e4c4056383e4a2b844b14687bae500b33a82wrowe#include "mpm_status.h"
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe#include "http_main.h"
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe#include "http_log.h"
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe#include "http_config.h"
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe#include "http_core.h" /* for get_remote_host */
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe#include "http_connection.h"
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe#include "scoreboard.h"
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe#include "ap_mpm.h"
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe#include "unixd.h"
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe#include "mpm_common.h"
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe#include "iol_socket.h"
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe#include "ap_listen.h"
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe#include "ap_mmn.h"
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe#ifdef HAVE_SYS_TYPES_H
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe#include <sys/types.h>
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe#endif
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe#ifdef HAVE_SYS_WAIT_H
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe#include <sys/wait.h>
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe#endif
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe#ifdef HAVE_SYS_SOCKET_H
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe#include <sys/socket.h>
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe#endif
9621e4c4056383e4a2b844b14687bae500b33a82wrowe#ifdef HAVE_UNISTD_H
9621e4c4056383e4a2b844b14687bae500b33a82wrowe#include <unistd.h>
9621e4c4056383e4a2b844b14687bae500b33a82wrowe#endif
9621e4c4056383e4a2b844b14687bae500b33a82wrowe#ifdef HAVE_NETINET_TCP_H
9621e4c4056383e4a2b844b14687bae500b33a82wrowe#include <netinet/tcp.h> /* for TCP_NODELAY */
9621e4c4056383e4a2b844b14687bae500b33a82wrowe#endif
9621e4c4056383e4a2b844b14687bae500b33a82wrowe
4c67ef499845a08771e81254ce6eb2324a160bc7wrowe#ifdef HAVE_BSTRING_H
4c67ef499845a08771e81254ce6eb2324a160bc7wrowe#include <bstring.h> /* for IRIX, FD_SET calls bzero() */
4c67ef499845a08771e81254ce6eb2324a160bc7wrowe#endif
4c67ef499845a08771e81254ce6eb2324a160bc7wrowe#ifdef HAVE_STRINGS_H
4c67ef499845a08771e81254ce6eb2324a160bc7wrowe#include <strings.h>
4c67ef499845a08771e81254ce6eb2324a160bc7wrowe#endif
4c67ef499845a08771e81254ce6eb2324a160bc7wrowe#ifdef HAVE_TIME_H
4415d997ac73262e513c0a571bd5be4f609040bawrowe#include <time.h>
4415d997ac73262e513c0a571bd5be4f609040bawrowe#endif
4415d997ac73262e513c0a571bd5be4f609040bawrowe#include <signal.h>
4415d997ac73262e513c0a571bd5be4f609040bawrowe#include <sys/times.h>
4415d997ac73262e513c0a571bd5be4f609040bawrowe
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe/* config globals */
5a5a6c22260854843c973e2ea9a14bec64362ab5wrowe
4415d997ac73262e513c0a571bd5be4f609040bawrowestatic int ap_max_requests_per_child=0;
4415d997ac73262e513c0a571bd5be4f609040bawrowestatic const char *ap_pid_fname=NULL;
4415d997ac73262e513c0a571bd5be4f609040bawrowestatic ap_lock_t *accept_lock;
4415d997ac73262e513c0a571bd5be4f609040bawrowestatic const char *ap_scoreboard_fname=NULL;
4415d997ac73262e513c0a571bd5be4f609040bawrowestatic const char *ap_lock_fname;
4415d997ac73262e513c0a571bd5be4f609040bawrowestatic int ap_daemons_to_start=0;
4415d997ac73262e513c0a571bd5be4f609040bawrowestatic int ap_daemons_min_free=0;
4415d997ac73262e513c0a571bd5be4f609040bawrowestatic int ap_daemons_max_free=0;
4415d997ac73262e513c0a571bd5be4f609040bawrowestatic int ap_daemons_limit=0;
4415d997ac73262e513c0a571bd5be4f609040bawrowestatic time_t ap_restart_time=0;
4415d997ac73262e513c0a571bd5be4f609040bawrowestatic int ap_extended_status = 0;
4415d997ac73262e513c0a571bd5be4f609040bawrowestatic int maintain_connection_status = 1;
4415d997ac73262e513c0a571bd5be4f609040bawrowe
4415d997ac73262e513c0a571bd5be4f609040bawrowe/*
4415d997ac73262e513c0a571bd5be4f609040bawrowe * The max child slot ever assigned, preserved across restarts. Necessary
4415d997ac73262e513c0a571bd5be4f609040bawrowe * to deal with MaxClients changes across SIGUSR1 restarts. We use this
4415d997ac73262e513c0a571bd5be4f609040bawrowe * value to optimize routines that have to scan the entire scoreboard.
4415d997ac73262e513c0a571bd5be4f609040bawrowe */
4415d997ac73262e513c0a571bd5be4f609040bawroweint ap_max_daemons_limit = -1;
4415d997ac73262e513c0a571bd5be4f609040bawroweserver_rec *ap_server_conf;
4415d997ac73262e513c0a571bd5be4f609040bawrowe
4415d997ac73262e513c0a571bd5be4f609040bawrowechar ap_coredump_dir[MAX_STRING_LEN];
4415d997ac73262e513c0a571bd5be4f609040bawrowe
4415d997ac73262e513c0a571bd5be4f609040bawrowe/* *Non*-shared http_main globals... */
4415d997ac73262e513c0a571bd5be4f609040bawrowe
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowestatic ap_socket_t *sd;
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowestatic fd_set listenfds;
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowestatic int listenmaxfd;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding/* one_process --- debugging mode variable; can be set from the command line
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * with the -X flag. If set, this gets you the child_main loop running
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * in the process which originally started up (no detach, no make_child),
00211b036b78699ace57a6d800a52e6c2d57652fnd * which is a pretty nice debugging environment. (You'll get a SIGHUP
a812b025d139f465a31c76fc02ed162ed5271b03nd * early in standalone_main; just continue through. This is the server
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * trying to kill off any child processes which it might have lying
00211b036b78699ace57a6d800a52e6c2d57652fnd * around --- Apache doesn't keep track of their pids, it just sends
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard * SIGHUP to the process group, ignoring it in the root process.
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard * Continue through and you'll be fine.).
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard */
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddardstatic int one_process = 0;
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddardstatic ap_pool_t *pconf; /* Pool for config stuff */
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddardstatic ap_pool_t *pchild; /* Pool for httpd child stuff */
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddardint ap_my_pid; /* it seems silly to call getpid all the time */
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard#ifndef MULTITHREAD
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddardstatic int my_child_num;
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard#endif
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard#ifdef TPF
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddardint tpf_child = 0;
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddardchar tpf_server_name[INETD_SERVNAME_LENGTH+1];
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq#endif /* TPF */
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq
a812b025d139f465a31c76fc02ed162ed5271b03ndAPI_VAR_EXPORT scoreboard *ap_scoreboard_image = NULL;
a812b025d139f465a31c76fc02ed162ed5271b03ndstatic new_scoreboard *ap_new_scoreboard_image = NULL;
a812b025d139f465a31c76fc02ed162ed5271b03nd
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq#ifdef GPROF
a812b025d139f465a31c76fc02ed162ed5271b03nd/*
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq * change directory for gprof to plop the gmon.out file
a812b025d139f465a31c76fc02ed162ed5271b03nd * configure in httpd.conf:
a812b025d139f465a31c76fc02ed162ed5271b03nd * GprofDir logs/ -> $ServerRoot/logs/gmon.out
a812b025d139f465a31c76fc02ed162ed5271b03nd * GprofDir logs/% -> $ServerRoot/logs/gprof.$pid/gmon.out
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq */
a812b025d139f465a31c76fc02ed162ed5271b03ndstatic void chdir_for_gprof(void)
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq{
a812b025d139f465a31c76fc02ed162ed5271b03nd core_server_config *sconf =
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq ap_get_module_config(ap_server_conf->module_config, &core_module);
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq char *dir = sconf->gprof_dir;
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard if(dir) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding char buf[512];
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding int len = strlen(sconf->gprof_dir) - 1;
00211b036b78699ace57a6d800a52e6c2d57652fnd if(*(dir + len) == '%') {
00211b036b78699ace57a6d800a52e6c2d57652fnd dir[len] = '\0';
00211b036b78699ace57a6d800a52e6c2d57652fnd ap_snprintf(buf, sizeof(buf), "%sgprof.%d", dir, (int)getpid());
00211b036b78699ace57a6d800a52e6c2d57652fnd }
00211b036b78699ace57a6d800a52e6c2d57652fnd dir = ap_server_root_relative(pconf, buf[0] ? buf : dir);
00211b036b78699ace57a6d800a52e6c2d57652fnd if(mkdir(dir, 0755) < 0 && errno != EEXIST) {
00211b036b78699ace57a6d800a52e6c2d57652fnd ap_log_error(APLOG_MARK, APLOG_ERR, errno, ap_server_conf,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding "gprof: error creating directory %s", dir);
00211b036b78699ace57a6d800a52e6c2d57652fnd }
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding }
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard else {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding dir = ap_server_root_relative(pconf, "logs");
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding }
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding chdir(dir);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding}
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding#else
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding#define chdir_for_gprof()
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding#endif
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding/* XXX - I don't know if TPF will ever use this module or not, so leave
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * the ap_check_signals calls in but disable them - manoj */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding#define ap_check_signals()
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding/* a clean exit from a child with proper cleanup */
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingstatic void clean_child_exit(int code) __attribute__ ((noreturn));
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingstatic void clean_child_exit(int code)
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding{
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding if (pchild) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_destroy_pool(pchild);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding }
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding chdir_for_gprof();
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding exit(code);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding}
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq
a812b025d139f465a31c76fc02ed162ed5271b03ndstatic void expand_lock_fname(ap_pool_t *p)
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq{
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq /* XXXX possibly bogus cast */
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq ap_lock_fname = ap_psprintf(p, "%s.%lu",
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq ap_server_root_relative(p, ap_lock_fname), (unsigned long)getpid());
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding}
16d38ac65d7e54cd44eeda7b23f84ee68b35094ewrowe
16d38ac65d7e54cd44eeda7b23f84ee68b35094ewrowe/* Initialize mutex lock.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * Done by each child at its birth
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard */
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddardstatic void accept_mutex_child_init(ap_pool_t *p)
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard{
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard ap_child_init_lock(&accept_lock, ap_lock_fname, p);
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard}
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard/* Initialize mutex lock.
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard * Must be safe to call this on a restart.
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard */
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddardstatic void accept_mutex_init(ap_pool_t *p)
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding{
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_status_t rv;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding expand_lock_fname(p);
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard rv = ap_create_lock(&accept_lock, APR_MUTEX, APR_CROSS_PROCESS, ap_lock_fname, p);
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard if (rv) {
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard ap_log_error(APLOG_MARK, APLOG_ERR, rv, NULL, "couldn't create accept mutex");
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard }
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard}
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard
33cb45dc8c5106018b7c2f6ae42478b109423e0eniqstatic void accept_mutex_on(void)
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq{
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq ap_status_t rv = ap_lock(accept_lock);
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq ap_assert(!rv);
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq}
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq
33cb45dc8c5106018b7c2f6ae42478b109423e0eniqstatic void accept_mutex_off(void)
a812b025d139f465a31c76fc02ed162ed5271b03nd{
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq ap_status_t rv = ap_unlock(accept_lock);
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq ap_assert(!rv);
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq}
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq/* On some architectures it's safe to do unserialized accept()s in the single
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq * Listen case. But it's never safe to do it in the case where there's
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq * multiple Listen statements. Define SINGLE_LISTEN_UNSERIALIZED_ACCEPT
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * when it's safe in the single Listen case.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding#ifdef SINGLE_LISTEN_UNSERIALIZED_ACCEPT
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding#define SAFE_ACCEPT(stmt) do {if (ap_listeners->next) {stmt;}} while(0)
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding#else
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding#define SAFE_ACCEPT(stmt) do {stmt;} while(0)
134330b92fbc39045b7e56654f4c252fb7c53803nd#endif
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding#if APR_HAS_SHARED_MEMORY
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding#include "apr_shmem.h"
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingstatic ap_shmem_t *scoreboard_shm = NULL;
134330b92fbc39045b7e56654f4c252fb7c53803nd
a812b025d139f465a31c76fc02ed162ed5271b03ndstatic ap_status_t cleanup_shared_mem(void *d)
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding{
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard ap_shm_free(scoreboard_shm, ap_scoreboard_image);
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard ap_scoreboard_image = NULL;
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard ap_shm_destroy(scoreboard_shm);
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard return APR_SUCCESS;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding}
a812b025d139f465a31c76fc02ed162ed5271b03nd
33cb45dc8c5106018b7c2f6ae42478b109423e0eniqstatic void setup_shared_mem(ap_pool_t *p)
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding{
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding char buf[512];
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding const char *fname;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding fname = ap_server_root_relative(p, ap_scoreboard_fname);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding if (ap_shm_init(&scoreboard_shm, SCOREBOARD_SIZE + NEW_SCOREBOARD_SIZE + 40, fname, p) != APR_SUCCESS) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_snprintf(buf, sizeof(buf), "%s: could not open(create) scoreboard",
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard ap_server_argv0);
11c3b5180e1de6776035320b012a28bb146e7b46chuck perror(buf);
a812b025d139f465a31c76fc02ed162ed5271b03nd exit(APEXIT_INIT);
22d348febc3c258df246ac93e37945398dbf0348ianh }
22d348febc3c258df246ac93e37945398dbf0348ianh ap_scoreboard_image = ap_shm_malloc(scoreboard_shm, SCOREBOARD_SIZE);
22d348febc3c258df246ac93e37945398dbf0348ianh ap_new_scoreboard_image = ap_shm_malloc(scoreboard_shm, NEW_SCOREBOARD_SIZE);
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm if (ap_scoreboard_image == NULL) {
a812b025d139f465a31c76fc02ed162ed5271b03nd ap_snprintf(buf, sizeof(buf), "%s: cannot allocate scoreboard",
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_server_argv0);
1d7f1b96b49dafbd6cb414fb709cb85de2686a72chuck perror(buf);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_shm_destroy(scoreboard_shm);
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard exit(APEXIT_INIT);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding }
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq ap_register_cleanup(p, NULL, cleanup_shared_mem, ap_null_cleanup);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_scoreboard_image->global.running_generation = 0;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding}
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
9b3001f2097437c3c605d29e353fda5131b9952bminfrinstatic void reopen_scoreboard(ap_pool_t *p)
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe{
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe}
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe#endif
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe/* Called by parent process */
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowestatic void reinit_scoreboard(ap_pool_t *p)
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe{
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe int running_gen = 0;
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard if (ap_scoreboard_image)
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard running_gen = ap_scoreboard_image->global.running_generation;
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe if (ap_scoreboard_image == NULL) {
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe setup_shared_mem(p);
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe }
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe memset(ap_scoreboard_image, 0, SCOREBOARD_SIZE);
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe ap_scoreboard_image->global.running_generation = running_gen;
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe}
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe/* Routines called to deal with the scoreboard image
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe * --- note that we do *not* need write locks, since update_child_status
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe * only updates a *single* record in place, and only one process writes to
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe * a given scoreboard slot at a time (either the child process owning that
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe * slot, or the parent, noting that the child has died).
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe *
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe * As a final note --- setting the score entry to getpid() is always safe,
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe * since when the parent is writing an entry, it's only noting SERVER_DEAD
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe * anyway.
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe */
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwroweap_inline void ap_sync_scoreboard_image(void)
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe{
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe#ifdef SCOREBOARD_FILE
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe lseek(scoreboard_fd, 0L, 0);
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe force_read(scoreboard_fd, ap_scoreboard_image, sizeof(*ap_scoreboard_image))
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe;
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe#endif
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe}
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwroweAPI_EXPORT(int) ap_exists_scoreboard_image(void)
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe{
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe return (ap_scoreboard_image ? 1 : 0);
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe}
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwroweAPI_EXPORT(int) ap_get_max_daemons(void)
8632261c895a84c88ae6ade6ea4c62b27bd22b3ebrianp{
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe return ap_max_daemons_limit;
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe}
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowestatic ap_inline void put_scoreboard_info(int child_num,
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe short_score *new_score_rec)
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe{
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe#ifdef SCOREBOARD_FILE
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe lseek(scoreboard_fd, (long) child_num * sizeof(short_score), 0);
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe force_write(scoreboard_fd, new_score_rec, sizeof(short_score));
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe#endif
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe}
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe
33cb45dc8c5106018b7c2f6ae42478b109423e0eniqint ap_update_child_status(int child_num, int status, request_rec *r)
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding{
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding int old_status;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding short_score *ss;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding if (child_num < 0)
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding return -1;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_check_signals();
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
68ce856106f153813339db8670f6cd0ab8dea484minfrin ss = &ap_scoreboard_image->servers[child_num];
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding old_status = ss->status;
45dac0729754e413ff7c673481b219e9ab1a11f1bnicholes ss->status = status;
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding if (ap_extended_status) {
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq if (status == SERVER_READY || status == SERVER_DEAD) {
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq /*
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq * Reset individual counters
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq */
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq if (status == SERVER_DEAD) {
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq ss->my_access_count = 0L;
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq ss->my_bytes_served = 0L;
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq }
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq ss->conn_count = (unsigned short) 0;
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe ss->conn_bytes = (unsigned long) 0;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding }
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding if (r) {
68ce856106f153813339db8670f6cd0ab8dea484minfrin conn_rec *c = r->connection;
2e41eca72bcc4167d1871b0941ee79845540d58eminfrin ap_cpystrn(ss->client, ap_get_remote_host(c, r->per_dir_config,
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard REMOTE_NOLOOKUP), sizeof(ss->client));
68ce856106f153813339db8670f6cd0ab8dea484minfrin if (r->the_request == NULL) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_cpystrn(ss->request, "NULL", sizeof(ss->request));
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding } else if (r->parsed_uri.password == NULL) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_cpystrn(ss->request, r->the_request, sizeof(ss->request));
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard } else {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* Don't reveal the password in the server-status view */
11c3b5180e1de6776035320b012a28bb146e7b46chuck ap_cpystrn(ss->request, ap_pstrcat(r->pool, r->method, " ",
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_unparse_uri_components(r->pool, &r->parsed_uri, UNP_OMITPASSWORD),
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq r->assbackwards ? NULL : " ", r->protocol, NULL),
11c3b5180e1de6776035320b012a28bb146e7b46chuck sizeof(ss->request));
11c3b5180e1de6776035320b012a28bb146e7b46chuck }
11c3b5180e1de6776035320b012a28bb146e7b46chuck ss->vhostrec = r->server;
11c3b5180e1de6776035320b012a28bb146e7b46chuck }
11c3b5180e1de6776035320b012a28bb146e7b46chuck }
11c3b5180e1de6776035320b012a28bb146e7b46chuck if (status == SERVER_STARTING && r == NULL) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* clean up the slot's vhostrec pointer (maybe re-used)
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * and mark the slot as belonging to a new generation.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ss->vhostrec = NULL;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_scoreboard_image->parent[child_num].generation = ap_my_generation;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding#ifdef SCOREBOARD_FILE
d7387fcd4969206172e3a2a8bbcd25a3d7011ac5rbb lseek(scoreboard_fd, XtOffsetOf(scoreboard, parent[child_num]), 0);
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard force_write(scoreboard_fd, &ap_scoreboard_image->parent[child_num],
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding sizeof(parent_score));
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding#endif
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding }
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding put_scoreboard_info(child_num, ss);
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding return old_status;
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm}
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingstatic void update_scoreboard_global(void)
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding{
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm#ifdef SCOREBOARD_FILE
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard lseek(scoreboard_fd,
b999f6ba2a266bf9a92687f31bb7e76021ac5891ianh (char *) &ap_scoreboard_image->global -(char *) ap_scoreboard_image, 0);
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard force_write(scoreboard_fd, &ap_scoreboard_image->global,
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard sizeof ap_scoreboard_image->global);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding#endif
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm}
1cde33c7e2019830f8fb3224e01649305583916etrawick
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddardvoid ap_time_process_request(int child_num, int status)
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard{
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard short_score *ss;
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding if (child_num < 0)
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding return;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_sync_scoreboard_image();
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ss = &ap_scoreboard_image->servers[child_num];
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding if (status == START_PREQUEST) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ss->start_time = ap_now();
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding }
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding else if (status == STOP_PREQUEST) {
a2f9f38db0931e6edf7b71378dd680c3c5fa5841rbb ss->stop_time = ap_now();
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding }
5babe00918c88eda487771fa6d6d4a1a19c0ced0chuck
5babe00918c88eda487771fa6d6d4a1a19c0ced0chuck put_scoreboard_info(child_num, ss);
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm}
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
2e41eca72bcc4167d1871b0941ee79845540d58eminfrin/*
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingstatic void increment_counts(int child_num, request_rec *r)
35c9e4d2c0a6465746a98958ef756114834461e6minfrin{
35c9e4d2c0a6465746a98958ef756114834461e6minfrin long int bs = 0;
5a5a6c22260854843c973e2ea9a14bec64362ab5wrowe short_score *ss;
d75bc22ab2702fa770f6935f07107efff16a76f0wrowe
11c3b5180e1de6776035320b012a28bb146e7b46chuck ap_sync_scoreboard_image();
35c9e4d2c0a6465746a98958ef756114834461e6minfrin ss = &ap_scoreboard_image->servers[child_num];
45dac0729754e413ff7c673481b219e9ab1a11f1bnicholes
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard if (r->sent_bodyct)
11c3b5180e1de6776035320b012a28bb146e7b46chuck ap_bgetopt(r->connection->client, BO_BYTECT, &bs);
35c9e4d2c0a6465746a98958ef756114834461e6minfrin
35c9e4d2c0a6465746a98958ef756114834461e6minfrin#ifdef HAVE_TIMES
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard times(&ss->times);
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard#endif
e2b2e15108eb7cb566b1d70ce4e479276d951de5minfrin ss->access_count++;
e2b2e15108eb7cb566b1d70ce4e479276d951de5minfrin ss->my_access_count++;
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard ss->conn_count++;
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard ss->bytes_served += (unsigned long) bs;
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard ss->my_bytes_served += (unsigned long) bs;
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard ss->conn_bytes += (unsigned long) bs;
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard put_scoreboard_info(child_num, ss);
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard}
e2b2e15108eb7cb566b1d70ce4e479276d951de5minfrin*/
e2b2e15108eb7cb566b1d70ce4e479276d951de5minfrin
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddardstatic int find_child_by_pid(ap_proc_t *pid)
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard{
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard int i;
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard for (i = 0; i < ap_max_daemons_limit; ++i)
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard if (ap_scoreboard_image->parent[i].pid == pid->pid)
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard return i;
e2b2e15108eb7cb566b1d70ce4e479276d951de5minfrin
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard return -1;
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard}
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard
e2b2e15108eb7cb566b1d70ce4e479276d951de5minfrin#if defined(NEED_WAITPID)
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard/*
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard Systems without a real waitpid sometimes lose a child's exit while waiting
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard for another. Search through the scoreboard for missing children.
35c9e4d2c0a6465746a98958ef756114834461e6minfrin */
35c9e4d2c0a6465746a98958ef756114834461e6minfrinint reap_children(ap_wait_t *status)
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard{
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard int n, pid;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
3d350b6e1cb11fa790a6adb428856b5dd9857fecianh for (n = 0; n < ap_max_daemons_limit; ++n) {
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard ap_sync_scoreboard_image();
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding if (ap_scoreboard_image->servers[n].status != SERVER_DEAD &&
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding kill((pid = ap_scoreboard_image->parent[n].pid), 0) == -1) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_update_child_status(n, SERVER_DEAD, NULL);
409f0f53a83313c59f1b227ed0a340adc1081e88wrowe /* just mark it as having a successful exit status */
409f0f53a83313c59f1b227ed0a340adc1081e88wrowe bzero((char *) status, sizeof(ap_wait_t));
409f0f53a83313c59f1b227ed0a340adc1081e88wrowe return(pid);
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard }
409f0f53a83313c59f1b227ed0a340adc1081e88wrowe }
5babe00918c88eda487771fa6d6d4a1a19c0ced0chuck return 0;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding}
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding#endif
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard/* handle all varieties of core dumping signals */
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddardstatic void sig_coredump(int sig)
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding{
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding chdir(ap_coredump_dir);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_signal(sig, SIG_DFL);
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm kill(getpid(), sig);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* At this point we've got sig blocked, because we're still inside
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * the signal handler. When we leave the signal handler it will
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * be unblocked, and we'll take the signal... and coredump or whatever
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * is appropriate for this particular Unix. In addition the parent
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * will see the real signal we received -- whereas if we called
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * abort() here, the parent would only see SIGABRT.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding */
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard}
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding/*****************************************************************
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard * Connection structures and accounting...
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard */
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingstatic void just_die(int sig)
1cde33c7e2019830f8fb3224e01649305583916etrawick{
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard clean_child_exit(0);
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard}
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingstatic int volatile deferred_die;
002bcf949b064d7c042465d1095cafcfc6c9b701wrowestatic int volatile usr1_just_die;
d75bc22ab2702fa770f6935f07107efff16a76f0wrowe
002bcf949b064d7c042465d1095cafcfc6c9b701wrowestatic void usr1_handler(int sig)
002bcf949b064d7c042465d1095cafcfc6c9b701wrowe{
d75bc22ab2702fa770f6935f07107efff16a76f0wrowe if (usr1_just_die) {
002bcf949b064d7c042465d1095cafcfc6c9b701wrowe just_die(sig);
2e41eca72bcc4167d1871b0941ee79845540d58eminfrin }
2e41eca72bcc4167d1871b0941ee79845540d58eminfrin deferred_die = 1;
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard}
a2f9f38db0931e6edf7b71378dd680c3c5fa5841rbb
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard/* volatile just in case */
9379749d811388a7d0e3410940ddd6743a33d330jimstatic int volatile shutdown_pending;
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddardstatic int volatile restart_pending;
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddardstatic int volatile is_graceful;
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddardap_generation_t volatile ap_my_generation=0;
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddardstatic void sig_term(int sig)
1cde33c7e2019830f8fb3224e01649305583916etrawick{
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard if (shutdown_pending == 1) {
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard /* Um, is this _probably_ not an error, if the user has
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard * tried to do a shutdown twice quickly, so we won't
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard * worry about reporting it.
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard */
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard return;
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard }
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard shutdown_pending = 1;
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard}
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard
2e41eca72bcc4167d1871b0941ee79845540d58eminfrinstatic void restart(int sig)
2e41eca72bcc4167d1871b0941ee79845540d58eminfrin{
2e41eca72bcc4167d1871b0941ee79845540d58eminfrin if (restart_pending == 1) {
2e41eca72bcc4167d1871b0941ee79845540d58eminfrin /* Probably not an error - don't bother reporting it */
2e41eca72bcc4167d1871b0941ee79845540d58eminfrin return;
2e41eca72bcc4167d1871b0941ee79845540d58eminfrin }
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding restart_pending = 1;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding if ((is_graceful = (sig == SIGUSR1))) {
1cde33c7e2019830f8fb3224e01649305583916etrawick ap_kill_cleanup(pconf, NULL, cleanup_shared_mem);
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard }
2e41eca72bcc4167d1871b0941ee79845540d58eminfrin}
2e41eca72bcc4167d1871b0941ee79845540d58eminfrin
1cde33c7e2019830f8fb3224e01649305583916etrawickstatic void set_signals(void)
6bdb2c094666367615890147775bb18761216c8dminfrin{
6bdb2c094666367615890147775bb18761216c8dminfrin#ifndef NO_USE_SIGACTION
6bdb2c094666367615890147775bb18761216c8dminfrin struct sigaction sa;
6bdb2c094666367615890147775bb18761216c8dminfrin
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard sigemptyset(&sa.sa_mask);
9865751743e928ea0a9ad83faa04a738001932deminfrin sa.sa_flags = 0;
002bcf949b064d7c042465d1095cafcfc6c9b701wrowe
002bcf949b064d7c042465d1095cafcfc6c9b701wrowe if (!one_process) {
002bcf949b064d7c042465d1095cafcfc6c9b701wrowe sa.sa_handler = sig_coredump;
002bcf949b064d7c042465d1095cafcfc6c9b701wrowe#if defined(SA_ONESHOT)
002bcf949b064d7c042465d1095cafcfc6c9b701wrowe sa.sa_flags = SA_ONESHOT;
002bcf949b064d7c042465d1095cafcfc6c9b701wrowe#elif defined(SA_RESETHAND)
d75bc22ab2702fa770f6935f07107efff16a76f0wrowe sa.sa_flags = SA_RESETHAND;
2e41eca72bcc4167d1871b0941ee79845540d58eminfrin#endif
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding if (sigaction(SIGSEGV, &sa, NULL) < 0)
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGSEGV)");
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding#ifdef SIGBUS
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding if (sigaction(SIGBUS, &sa, NULL) < 0)
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGBUS)");
11c3b5180e1de6776035320b012a28bb146e7b46chuck#endif
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding#ifdef SIGABORT
9b4c60b689b8a3f2d48d19c55d857b276d405f85wrowe if (sigaction(SIGABORT, &sa, NULL) < 0)
9b4c60b689b8a3f2d48d19c55d857b276d405f85wrowe ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGABORT)");
9b4c60b689b8a3f2d48d19c55d857b276d405f85wrowe#endif
9b4c60b689b8a3f2d48d19c55d857b276d405f85wrowe#ifdef SIGABRT
9b4c60b689b8a3f2d48d19c55d857b276d405f85wrowe if (sigaction(SIGABRT, &sa, NULL) < 0)
9b4c60b689b8a3f2d48d19c55d857b276d405f85wrowe ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGABRT)");
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq#endif
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq#ifdef SIGILL
a812b025d139f465a31c76fc02ed162ed5271b03nd if (sigaction(SIGILL, &sa, NULL) < 0)
a812b025d139f465a31c76fc02ed162ed5271b03nd ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGILL)");
9b4c60b689b8a3f2d48d19c55d857b276d405f85wrowe#endif
9b4c60b689b8a3f2d48d19c55d857b276d405f85wrowe sa.sa_flags = 0;
9b4c60b689b8a3f2d48d19c55d857b276d405f85wrowe }
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe sa.sa_handler = sig_term;
5a5a6c22260854843c973e2ea9a14bec64362ab5wrowe if (sigaction(SIGTERM, &sa, NULL) < 0)
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGTERM)");
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding#ifdef SIGINT
af952917c05e56874069e1e5f64e6473bb478b68minfrin if (sigaction(SIGINT, &sa, NULL) < 0)
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGINT)");
af952917c05e56874069e1e5f64e6473bb478b68minfrin#endif
af952917c05e56874069e1e5f64e6473bb478b68minfrin#ifdef SIGXCPU
af952917c05e56874069e1e5f64e6473bb478b68minfrin sa.sa_handler = SIG_DFL;
afef080e47ef499a5cbceb7ad7fadbb3abca0b48minfrin if (sigaction(SIGXCPU, &sa, NULL) < 0)
afef080e47ef499a5cbceb7ad7fadbb3abca0b48minfrin ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGXCPU)");
35c9e4d2c0a6465746a98958ef756114834461e6minfrin#endif
35c9e4d2c0a6465746a98958ef756114834461e6minfrin#ifdef SIGXFSZ
4a7df15077ff65dbf3b2cf68fa3063273ac0a547minfrin sa.sa_handler = SIG_DFL;
dcc56911d2b95e73554ff8ced9f72fd456d73881minfrin if (sigaction(SIGXFSZ, &sa, NULL) < 0)
db8ac7cbb1fa6cdd6abcc4bb797d4deed32dd269jim ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGXFSZ)");
db8ac7cbb1fa6cdd6abcc4bb797d4deed32dd269jim#endif
db8ac7cbb1fa6cdd6abcc4bb797d4deed32dd269jim#ifdef SIGPIPE
db8ac7cbb1fa6cdd6abcc4bb797d4deed32dd269jim sa.sa_handler = SIG_IGN;
db8ac7cbb1fa6cdd6abcc4bb797d4deed32dd269jim if (sigaction(SIGPIPE, &sa, NULL) < 0)
db8ac7cbb1fa6cdd6abcc4bb797d4deed32dd269jim ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGPIPE)");
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding#endif
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* we want to ignore HUPs and USR1 while we're busy processing one */
af952917c05e56874069e1e5f64e6473bb478b68minfrin sigaddset(&sa.sa_mask, SIGHUP);
af952917c05e56874069e1e5f64e6473bb478b68minfrin sigaddset(&sa.sa_mask, SIGUSR1);
9b4c60b689b8a3f2d48d19c55d857b276d405f85wrowe sa.sa_handler = restart;
af952917c05e56874069e1e5f64e6473bb478b68minfrin if (sigaction(SIGHUP, &sa, NULL) < 0)
af952917c05e56874069e1e5f64e6473bb478b68minfrin ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGHUP)");
af952917c05e56874069e1e5f64e6473bb478b68minfrin if (sigaction(SIGUSR1, &sa, NULL) < 0)
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGUSR1)");
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe#else
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe if (!one_process) {
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe ap_signal(SIGSEGV, sig_coredump);
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq#ifdef SIGBUS
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq ap_signal(SIGBUS, sig_coredump);
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq#endif /* SIGBUS */
a812b025d139f465a31c76fc02ed162ed5271b03nd#ifdef SIGABORT
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq ap_signal(SIGABORT, sig_coredump);
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq#endif /* SIGABORT */
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe#ifdef SIGABRT
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe ap_signal(SIGABRT, sig_coredump);
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe#endif /* SIGABRT */
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe#ifdef SIGILL
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe ap_signal(SIGILL, sig_coredump);
af952917c05e56874069e1e5f64e6473bb478b68minfrin#endif /* SIGILL */
af952917c05e56874069e1e5f64e6473bb478b68minfrin#ifdef SIGXCPU
af952917c05e56874069e1e5f64e6473bb478b68minfrin ap_signal(SIGXCPU, SIG_DFL);
af952917c05e56874069e1e5f64e6473bb478b68minfrin#endif /* SIGXCPU */
af952917c05e56874069e1e5f64e6473bb478b68minfrin#ifdef SIGXFSZ
afef080e47ef499a5cbceb7ad7fadbb3abca0b48minfrin ap_signal(SIGXFSZ, SIG_DFL);
35c9e4d2c0a6465746a98958ef756114834461e6minfrin#endif /* SIGXFSZ */
dcc56911d2b95e73554ff8ced9f72fd456d73881minfrin }
fd3fa792f04fc9c4e8f5f83dceb0fc34e71f8570ianh
4224d5789080ea5586d49420da1e1996f5653bb5ianh ap_signal(SIGTERM, sig_term);
db8ac7cbb1fa6cdd6abcc4bb797d4deed32dd269jim#ifdef SIGHUP
af952917c05e56874069e1e5f64e6473bb478b68minfrin ap_signal(SIGHUP, restart);
af952917c05e56874069e1e5f64e6473bb478b68minfrin#endif /* SIGHUP */
af952917c05e56874069e1e5f64e6473bb478b68minfrin#ifdef SIGUSR1
af952917c05e56874069e1e5f64e6473bb478b68minfrin ap_signal(SIGUSR1, restart);
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe#endif /* SIGUSR1 */
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe#ifdef SIGPIPE
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe ap_signal(SIGPIPE, SIG_IGN);
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe#endif /* SIGPIPE */
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe#endif
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe}
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe/*****************************************************************
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe * Child process main loop.
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe * The following vars are static to avoid getting clobbered by longjmp();
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe * they are really private to child_main.
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe */
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowestatic int srv;
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowestatic ap_socket_t *csd;
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowestatic int requests_this_child;
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowestatic fd_set main_fds;
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwroweint ap_graceful_stop_signalled(void)
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe{
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe ap_sync_scoreboard_image();
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding if (deferred_die ||
9379749d811388a7d0e3410940ddd6743a33d330jim ap_scoreboard_image->global.running_generation != ap_my_generation) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding return 1;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding }
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding return 0;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding}
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingstatic void child_main(int child_num_arg)
3c59b18ce62f97468aaa5951d4e21a5478ef36ecminfrin{
9379749d811388a7d0e3410940ddd6743a33d330jim ap_listen_rec *lr;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_listen_rec *last_lr;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_listen_rec *first_lr;
a2f9f38db0931e6edf7b71378dd680c3c5fa5841rbb ap_pool_t *ptrans;
3c59b18ce62f97468aaa5951d4e21a5478ef36ecminfrin conn_rec *current_conn;
a2f9f38db0931e6edf7b71378dd680c3c5fa5841rbb ap_iol *iol;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_status_t stat = APR_EINIT;
3c59b18ce62f97468aaa5951d4e21a5478ef36ecminfrin int sockdes;
9379749d811388a7d0e3410940ddd6743a33d330jim
9379749d811388a7d0e3410940ddd6743a33d330jim ap_my_pid = getpid();
9379749d811388a7d0e3410940ddd6743a33d330jim csd = NULL;
9379749d811388a7d0e3410940ddd6743a33d330jim my_child_num = child_num_arg;
3c59b18ce62f97468aaa5951d4e21a5478ef36ecminfrin requests_this_child = 0;
3c59b18ce62f97468aaa5951d4e21a5478ef36ecminfrin last_lr = NULL;
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard
3c59b18ce62f97468aaa5951d4e21a5478ef36ecminfrin /* Get a sub context for global allocations in this child, so that
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * we can have cleanups occur when the child exits.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding */
9379749d811388a7d0e3410940ddd6743a33d330jim ap_create_pool(&pchild, pconf);
9379749d811388a7d0e3410940ddd6743a33d330jim
9379749d811388a7d0e3410940ddd6743a33d330jim ap_create_pool(&ptrans, pchild);
9379749d811388a7d0e3410940ddd6743a33d330jim
9379749d811388a7d0e3410940ddd6743a33d330jim /* needs to be done before we switch UIDs so we have permissions */
9379749d811388a7d0e3410940ddd6743a33d330jim reopen_scoreboard(pchild);
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard SAFE_ACCEPT(accept_mutex_child_init(pchild));
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding if (unixd_setup_child()) {
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard clean_child_exit(APEXIT_CHILDFATAL);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding }
9379749d811388a7d0e3410940ddd6743a33d330jim
9379749d811388a7d0e3410940ddd6743a33d330jim ap_child_init_hook(pchild, ap_server_conf);
9379749d811388a7d0e3410940ddd6743a33d330jim
9379749d811388a7d0e3410940ddd6743a33d330jim (void) ap_update_child_status(my_child_num, SERVER_READY, (request_rec *) NULL);
9379749d811388a7d0e3410940ddd6743a33d330jim
9379749d811388a7d0e3410940ddd6743a33d330jim ap_signal(SIGHUP, just_die);
9379749d811388a7d0e3410940ddd6743a33d330jim ap_signal(SIGTERM, just_die);
9379749d811388a7d0e3410940ddd6743a33d330jim
11c3b5180e1de6776035320b012a28bb146e7b46chuck#ifdef OS2
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding/* Stop Ctrl-C/Ctrl-Break signals going to child processes */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding {
24efed0910118b762a4eb84830875d4714b8d315ianh unsigned long ulTimes;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding DosSetSignalExceptionFocus(0, &ulTimes);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding }
066877f1a045103acfdd376d48cdd473c33f409bdougm#endif
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding while (!ap_graceful_stop_signalled()) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding BUFF *conn_io;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
9379749d811388a7d0e3410940ddd6743a33d330jim /* Prepare to receive a SIGUSR1 due to graceful restart so that
9379749d811388a7d0e3410940ddd6743a33d330jim * we can exit cleanly.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding usr1_just_die = 1;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_signal(SIGUSR1, usr1_handler);
9379749d811388a7d0e3410940ddd6743a33d330jim
9379749d811388a7d0e3410940ddd6743a33d330jim /*
9379749d811388a7d0e3410940ddd6743a33d330jim * (Re)initialize this child to a pre-connection state.
9379749d811388a7d0e3410940ddd6743a33d330jim */
9379749d811388a7d0e3410940ddd6743a33d330jim
9379749d811388a7d0e3410940ddd6743a33d330jim current_conn = NULL;
9379749d811388a7d0e3410940ddd6743a33d330jim
9379749d811388a7d0e3410940ddd6743a33d330jim ap_clear_pool(ptrans);
9379749d811388a7d0e3410940ddd6743a33d330jim
9379749d811388a7d0e3410940ddd6743a33d330jim if ((ap_max_requests_per_child > 0
9379749d811388a7d0e3410940ddd6743a33d330jim && requests_this_child++ >= ap_max_requests_per_child)) {
9379749d811388a7d0e3410940ddd6743a33d330jim clean_child_exit(0);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding }
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding (void) ap_update_child_status(my_child_num, SERVER_READY, (request_rec *) NULL);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /*
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * Wait for an acceptable connection to arrive.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding */
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe /* Lock around "accept", if necessary */
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe SAFE_ACCEPT(accept_mutex_on());
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe for (;;) {
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe if (ap_listeners->next) {
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe /* more than one socket */
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe memcpy(&main_fds, &listenfds, sizeof(fd_set));
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe srv = select(listenmaxfd + 1, &main_fds, NULL, NULL, NULL);
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe if (srv < 0 && errno != EINTR) {
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe /* Single Unix documents select as returning errnos
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe * EBADF, EINTR, and EINVAL... and in none of those
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe * cases does it make sense to continue. In fact
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe * on Linux 2.0.x we seem to end up with EFAULT
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe * occasionally, and we'd loop forever due to it.
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe */
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe ap_log_error(APLOG_MARK, APLOG_ERR, errno, ap_server_conf, "select: (listen)");
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe clean_child_exit(1);
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe }
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe if (srv <= 0)
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe continue;
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe /* we remember the last_lr we searched last time around so that
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe we don't end up starving any particular listening socket */
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe if (last_lr == NULL) {
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe lr = ap_listeners;
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe }
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe else {
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe lr = last_lr->next;
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe if (!lr)
75b0a6a06ca1f4de80e3dd2a09c9f0c7d0a56089wrowe lr = ap_listeners;
75b0a6a06ca1f4de80e3dd2a09c9f0c7d0a56089wrowe }
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe first_lr=lr;
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe do {
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe ap_get_os_sock(&sockdes, lr->sd);
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe if (FD_ISSET(sockdes, &main_fds))
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe goto got_listener;
5a5a6c22260854843c973e2ea9a14bec64362ab5wrowe lr = lr->next;
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe if (!lr)
4415d997ac73262e513c0a571bd5be4f609040bawrowe lr = ap_listeners;
4415d997ac73262e513c0a571bd5be4f609040bawrowe }
4415d997ac73262e513c0a571bd5be4f609040bawrowe while (lr != first_lr);
4415d997ac73262e513c0a571bd5be4f609040bawrowe /* FIXME: if we get here, something bad has happened, and we're
4415d997ac73262e513c0a571bd5be4f609040bawrowe probably gonna spin forever.
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe */
4415d997ac73262e513c0a571bd5be4f609040bawrowe continue;
4415d997ac73262e513c0a571bd5be4f609040bawrowe got_listener:
4415d997ac73262e513c0a571bd5be4f609040bawrowe last_lr = lr;
4415d997ac73262e513c0a571bd5be4f609040bawrowe sd = lr->sd;
4415d997ac73262e513c0a571bd5be4f609040bawrowe }
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe else {
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe /* only one socket, just pretend we did the other stuff */
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe sd = ap_listeners->sd;
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe }
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe /* if we accept() something we don't want to die, so we have to
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe * defer the exit
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe */
7bcd3f64532e7da74ad6bd4a9b1cbdf52bdee068wrowe usr1_just_die = 0;
7bcd3f64532e7da74ad6bd4a9b1cbdf52bdee068wrowe for (;;) {
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe if (deferred_die) {
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe /* we didn't get a socket, and we were told to die */
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe clean_child_exit(0);
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe }
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe stat = ap_accept(&csd, sd, ptrans);
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe if (stat == APR_SUCCESS || stat != APR_EINTR)
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe break;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding }
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding if (stat == APR_SUCCESS)
a2f9f38db0931e6edf7b71378dd680c3c5fa5841rbb break; /* We have a socket ready for reading */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding else {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding/* TODO: this accept result handling stuff should be abstracted...
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * it's already out of date between the various unix mpms
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* Our old behaviour here was to continue after accept()
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard * errors. But this leads us into lots of troubles
529005244758297d4415aa912c67a67f805349bcianh * because most of the errors are quite fatal. For
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard * example, EMFILE can be caused by slow descriptor
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard * leaks (say in a 3rd party module, or libc). It's
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard * foolish for us to continue after an EMFILE. We also
529005244758297d4415aa912c67a67f805349bcianh * seem to tickle kernel bugs on some platforms which
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard * lead to never-ending loops here. So it seems best
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard * to just exit in most cases.
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard */
529005244758297d4415aa912c67a67f805349bcianh switch (stat) {
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard#ifdef EPROTO
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard /* EPROTO on certain older kernels really means
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard * ECONNABORTED, so we need to ignore it for them.
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard * See discussion in new-httpd archives nh.9701
529005244758297d4415aa912c67a67f805349bcianh * search for EPROTO.
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard *
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * Also see nh.9603, search for EPROTO:
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * There is potentially a bug in Solaris 2.x x<6,
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq * and other boxes that implement tcp sockets in
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq * userland (i.e. on top of STREAMS). On these
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq * systems, EPROTO can actually result in a fatal
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq * loop. See PR#981 for example. It's hard to
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq * handle both uses of EPROTO.
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq */
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq case EPROTO:
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq#endif
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq#ifdef ECONNABORTED
a812b025d139f465a31c76fc02ed162ed5271b03nd case ECONNABORTED:
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq#endif
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq /* Linux generates the rest of these, other tcp
a812b025d139f465a31c76fc02ed162ed5271b03nd * stacks (i.e. bsd) tend to hide them behind
a812b025d139f465a31c76fc02ed162ed5271b03nd * getsockopt() interfaces. They occur when
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq * the net goes sour or the client disconnects
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq * after the three-way handshake has been done
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq * in the kernel but before userland has picked
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq * up the socket.
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq */
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq#ifdef ECONNRESET
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq case ECONNRESET:
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq#endif
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq#ifdef ETIMEDOUT
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq case ETIMEDOUT:
a812b025d139f465a31c76fc02ed162ed5271b03nd#endif
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq#ifdef EHOSTUNREACH
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq case EHOSTUNREACH:
a812b025d139f465a31c76fc02ed162ed5271b03nd#endif
a812b025d139f465a31c76fc02ed162ed5271b03nd#ifdef ENETUNREACH
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq case ENETUNREACH:
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding#endif
11c3b5180e1de6776035320b012a28bb146e7b46chuck break;
11c3b5180e1de6776035320b012a28bb146e7b46chuck#ifdef ENETDOWN
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding case ENETDOWN:
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /*
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * When the network layer has been shut down, there
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * is not much use in simply exiting: the parent
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * would simply re-create us (and we'd fail again).
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * Use the CHILDFATAL code to tear the server down.
a6314dfa8dd8a0d69db16288581e4950a2dd3955minfrin * @@@ Martin's idea for possible improvement:
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * A different approach would be to define
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * a new APEXIT_NETDOWN exit code, the reception
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * of which would make the parent shutdown all
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * children, then idle-loop until it detected that
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * the network is up again, and restart the children.
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard * Ben Hyde noted that temporary ENETDOWN situations
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard * occur in mobile IP.
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_log_error(APLOG_MARK, APLOG_EMERG, stat, ap_server_conf,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding "ap_accept: giving up.");
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding clean_child_exit(APEXIT_CHILDFATAL);
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard#endif /*ENETDOWN*/
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard#ifdef TPF
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard case EINACT:
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard ap_log_error(APLOG_MARK, APLOG_EMERG, stat, ap_server_conf,
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard "offload device inactive");
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard clean_child_exit(APEXIT_CHILDFATAL);
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard break;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding default:
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, ap_server_conf,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding "select/accept error (%u)", stat);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding clean_child_exit(APEXIT_CHILDFATAL);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding#else
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding default:
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_log_error(APLOG_MARK, APLOG_ERR, stat, ap_server_conf,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding "ap_accept: (client socket)");
a2f9f38db0931e6edf7b71378dd680c3c5fa5841rbb clean_child_exit(1);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding#endif
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding }
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding }
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding if (ap_graceful_stop_signalled()) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding clean_child_exit(0);
10a4cdd68ef1ca0e54af296fe1d08ac00150c90bwrowe }
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard usr1_just_die = 1;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding }
066877f1a045103acfdd376d48cdd473c33f409bdougm
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding SAFE_ACCEPT(accept_mutex_off()); /* unlock after "accept" */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* We've got a socket, let's at least process one request off the
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * socket before we accept a graceful restart request. We set
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * the signal to ignore because we don't want to disturb any
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * third party code.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_signal(SIGUSR1, SIG_IGN);
11c3b5180e1de6776035320b012a28bb146e7b46chuck /*
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * We now have a connection, so set it up with the appropriate
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * socket options, file descriptors, and read/write buffers.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_get_os_sock(&sockdes, csd);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding if (sockdes >= FD_SETSIZE) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, NULL,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding "new file descriptor %d is too large; you probably need "
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding "to rebuild Apache with a larger FD_SETSIZE "
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding "(currently %d)",
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard sockdes, FD_SETSIZE);
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard ap_close_socket(csd);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding continue;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding }
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard#ifdef TPF
11c3b5180e1de6776035320b012a28bb146e7b46chuck if (sockdes == 0) /* 0 is invalid socket for TPF */
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard continue;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding#endif
11c3b5180e1de6776035320b012a28bb146e7b46chuck
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_sock_disable_nagle(sockdes);
1cde33c7e2019830f8fb3224e01649305583916etrawick
407cde44becba3694e7c3d81ac99b5d86f4b03a9rbb iol = ap_iol_attach_socket(ptrans, csd);
1cde33c7e2019830f8fb3224e01649305583916etrawick (void) ap_update_child_status(my_child_num, SERVER_BUSY_READ,
407cde44becba3694e7c3d81ac99b5d86f4b03a9rbb (request_rec *) NULL);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
11c3b5180e1de6776035320b012a28bb146e7b46chuck conn_io = ap_bcreate(ptrans, B_RDWR);
11c3b5180e1de6776035320b012a28bb146e7b46chuck
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard ap_bpush_iol(conn_io, iol);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
1cde33c7e2019830f8fb3224e01649305583916etrawick current_conn = ap_new_apr_connection(ptrans, ap_server_conf, conn_io, csd,
407cde44becba3694e7c3d81ac99b5d86f4b03a9rbb my_child_num);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard ap_process_connection(current_conn);
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard ap_lingering_close(current_conn);
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard }
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding}
1cde33c7e2019830f8fb3224e01649305583916etrawick
407cde44becba3694e7c3d81ac99b5d86f4b03a9rbb
0f081398cf0eef8cc7c66a535d450110a92dc8aefieldingstatic int make_child(server_rec *s, int slot, time_t now)
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard{
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard int pid;
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding if (slot + 1 > ap_max_daemons_limit) {
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard ap_max_daemons_limit = slot + 1;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding }
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding if (one_process) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_signal(SIGHUP, just_die);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_signal(SIGINT, just_die);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding#ifdef SIGQUIT
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_signal(SIGQUIT, SIG_DFL);
11c3b5180e1de6776035320b012a28bb146e7b46chuck#endif
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_signal(SIGTERM, just_die);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding child_main(slot);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding }
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding (void) ap_update_child_status(slot, SERVER_STARTING, (request_rec *) NULL);
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding#ifdef _OSD_POSIX
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* BS2000 requires a "special" version of fork() before a setuid() call */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding if ((pid = os_fork(unixd_config.user_name)) == -1) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding#elif defined(TPF)
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding if ((pid = os_fork(s, slot)) == -1) {
11c3b5180e1de6776035320b012a28bb146e7b46chuck#else
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding if ((pid = fork()) == -1) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding#endif
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_log_error(APLOG_MARK, APLOG_ERR, errno, s, "fork: Unable to fork new process");
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* fork didn't succeed. Fix the scoreboard or else
af952917c05e56874069e1e5f64e6473bb478b68minfrin * it will say SERVER_STARTING forever and ever
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding (void) ap_update_child_status(slot, SERVER_DEAD, (request_rec *) NULL);
ff1234e45aca1b8171d711ecb87f58b9d9100a99ianh
4a7df15077ff65dbf3b2cf68fa3063273ac0a547minfrin /* In case system resources are maxxed out, we don't want
ff1234e45aca1b8171d711ecb87f58b9d9100a99ianh Apache running away with the CPU trying to fork over and
ff1234e45aca1b8171d711ecb87f58b9d9100a99ianh over and over again. */
ff1234e45aca1b8171d711ecb87f58b9d9100a99ianh sleep(10);
ff1234e45aca1b8171d711ecb87f58b9d9100a99ianh
4a7df15077ff65dbf3b2cf68fa3063273ac0a547minfrin return -1;
dcc56911d2b95e73554ff8ced9f72fd456d73881minfrin }
ff1234e45aca1b8171d711ecb87f58b9d9100a99ianh
ff1234e45aca1b8171d711ecb87f58b9d9100a99ianh if (!pid) {
fd3fa792f04fc9c4e8f5f83dceb0fc34e71f8570ianh#ifdef AIX_BIND_PROCESSOR
fd3fa792f04fc9c4e8f5f83dceb0fc34e71f8570ianh/* by default AIX binds to a single processor
fd3fa792f04fc9c4e8f5f83dceb0fc34e71f8570ianh * this bit unbinds children which will then bind to another cpu
fd3fa792f04fc9c4e8f5f83dceb0fc34e71f8570ianh */
fd3fa792f04fc9c4e8f5f83dceb0fc34e71f8570ianh#include <sys/processor.h>
fd3fa792f04fc9c4e8f5f83dceb0fc34e71f8570ianh int status = bindprocessor(BINDPROCESS, (int)getpid(),
fd3fa792f04fc9c4e8f5f83dceb0fc34e71f8570ianh PROCESSOR_CLASS_ANY);
fd3fa792f04fc9c4e8f5f83dceb0fc34e71f8570ianh if (status != OK) {
fd3fa792f04fc9c4e8f5f83dceb0fc34e71f8570ianh ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, ap_server_conf,
fd3fa792f04fc9c4e8f5f83dceb0fc34e71f8570ianh "processor unbind failed %d", status);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding }
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding#endif
11c3b5180e1de6776035320b012a28bb146e7b46chuck RAISE_SIGSTOP(MAKE_CHILD);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* Disable the restart signal handlers and enable the just_die stuff.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * Note that since restart() just notes that a restart has been
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * requested there's no race condition here.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_signal(SIGHUP, just_die);
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard ap_signal(SIGUSR1, just_die);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_signal(SIGTERM, just_die);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding child_main(slot);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding }
af952917c05e56874069e1e5f64e6473bb478b68minfrin
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_scoreboard_image->parent[slot].pid = pid;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding#ifdef SCOREBOARD_FILE
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding lseek(scoreboard_fd, XtOffsetOf(scoreboard, parent[slot]), 0);
afef080e47ef499a5cbceb7ad7fadbb3abca0b48minfrin force_write(scoreboard_fd, &ap_scoreboard_image->parent[slot],
afef080e47ef499a5cbceb7ad7fadbb3abca0b48minfrin sizeof(parent_score));
afef080e47ef499a5cbceb7ad7fadbb3abca0b48minfrin#endif
afef080e47ef499a5cbceb7ad7fadbb3abca0b48minfrin
afef080e47ef499a5cbceb7ad7fadbb3abca0b48minfrin return 0;
afef080e47ef499a5cbceb7ad7fadbb3abca0b48minfrin}
afef080e47ef499a5cbceb7ad7fadbb3abca0b48minfrin
10306ac2c175f420e6989568f4c8535a5dbc1349minfrin
afef080e47ef499a5cbceb7ad7fadbb3abca0b48minfrin/* start up a bunch of children */
afef080e47ef499a5cbceb7ad7fadbb3abca0b48minfrinstatic void startup_children(int number_to_start)
afef080e47ef499a5cbceb7ad7fadbb3abca0b48minfrin{
afef080e47ef499a5cbceb7ad7fadbb3abca0b48minfrin int i;
35c9e4d2c0a6465746a98958ef756114834461e6minfrin time_t now = time(0);
35c9e4d2c0a6465746a98958ef756114834461e6minfrin
35c9e4d2c0a6465746a98958ef756114834461e6minfrin for (i = 0; number_to_start && i < ap_daemons_limit; ++i) {
35c9e4d2c0a6465746a98958ef756114834461e6minfrin if (ap_scoreboard_image->servers[i].status != SERVER_DEAD) {
35c9e4d2c0a6465746a98958ef756114834461e6minfrin continue;
35c9e4d2c0a6465746a98958ef756114834461e6minfrin }
35c9e4d2c0a6465746a98958ef756114834461e6minfrin if (make_child(ap_server_conf, i, now) < 0) {
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard break;
35c9e4d2c0a6465746a98958ef756114834461e6minfrin }
35c9e4d2c0a6465746a98958ef756114834461e6minfrin --number_to_start;
35c9e4d2c0a6465746a98958ef756114834461e6minfrin }
35c9e4d2c0a6465746a98958ef756114834461e6minfrin}
35c9e4d2c0a6465746a98958ef756114834461e6minfrin
35c9e4d2c0a6465746a98958ef756114834461e6minfrin
4224d5789080ea5586d49420da1e1996f5653bb5ianh/*
4224d5789080ea5586d49420da1e1996f5653bb5ianh * idle_spawn_rate is the number of children that will be spawned on the
4224d5789080ea5586d49420da1e1996f5653bb5ianh * next maintenance cycle if there aren't enough idle servers. It is
4224d5789080ea5586d49420da1e1996f5653bb5ianh * doubled up to MAX_SPAWN_RATE, and reset only when a cycle goes by
4224d5789080ea5586d49420da1e1996f5653bb5ianh * without the need to spawn.
4224d5789080ea5586d49420da1e1996f5653bb5ianh */
4224d5789080ea5586d49420da1e1996f5653bb5ianhstatic int idle_spawn_rate = 1;
4224d5789080ea5586d49420da1e1996f5653bb5ianh#ifndef MAX_SPAWN_RATE
4224d5789080ea5586d49420da1e1996f5653bb5ianh#define MAX_SPAWN_RATE (32)
4224d5789080ea5586d49420da1e1996f5653bb5ianh#endif
4224d5789080ea5586d49420da1e1996f5653bb5ianhstatic int hold_off_on_exponential_spawning;
4224d5789080ea5586d49420da1e1996f5653bb5ianh
fa861fc5a880d2c3a5ecc0ec71fa7da556adf5c1wrowestatic void perform_idle_server_maintenance(void)
4224d5789080ea5586d49420da1e1996f5653bb5ianh{
4224d5789080ea5586d49420da1e1996f5653bb5ianh int i;
4224d5789080ea5586d49420da1e1996f5653bb5ianh int to_kill;
35c9e4d2c0a6465746a98958ef756114834461e6minfrin int idle_count;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding short_score *ss;
a2f9f38db0931e6edf7b71378dd680c3c5fa5841rbb time_t now = time(0);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding int free_length;
11c3b5180e1de6776035320b012a28bb146e7b46chuck int free_slots[MAX_SPAWN_RATE];
11c3b5180e1de6776035320b012a28bb146e7b46chuck int last_non_dead;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding int total_non_dead;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* initialize the free_list */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding free_length = 0;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding to_kill = -1;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding idle_count = 0;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding last_non_dead = -1;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding total_non_dead = 0;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard ap_sync_scoreboard_image();
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard for (i = 0; i < ap_daemons_limit; ++i) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding int status;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
af952917c05e56874069e1e5f64e6473bb478b68minfrin if (i >= ap_max_daemons_limit && free_length == idle_spawn_rate)
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding break;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ss = &ap_scoreboard_image->servers[i];
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding status = ss->status;
db8ac7cbb1fa6cdd6abcc4bb797d4deed32dd269jim if (status == SERVER_DEAD) {
db8ac7cbb1fa6cdd6abcc4bb797d4deed32dd269jim /* try to keep children numbers as low as possible */
db8ac7cbb1fa6cdd6abcc4bb797d4deed32dd269jim if (free_length < idle_spawn_rate) {
db8ac7cbb1fa6cdd6abcc4bb797d4deed32dd269jim free_slots[free_length] = i;
db8ac7cbb1fa6cdd6abcc4bb797d4deed32dd269jim ++free_length;
db8ac7cbb1fa6cdd6abcc4bb797d4deed32dd269jim }
db8ac7cbb1fa6cdd6abcc4bb797d4deed32dd269jim }
db8ac7cbb1fa6cdd6abcc4bb797d4deed32dd269jim else {
db8ac7cbb1fa6cdd6abcc4bb797d4deed32dd269jim /* We consider a starting server as idle because we started it
db8ac7cbb1fa6cdd6abcc4bb797d4deed32dd269jim * at least a cycle ago, and if it still hasn't finished starting
db8ac7cbb1fa6cdd6abcc4bb797d4deed32dd269jim * then we're just going to swamp things worse by forking more.
db8ac7cbb1fa6cdd6abcc4bb797d4deed32dd269jim * So we hopefully won't need to fork more if we count it.
db8ac7cbb1fa6cdd6abcc4bb797d4deed32dd269jim * This depends on the ordering of SERVER_READY and SERVER_STARTING.
db8ac7cbb1fa6cdd6abcc4bb797d4deed32dd269jim */
db8ac7cbb1fa6cdd6abcc4bb797d4deed32dd269jim if (status <= SERVER_READY) {
db8ac7cbb1fa6cdd6abcc4bb797d4deed32dd269jim ++ idle_count;
db8ac7cbb1fa6cdd6abcc4bb797d4deed32dd269jim /* always kill the highest numbered child if we have to...
db8ac7cbb1fa6cdd6abcc4bb797d4deed32dd269jim * no really well thought out reason ... other than observing
db8ac7cbb1fa6cdd6abcc4bb797d4deed32dd269jim * the server behaviour under linux where lower numbered children
db8ac7cbb1fa6cdd6abcc4bb797d4deed32dd269jim * tend to service more hits (and hence are more likely to have
db8ac7cbb1fa6cdd6abcc4bb797d4deed32dd269jim * their data in cpu caches).
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe */
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe to_kill = i;
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe }
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe ++total_non_dead;
5a5a6c22260854843c973e2ea9a14bec64362ab5wrowe last_non_dead = i;
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe }
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe }
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe ap_max_daemons_limit = last_non_dead + 1;
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe if (idle_count > ap_daemons_max_free) {
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe /* kill off one child... we use SIGUSR1 because that'll cause it to
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe * shut down gracefully, in case it happened to pick up a request
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe * while we were counting
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe */
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe kill(ap_scoreboard_image->parent[to_kill].pid, SIGUSR1);
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe idle_spawn_rate = 1;
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe }
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe else if (idle_count < ap_daemons_min_free) {
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe /* terminate the free list */
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe if (free_length == 0) {
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe /* only report this condition once */
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe static int reported = 0;
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe if (!reported) {
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, ap_server_conf,
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe "server reached MaxClients setting, consider"
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe " raising the MaxClients setting");
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe reported = 1;
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe }
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe idle_spawn_rate = 1;
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe }
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe else {
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe if (idle_spawn_rate >= 8) {
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0, ap_server_conf,
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe "server seems busy, (you may need "
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe "to increase StartServers, or Min/MaxSpareServers), "
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe "spawning %d children, there are %d idle, and "
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe "%d total children", idle_spawn_rate,
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe idle_count, total_non_dead);
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe }
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe for (i = 0; i < free_length; ++i) {
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe#ifdef TPF
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe if(make_child(ap_server_conf, free_slots[i], now) == -1) {
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe if(free_length == 1) {
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe shutdown_pending = 1;
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_EMERG, 0, ap_server_conf,
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe "No active child processes: shutting down");
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe }
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe }
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe#else
4c67ef499845a08771e81254ce6eb2324a160bc7wrowe make_child(ap_server_conf, free_slots[i], now);
7bcd3f64532e7da74ad6bd4a9b1cbdf52bdee068wrowe#endif /* TPF */
4c67ef499845a08771e81254ce6eb2324a160bc7wrowe }
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe /* the next time around we want to spawn twice as many if this
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe * wasn't good enough, but not if we've just done a graceful
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe */
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe if (hold_off_on_exponential_spawning) {
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe --hold_off_on_exponential_spawning;
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe }
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe else if (idle_spawn_rate < MAX_SPAWN_RATE) {
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe idle_spawn_rate *= 2;
ac0ec0b79e23806b8010b721ad7f1a89070f994awrowe }
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe }
4415d997ac73262e513c0a571bd5be4f609040bawrowe }
4415d997ac73262e513c0a571bd5be4f609040bawrowe else {
4415d997ac73262e513c0a571bd5be4f609040bawrowe idle_spawn_rate = 1;
4415d997ac73262e513c0a571bd5be4f609040bawrowe }
4415d997ac73262e513c0a571bd5be4f609040bawrowe}
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowestatic int setup_listeners(server_rec *s)
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe{
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe ap_listen_rec *lr;
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe int sockdes;
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe if (ap_listen_open(s->process, s->port)) {
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ALERT, 0, s,
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe "no listening sockets available, shutting down");
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe return -1;
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe }
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe listenmaxfd = -1;
5a5a6c22260854843c973e2ea9a14bec64362ab5wrowe FD_ZERO(&listenfds);
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe for (lr = ap_listeners; lr; lr = lr->next) {
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe ap_get_os_sock(&sockdes, lr->sd);
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe FD_SET(sockdes, &listenfds);
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe if (sockdes > listenmaxfd) {
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe listenmaxfd = sockdes;
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe }
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe }
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe return 0;
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe}
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe/* Useful to erase the status of children that might be from previous
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe * generations */
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowestatic void ap_prefork_force_reset_connection_status(long conn_id)
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe{
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe int i;
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe for (i = 0; i < STATUSES_PER_CONNECTION; i++) {
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe ap_new_scoreboard_image->table[conn_id][i].key[0] = '\0';
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe } }
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowevoid ap_reset_connection_status(long conn_id)
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe{
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe if (maintain_connection_status) {
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe ap_prefork_force_reset_connection_status(conn_id);
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe }
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe}
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe/*****************************************************************
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe * Executive routines.
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe */
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwroweint ap_mpm_run(ap_pool_t *_pconf, ap_pool_t *plog, server_rec *s)
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe{
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe int remaining_children_to_start;
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe pconf = _pconf;
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe ap_server_conf = s;
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe ap_log_pid(pconf, ap_pid_fname);
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe if (setup_listeners(s)) {
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe /* XXX: hey, what's the right way for the mpm to indicate a fatal error? */
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe return 1;
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe }
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe SAFE_ACCEPT(accept_mutex_init(pconf));
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard if (!is_graceful) {
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe reinit_scoreboard(pconf);
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe }
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe#ifdef SCOREBOARD_FILE
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe else {
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe ap_scoreboard_fname = ap_server_root_relative(pconf, ap_scoreboard_fname);
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe ap_note_cleanups_for_fd(pconf, scoreboard_fd);
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard }
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe#endif
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe set_signals();
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe if (ap_daemons_max_free < ap_daemons_min_free + 1) /* Don't thrash... */
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe ap_daemons_max_free = ap_daemons_min_free + 1;
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe /* If we're doing a graceful_restart then we're going to see a lot
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe * of children exiting immediately when we get into the main loop
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe * below (because we just sent them SIGUSR1). This happens pretty
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe * rapidly... and for each one that exits we'll start a new one until
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe * we reach at least daemons_min_free. But we may be permitted to
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe * start more than that, so we'll just keep track of how many we're
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe * supposed to start up without the 1 second penalty between each fork.
52489511342e4ff3fe399e57f29d38e5c4227bc8trawick */
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe remaining_children_to_start = ap_daemons_to_start;
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe if (remaining_children_to_start > ap_daemons_limit) {
52489511342e4ff3fe399e57f29d38e5c4227bc8trawick remaining_children_to_start = ap_daemons_limit;
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe }
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe if (!is_graceful) {
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe startup_children(remaining_children_to_start);
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe remaining_children_to_start = 0;
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard }
e6c244ee56578707b20a86e0e938498299a93b6cnd else {
e6c244ee56578707b20a86e0e938498299a93b6cnd /* give the system some time to recover before kicking into
e6c244ee56578707b20a86e0e938498299a93b6cnd * exponential mode */
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe hold_off_on_exponential_spawning = 10;
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe }
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, ap_server_conf,
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe "%s configured -- resuming normal operations",
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe ap_get_server_version());
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0, ap_server_conf,
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard "Server built: %s", ap_get_server_built());
e6c244ee56578707b20a86e0e938498299a93b6cnd restart_pending = shutdown_pending = 0;
e6c244ee56578707b20a86e0e938498299a93b6cnd
e6c244ee56578707b20a86e0e938498299a93b6cnd while (!restart_pending && !shutdown_pending) {
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe int child_slot;
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe ap_wait_t status;
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe /* this is a memory leak, but I'll fix it later. */
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe ap_proc_t pid;
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe ap_wait_or_timeout(&status, &pid, pconf);
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe /* XXX: if it takes longer than 1 second for all our children
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard * to start up and get into IDLE state then we may spawn an
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe * extra child
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe */
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe if (pid.pid != -1) {
9a806b671337b22acf6418e60a83f6bbeabdf771wrowe ap_process_child_status(&pid, status);
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe /* non-fatal death... note that it's gone in the scoreboard. */
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe ap_sync_scoreboard_image();
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe child_slot = find_child_by_pid(&pid);
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe if (child_slot >= 0) {
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard ap_prefork_force_reset_connection_status(child_slot);
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard (void) ap_update_child_status(child_slot, SERVER_DEAD,
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe (request_rec *) NULL);
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe if (remaining_children_to_start
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe && child_slot < ap_daemons_limit) {
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe /* we're still doing a 1-for-1 replacement of dead
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe * children with new children
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe */
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe make_child(ap_server_conf, child_slot, time(0));
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe --remaining_children_to_start;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding }
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding#if APR_HAS_OTHER_CHILD
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe }
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe else if (ap_reap_other_child(&pid, status) == 0) {
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe /* handled */
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe#endif
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe }
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe else if (is_graceful) {
a2f9f38db0931e6edf7b71378dd680c3c5fa5841rbb /* Great, we've probably just lost a slot in the
a2f9f38db0931e6edf7b71378dd680c3c5fa5841rbb * scoreboard. Somehow we don't know about this
9379749d811388a7d0e3410940ddd6743a33d330jim * child.
a2f9f38db0931e6edf7b71378dd680c3c5fa5841rbb */
9379749d811388a7d0e3410940ddd6743a33d330jim ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING,
9379749d811388a7d0e3410940ddd6743a33d330jim 0, ap_server_conf,
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe "long lost child came home! (pid %ld)", (long)pid.pid);
a2f9f38db0931e6edf7b71378dd680c3c5fa5841rbb }
93aa7afe1af831ee8b23aa0d97323c388e3fb8d3ianh /* Don't perform idle maintenance when a child dies,
a2f9f38db0931e6edf7b71378dd680c3c5fa5841rbb * only do it when there's a timeout. Remember only a
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq * finite number of children can die, and it's pretty
a812b025d139f465a31c76fc02ed162ed5271b03nd * pathological for a lot to die suddenly.
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq */
a812b025d139f465a31c76fc02ed162ed5271b03nd continue;
a2f9f38db0931e6edf7b71378dd680c3c5fa5841rbb }
a2f9f38db0931e6edf7b71378dd680c3c5fa5841rbb else if (remaining_children_to_start) {
a2f9f38db0931e6edf7b71378dd680c3c5fa5841rbb /* we hit a 1 second timeout in which none of the previous
a2f9f38db0931e6edf7b71378dd680c3c5fa5841rbb * generation of children needed to be reaped... so assume
afef080e47ef499a5cbceb7ad7fadbb3abca0b48minfrin * they're all done, and pick up the slack if any is left.
afef080e47ef499a5cbceb7ad7fadbb3abca0b48minfrin */
35c9e4d2c0a6465746a98958ef756114834461e6minfrin startup_children(remaining_children_to_start);
35c9e4d2c0a6465746a98958ef756114834461e6minfrin remaining_children_to_start = 0;
a2f9f38db0931e6edf7b71378dd680c3c5fa5841rbb /* In any event we really shouldn't do the code below because
a2f9f38db0931e6edf7b71378dd680c3c5fa5841rbb * few of the servers we just started are in the IDLE state
a2f9f38db0931e6edf7b71378dd680c3c5fa5841rbb * yet, so we'd mistakenly create an extra server.
a2f9f38db0931e6edf7b71378dd680c3c5fa5841rbb */
a2f9f38db0931e6edf7b71378dd680c3c5fa5841rbb continue;
a2f9f38db0931e6edf7b71378dd680c3c5fa5841rbb }
a2f9f38db0931e6edf7b71378dd680c3c5fa5841rbb
a2f9f38db0931e6edf7b71378dd680c3c5fa5841rbb perform_idle_server_maintenance();
4a7df15077ff65dbf3b2cf68fa3063273ac0a547minfrin#ifdef TPF
4ecd546edd89824908c2a9ad2e07339d89368f9cmartin shutdown_pending = os_check_server(tpf_server_name);
fd3fa792f04fc9c4e8f5f83dceb0fc34e71f8570ianh ap_check_signals();
4ecd546edd89824908c2a9ad2e07339d89368f9cmartin sleep(1);
4224d5789080ea5586d49420da1e1996f5653bb5ianh#endif /*TPF */
4224d5789080ea5586d49420da1e1996f5653bb5ianh }
4224d5789080ea5586d49420da1e1996f5653bb5ianh
db8ac7cbb1fa6cdd6abcc4bb797d4deed32dd269jim if (shutdown_pending) {
db8ac7cbb1fa6cdd6abcc4bb797d4deed32dd269jim /* Time to gracefully shut down:
5d5c9e862c3d4e7f15c12d293de4111f52404760wrowe * Kill child processes, tell them to call child_exit, etc...
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe */
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe if (unixd_killpg(getpgrp(), SIGTERM) < 0) {
d52b01101efdd3a37493d1090f20eb23c4dd1521wrowe ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "killpg SIGTERM");
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding }
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_reclaim_child_processes(1); /* Start with SIGTERM */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
1723d9ccdd3b647f5b7bae44cab9ab3eca7a4874dougm /* cleanup pid file on normal shutdown */
621bd763d2e4d32f19013ac8b76b375b5a01851fdougm {
1723d9ccdd3b647f5b7bae44cab9ab3eca7a4874dougm const char *pidfile = NULL;
de8799b6a9e8221681873ab5a81b6af6596faaafwrowe pidfile = ap_server_root_relative (pconf, ap_pid_fname);
1723d9ccdd3b647f5b7bae44cab9ab3eca7a4874dougm if ( pidfile != NULL && unlink(pidfile) == 0)
1723d9ccdd3b647f5b7bae44cab9ab3eca7a4874dougm ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO,
1723d9ccdd3b647f5b7bae44cab9ab3eca7a4874dougm 0, ap_server_conf,
1723d9ccdd3b647f5b7bae44cab9ab3eca7a4874dougm "removed PID file %s (pid=%ld)",
1723d9ccdd3b647f5b7bae44cab9ab3eca7a4874dougm pidfile, (long)getpid());
1723d9ccdd3b647f5b7bae44cab9ab3eca7a4874dougm }
1723d9ccdd3b647f5b7bae44cab9ab3eca7a4874dougm
1723d9ccdd3b647f5b7bae44cab9ab3eca7a4874dougm ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, ap_server_conf,
1723d9ccdd3b647f5b7bae44cab9ab3eca7a4874dougm "caught SIGTERM, shutting down");
1723d9ccdd3b647f5b7bae44cab9ab3eca7a4874dougm return 1;
1723d9ccdd3b647f5b7bae44cab9ab3eca7a4874dougm }
1723d9ccdd3b647f5b7bae44cab9ab3eca7a4874dougm
621bd763d2e4d32f19013ac8b76b375b5a01851fdougm /* we've been told to restart */
621bd763d2e4d32f19013ac8b76b375b5a01851fdougm ap_signal(SIGHUP, SIG_IGN);
621bd763d2e4d32f19013ac8b76b375b5a01851fdougm ap_signal(SIGUSR1, SIG_IGN);
621bd763d2e4d32f19013ac8b76b375b5a01851fdougm if (one_process) {
621bd763d2e4d32f19013ac8b76b375b5a01851fdougm /* not worth thinking about */
621bd763d2e4d32f19013ac8b76b375b5a01851fdougm return 1;
621bd763d2e4d32f19013ac8b76b375b5a01851fdougm }
621bd763d2e4d32f19013ac8b76b375b5a01851fdougm
621bd763d2e4d32f19013ac8b76b375b5a01851fdougm /* advance to the next generation */
e1d00c81dc34e2c644cc936b9dea75ec9ccfca2adougm /* XXX: we really need to make sure this new generation number isn't in
e1d00c81dc34e2c644cc936b9dea75ec9ccfca2adougm * use by any of the children.
e1d00c81dc34e2c644cc936b9dea75ec9ccfca2adougm */
e1d00c81dc34e2c644cc936b9dea75ec9ccfca2adougm ++ap_my_generation;
621bd763d2e4d32f19013ac8b76b375b5a01851fdougm ap_scoreboard_image->global.running_generation = ap_my_generation;
e1d00c81dc34e2c644cc936b9dea75ec9ccfca2adougm update_scoreboard_global();
e1d00c81dc34e2c644cc936b9dea75ec9ccfca2adougm
e1d00c81dc34e2c644cc936b9dea75ec9ccfca2adougm if (is_graceful) {
e1d00c81dc34e2c644cc936b9dea75ec9ccfca2adougm#ifndef SCOREBOARD_FILE
73e8b26287de5c06fa470d36162e103dbac9c7e5wrowe int i;
5babe00918c88eda487771fa6d6d4a1a19c0ced0chuck#endif
65aeb4185d6a108b19c27b89f311dc57dab62239nd ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, ap_server_conf,
65aeb4185d6a108b19c27b89f311dc57dab62239nd "SIGUSR1 received. Doing graceful restart");
65aeb4185d6a108b19c27b89f311dc57dab62239nd
134330b92fbc39045b7e56654f4c252fb7c53803nd /* kill off the idle ones */
65aeb4185d6a108b19c27b89f311dc57dab62239nd if (unixd_killpg(getpgrp(), SIGUSR1) < 0) {
134330b92fbc39045b7e56654f4c252fb7c53803nd ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "killpg SIGUSR1");
65aeb4185d6a108b19c27b89f311dc57dab62239nd }
fdacf528f0125e0165de42b7783b1dcbf961a189chuck#ifndef SCOREBOARD_FILE
fdacf528f0125e0165de42b7783b1dcbf961a189chuck /* This is mostly for debugging... so that we know what is still
fdacf528f0125e0165de42b7783b1dcbf961a189chuck * gracefully dealing with existing request. But we can't really
b980ad7fdc218b4855cde9f75a747527f50c554dwrowe * do it if we're in a SCOREBOARD_FILE because it'll cause
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe * corruption too easily.
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe */
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq ap_sync_scoreboard_image();
fdacf528f0125e0165de42b7783b1dcbf961a189chuck for (i = 0; i < ap_daemons_limit; ++i) {
65aeb4185d6a108b19c27b89f311dc57dab62239nd if (ap_scoreboard_image->servers[i].status != SERVER_DEAD) {
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq ap_scoreboard_image->servers[i].status = SERVER_GRACEFUL;
fdacf528f0125e0165de42b7783b1dcbf961a189chuck }
b980ad7fdc218b4855cde9f75a747527f50c554dwrowe }
e1d00c81dc34e2c644cc936b9dea75ec9ccfca2adougm#endif
e1d00c81dc34e2c644cc936b9dea75ec9ccfca2adougm }
5babe00918c88eda487771fa6d6d4a1a19c0ced0chuck else {
5babe00918c88eda487771fa6d6d4a1a19c0ced0chuck /* Kill 'em off */
3d96ee83babeec32482c9082c9426340cee8c44dwrowe if (unixd_killpg(getpgrp(), SIGHUP) < 0) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "killpg SIGHUP");
5babe00918c88eda487771fa6d6d4a1a19c0ced0chuck }
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe ap_reclaim_child_processes(0); /* Not when just starting up */
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, ap_server_conf,
11c3b5180e1de6776035320b012a28bb146e7b46chuck "SIGHUP received. Attempting to restart");
af952917c05e56874069e1e5f64e6473bb478b68minfrin }
11c3b5180e1de6776035320b012a28bb146e7b46chuck
5babe00918c88eda487771fa6d6d4a1a19c0ced0chuck if (!is_graceful) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_restart_time = time(NULL);
2e41eca72bcc4167d1871b0941ee79845540d58eminfrin }
2e41eca72bcc4167d1871b0941ee79845540d58eminfrin
2e41eca72bcc4167d1871b0941ee79845540d58eminfrin return 0;
2e41eca72bcc4167d1871b0941ee79845540d58eminfrin}
d75bc22ab2702fa770f6935f07107efff16a76f0wrowe
d75bc22ab2702fa770f6935f07107efff16a76f0wrowestatic void prefork_pre_config(ap_pool_t *p, ap_pool_t *plog, ap_pool_t *ptemp)
2e41eca72bcc4167d1871b0941ee79845540d58eminfrin{
2e41eca72bcc4167d1871b0941ee79845540d58eminfrin static int restart_num = 0;
2e41eca72bcc4167d1871b0941ee79845540d58eminfrin
2e41eca72bcc4167d1871b0941ee79845540d58eminfrin one_process = !!getenv("ONE_PROCESS");
2e41eca72bcc4167d1871b0941ee79845540d58eminfrin
2e41eca72bcc4167d1871b0941ee79845540d58eminfrin /* sigh, want this only the second time around */
2e41eca72bcc4167d1871b0941ee79845540d58eminfrin if (restart_num++ == 1) {
2e41eca72bcc4167d1871b0941ee79845540d58eminfrin is_graceful = 0;
2e41eca72bcc4167d1871b0941ee79845540d58eminfrin
2e41eca72bcc4167d1871b0941ee79845540d58eminfrin if (!one_process) {
d75bc22ab2702fa770f6935f07107efff16a76f0wrowe ap_detach();
d75bc22ab2702fa770f6935f07107efff16a76f0wrowe }
5a5a6c22260854843c973e2ea9a14bec64362ab5wrowe
d75bc22ab2702fa770f6935f07107efff16a76f0wrowe ap_my_pid = getpid();
d75bc22ab2702fa770f6935f07107efff16a76f0wrowe }
d75bc22ab2702fa770f6935f07107efff16a76f0wrowe
d75bc22ab2702fa770f6935f07107efff16a76f0wrowe unixd_pre_config();
d75bc22ab2702fa770f6935f07107efff16a76f0wrowe ap_listen_pre_config();
d75bc22ab2702fa770f6935f07107efff16a76f0wrowe ap_daemons_to_start = DEFAULT_START_DAEMON;
5a5a6c22260854843c973e2ea9a14bec64362ab5wrowe ap_daemons_min_free = DEFAULT_MIN_FREE_DAEMON;
d75bc22ab2702fa770f6935f07107efff16a76f0wrowe ap_daemons_max_free = DEFAULT_MAX_FREE_DAEMON;
d75bc22ab2702fa770f6935f07107efff16a76f0wrowe ap_daemons_limit = HARD_SERVER_LIMIT;
d75bc22ab2702fa770f6935f07107efff16a76f0wrowe ap_pid_fname = DEFAULT_PIDLOG;
67f62b7a48ff9eb8d9f31898dceaf9f89280a723dougm ap_scoreboard_fname = DEFAULT_SCOREBOARD;
67f62b7a48ff9eb8d9f31898dceaf9f89280a723dougm ap_lock_fname = DEFAULT_LOCKFILE;
67f62b7a48ff9eb8d9f31898dceaf9f89280a723dougm ap_max_requests_per_child = DEFAULT_MAX_REQUESTS_PER_CHILD;
ap_extended_status = 0;
ap_cpystrn(ap_coredump_dir, ap_server_root, sizeof(ap_coredump_dir));
}
static void prefork_hooks(void)
{
INIT_SIGLIST();
#ifdef AUX3
(void) set42sig();
#endif
/* TODO: set one_process properly */ one_process = 0;
ap_hook_pre_config(prefork_pre_config, NULL, NULL, AP_HOOK_MIDDLE);
}
static const char *set_pidfile(cmd_parms *cmd, void *dummy, const char *arg)
{
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
if (err != NULL) {
return err;
}
if (cmd->server->is_virtual) {
return "PidFile directive not allowed in <VirtualHost>";
}
ap_pid_fname = arg;
return NULL;
}
static const char *set_scoreboard(cmd_parms *cmd, void *dummy, const char *arg)
{
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
if (err != NULL) {
return err;
}
ap_scoreboard_fname = arg;
return NULL;
}
static const char *set_lockfile(cmd_parms *cmd, void *dummy, const char *arg)
{
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
if (err != NULL) {
return err;
}
ap_lock_fname = arg;
return NULL;
}
static const char *set_daemons_to_start(cmd_parms *cmd, void *dummy, const char *arg)
{
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
if (err != NULL) {
return err;
}
ap_daemons_to_start = atoi(arg);
return NULL;
}
static const char *set_min_free_servers(cmd_parms *cmd, void *dummy, const char *arg)
{
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
if (err != NULL) {
return err;
}
ap_daemons_min_free = atoi(arg);
if (ap_daemons_min_free <= 0) {
ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
"WARNING: detected MinSpareServers set to non-positive.");
ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
"Resetting to 1 to avoid almost certain Apache failure.");
ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
"Please read the documentation.");
ap_daemons_min_free = 1;
}
return NULL;
}
static const char *set_max_free_servers(cmd_parms *cmd, void *dummy, const char *arg)
{
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
if (err != NULL) {
return err;
}
ap_daemons_max_free = atoi(arg);
return NULL;
}
static const char *set_server_limit (cmd_parms *cmd, void *dummy, const char *arg)
{
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
if (err != NULL) {
return err;
}
ap_daemons_limit = atoi(arg);
if (ap_daemons_limit > HARD_SERVER_LIMIT) {
ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
"WARNING: MaxClients of %d exceeds compile time limit "
"of %d servers,", ap_daemons_limit, HARD_SERVER_LIMIT);
ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
" lowering MaxClients to %d. To increase, please "
"see the", HARD_SERVER_LIMIT);
ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
" HARD_SERVER_LIMIT define in %s.",
AP_MPM_HARD_LIMITS_FILE);
ap_daemons_limit = HARD_SERVER_LIMIT;
}
else if (ap_daemons_limit < 1) {
ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
"WARNING: Require MaxClients > 0, setting to 1");
ap_daemons_limit = 1;
}
return NULL;
}
static const char *set_max_requests(cmd_parms *cmd, void *dummy, const char *arg)
{
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
if (err != NULL) {
return err;
}
ap_max_requests_per_child = atoi(arg);
return NULL;
}
static const char *set_coredumpdir (cmd_parms *cmd, void *dummy, const char *arg)
{
ap_finfo_t finfo;
const char *fname;
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
if (err != NULL) {
return err;
}
fname = ap_server_root_relative(cmd->pool, arg);
if ((ap_stat(&finfo, fname, cmd->pool) != APR_SUCCESS) ||
(finfo.filetype != APR_DIR)) {
return ap_pstrcat(cmd->pool, "CoreDumpDirectory ", fname,
" does not exist or is not a directory", NULL);
}
ap_cpystrn(ap_coredump_dir, fname, sizeof(ap_coredump_dir));
return NULL;
}
/* Stub functions until this MPM supports the connection status API */
/* Don't mess with the string you get back from this function */
const char *ap_get_connection_status(long conn_id, const char *key)
{
int i = 0;
status_table_entry *ss;
if (!maintain_connection_status) return "";
while (i < STATUSES_PER_CONNECTION) {
ss = &(ap_new_scoreboard_image->table[conn_id][i]);
if (ss->key[0] == '\0') {
break;
}
if (0 == strcmp(ss->key, key)) {
return ss->value;
}
}
return NULL;
}
ap_array_header_t *ap_get_connections(ap_pool_t *p)
{
int i;
ap_array_header_t *connection_list;
long *array_slot;
connection_list = ap_make_array(p, 0, sizeof(long));
/* We assume that there is a connection iff it has an entry in the status
* table. Connections without any status sound problematic to me, so this
* is probably for the best. - manoj */
for (i = 0; i < ap_max_daemons_limit; i++) {
if (ap_new_scoreboard_image->table[i][0].key[0] != '\0') {
array_slot = ap_push_array(connection_list);
*array_slot = i;
}
}
return connection_list;
}
ap_array_header_t *ap_get_connection_keys(ap_pool_t *p, long conn_id)
{
int i = 0;
status_table_entry *ss;
ap_array_header_t *key_list;
char **array_slot;
key_list = ap_make_array(p, 0, KEY_LENGTH * sizeof(char));
while (i < STATUSES_PER_CONNECTION) {
ss = &(ap_new_scoreboard_image->table[conn_id][i]);
if (ss->key[0] == '\0') {
break;
}
array_slot = ap_push_array(key_list);
*array_slot = ap_pstrdup(p, ss->key);
i++;
}
return key_list;
}
/* Note: no effort is made here to prevent multiple threads from messing with
* a single connection at the same time. ap_update_connection_status should
* only be called by the thread that owns the connection */
void ap_update_connection_status(long conn_id, const char *key,
const char *value)
{
int i = 0;
status_table_entry *ss;
if (!maintain_connection_status) return;
while (i < STATUSES_PER_CONNECTION) {
ss = &(ap_new_scoreboard_image->table[conn_id][i]);
if (ss->key[0] == '\0') {
break;
}
if (0 == strcmp(ss->key, key)) {
ap_cpystrn(ss->value, value, VALUE_LENGTH);
return;
}
i++;
}
/* Not found. Add an entry for this value */
if (i >= STATUSES_PER_CONNECTION) {
/* No room. Oh well, not much anyone can do about it. */
return;
}
ap_cpystrn(ss->key, key, KEY_LENGTH);
ap_cpystrn(ss->value, value, VALUE_LENGTH);
return;
}
ap_array_header_t *ap_get_status_table(ap_pool_t *p)
{
int i, j;
ap_array_header_t *server_status;
ap_status_table_row_t *array_slot;
status_table_entry *ss;
server_status = ap_make_array(p, 0, sizeof(ap_status_table_row_t));
/* Go ahead and return what's in the connection status table even if we
* aren't maintaining it. We can at least look at what children from
* previous generations are up to. */
for (i = 0; i < ap_max_daemons_limit; i++) {
if (ap_new_scoreboard_image->table[i][0].key[0] == '\0')
continue;
array_slot = ap_push_array(server_status);
array_slot->data = ap_make_table(p, 0);
array_slot->conn_id = i;
for (j = 0; j < STATUSES_PER_CONNECTION; j++) {
ss = &(ap_new_scoreboard_image->table[i][j]);
if (ss->key[0] != '\0') {
ap_table_add(array_slot->data, ss->key, ss->value);
}
else {
break;
}
}
}
return server_status;
}
static const command_rec prefork_cmds[] = {
UNIX_DAEMON_COMMANDS
LISTEN_COMMANDS
AP_INIT_TAKE1("PidFile", set_pidfile, NULL, RSRC_CONF,
"A file for logging the server process ID"),
AP_INIT_TAKE1("ScoreBoardFile", set_scoreboard, NULL, RSRC_CONF,
"A file for Apache to maintain runtime process management information"),
AP_INIT_TAKE1("LockFile", set_lockfile, NULL, RSRC_CONF,
"The lockfile used when Apache needs to lock the accept() call"),
AP_INIT_TAKE1("StartServers", set_daemons_to_start, NULL, RSRC_CONF,
"Number of child processes launched at server startup"),
AP_INIT_TAKE1("MinSpareServers", set_min_free_servers, NULL, RSRC_CONF,
"Minimum number of idle children, to handle request spikes"),
AP_INIT_TAKE1("MaxSpareServers", set_max_free_servers, NULL, RSRC_CONF,
"Maximum number of idle children"),
AP_INIT_TAKE1("MaxClients", set_server_limit, NULL, RSRC_CONF,
"Maximum number of children alive at the same time"),
AP_INIT_TAKE1("MaxRequestsPerChild", set_max_requests, NULL, RSRC_CONF,
"Maximum number of requests a particular child serves before dying."),
AP_INIT_TAKE1("CoreDumpDirectory", set_coredumpdir, NULL, RSRC_CONF,
"The location of the directory Apache changes to before dumping core"),
{ NULL }
};
module MODULE_VAR_EXPORT mpm_prefork_module = {
MPM20_MODULE_STUFF,
NULL, /* hook to run before apache parses args */
NULL, /* create per-directory config structure */
NULL, /* merge per-directory config structures */
NULL, /* create per-server config structure */
NULL, /* merge per-server config structures */
prefork_cmds, /* command ap_table_t */
NULL, /* handlers */
prefork_hooks, /* register hooks */
};