prefork.c revision 6cfef4069051100dce381e986e8e2471f15c97d1
842ae4bd224140319ae7feec1872b93dfd491143fielding/* ====================================================================
842ae4bd224140319ae7feec1872b93dfd491143fielding * Copyright (c) 1995-2000 The Apache Software Foundation. All rights reserved.
842ae4bd224140319ae7feec1872b93dfd491143fielding * Redistribution and use in source and binary forms, with or without
842ae4bd224140319ae7feec1872b93dfd491143fielding * modification, are permitted provided that the following conditions
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * 1. Redistributions of source code must retain the above copyright
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * notice, this list of conditions and the following disclaimer.
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * 2. Redistributions in binary form must reproduce the above copyright
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * notice, this list of conditions and the following disclaimer in
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * the documentation and/or other materials provided with the
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * distribution.
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * 3. All advertising materials mentioning features or use of this
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * software must display the following acknowledgment:
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * "This product includes software developed by the Apache Software Foundation
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * for use in the Apache HTTP server project (http://www.apache.org/)."
2d728410bcf9e6e53698bb035f516e18efd76d8bnd * 4. The names "Apache Server" and "Apache Software Foundation" must not be used to
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * endorse or promote products derived from this software without
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * prior written permission. For written permission, please contact
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * apache@apache.org.
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * 5. Products derived from this software may not be called "Apache"
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * nor may "Apache" appear in their names without prior written
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * permission of the Apache Software Foundation.
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * 6. Redistributions of any form whatsoever must retain the following
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * acknowledgment:
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * "This product includes software developed by the Apache Software Foundation
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * for use in the Apache HTTP server project (http://www.apache.org/)."
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin * THIS SOFTWARE IS PROVIDED BY THE Apache Software Foundation ``AS IS'' AND ANY
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
806b50b4d37ade77f1c767a1593fac5a2d7786c8minfrin * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE Apache Software Foundation OR
c07866e582be4daac7f6a0a8754fa12fca044663fuankg * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
07ed2f9227b98d2cac21a7121ef7ea5328fa3f98fuankg * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
15ff8c621815e8337abc10638f2b2853ee6fd076minfrin * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * OF THE POSSIBILITY OF SUCH DAMAGE.
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * ====================================================================
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * This software consists of voluntary contributions made by many
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * individuals on behalf of the Apache Software Foundation and was originally based
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * on public domain software written at the National Center for
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * Supercomputing Applications, University of Illinois, Urbana-Champaign.
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * For more information on the Apache Software Foundation and the Apache HTTP server
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * project, please see <http://www.apache.org/>.
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * httpd.c: simple http daemon for answering WWW file requests
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * 03-21-93 Rob McCool wrote original code (up to NCSA HTTPd 1.3)
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * 03-06-95 blong
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * changed server number for child-alone processes to 0 and changed name
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * of processes
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * 03-10-95 blong
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * Added numerous speed hacks proposed by Robert S. Thau (rst@ai.mit.edu)
15351ab1a34130c1f880daef4e5dc15407a75969colm * including set group before fork, and call gettime before to fork
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * to set up libraries.
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * 04-14-95 rst / rh
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd * Brandon's code snarfed from NCSA 1.4, but tinkered to work with the
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * Apache server, and also to have child processes do accept() directly.
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd * April-July '95 rst
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd * Extensive rework for Apache.
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd/* TODO: this is a cobbled together prefork MPM example... it should mostly
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * TODO: behave like apache-1.3... here's a short list of things I think
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * TODO: need cleaning up still:
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd * TODO: - clean up scoreboard stuff when we figure out how to do it in 2.0
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd/* config globals */
9fe23388f983cb652b5d68e2bd92aa9f0568c574minfrin * The max child slot ever assigned, preserved across restarts. Necessary
9fe23388f983cb652b5d68e2bd92aa9f0568c574minfrin * to deal with MaxClients changes across SIGUSR1 restarts. We use this
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd * value to optimize routines that have to scan the entire scoreboard.
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz/* *Non*-shared http_main globals... */
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz/* one_process --- debugging mode variable; can be set from the command line
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * with the -X flag. If set, this gets you the child_main loop running
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * in the process which originally started up (no detach, no make_child),
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * which is a pretty nice debugging environment. (You'll get a SIGHUP
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * early in standalone_main; just continue through. This is the server
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * trying to kill off any child processes which it might have lying
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * around --- Apache doesn't keep track of their pids, it just sends
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * SIGHUP to the process group, ignoring it in the root process.
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * Continue through and you'll be fine.).
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantzstatic int one_process = 0;
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz/* used to maintain list of children which aren't part of the scoreboard */
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantzstatic ap_context_t *pconf; /* Pool for config stuff */
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantzstatic ap_context_t *pchild; /* Pool for httpd child stuff */
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantzstatic int my_pid; /* it seems silly to call getpid all the time */
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz#endif /* TPF */
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantzstatic new_scoreboard *ap_new_scoreboard_image = NULL;
9fe23388f983cb652b5d68e2bd92aa9f0568c574minfrin * change directory for gprof to plop the gmon.out file
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * configure in httpd.conf:
9fe23388f983cb652b5d68e2bd92aa9f0568c574minfrin * GprofDir logs/ -> $ServerRoot/logs/gmon.out
9fe23388f983cb652b5d68e2bd92aa9f0568c574minfrin * GprofDir logs/% -> $ServerRoot/logs/gprof.$pid/gmon.out
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantzstatic void chdir_for_gprof(void)
9fe23388f983cb652b5d68e2bd92aa9f0568c574minfrin ap_get_module_config(server_conf->module_config, &core_module);
9fe23388f983cb652b5d68e2bd92aa9f0568c574minfrin ap_snprintf(buf, sizeof(buf), "%sgprof.%d", dir, (int)getpid());
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz dir = ap_server_root_relative(pconf, buf[0] ? buf : dir);
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz ap_log_error(APLOG_MARK, APLOG_ERR, errno, server_conf,
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz/* XXX - I don't know if TPF will ever use this module or not, so leave
a51acf58d9d82f52e0ee56106cd9282030f3f3bend * the ap_check_signals calls in but disable them - manoj */
f58bb3da705eb7ec926f4883597fc2eb1336a360minfrin/* a clean exit from a child with proper cleanup */
f58bb3da705eb7ec926f4883597fc2eb1336a360minfrinstatic void clean_child_exit(int code) __attribute__ ((noreturn));
f58bb3da705eb7ec926f4883597fc2eb1336a360minfrin#if defined(USE_FCNTL_SERIALIZED_ACCEPT) || defined(USE_FLOCK_SERIALIZED_ACCEPT)
f58bb3da705eb7ec926f4883597fc2eb1336a360minfrin /* XXXX possibly bogus cast */
f58bb3da705eb7ec926f4883597fc2eb1336a360minfrin ap_server_root_relative(p, ap_lock_fname), (unsigned long)getpid());
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz /* default is 8, allocate enough for all the children plus the parent */
f58bb3da705eb7ec926f4883597fc2eb1336a360minfrin if ((old = usconfig(CONF_INITUSERS, HARD_SERVER_LIMIT + 1)) == -1) {
f58bb3da705eb7ec926f4883597fc2eb1336a360minfrin if ((old = usconfig(CONF_LOCKTYPE, US_NODEBUG)) == -1) {
f58bb3da705eb7ec926f4883597fc2eb1336a360minfrin if ((old = usconfig(CONF_ARENATYPE, US_SHAREDONLY)) == -1) {
f58bb3da705eb7ec926f4883597fc2eb1336a360minfrinstatic void accept_mutex_on(void)
f58bb3da705eb7ec926f4883597fc2eb1336a360minfrin /* got lock */
f58bb3da705eb7ec926f4883597fc2eb1336a360minfrin ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
f58bb3da705eb7ec926f4883597fc2eb1336a360minfrin "didn't get lock");
f58bb3da705eb7ec926f4883597fc2eb1336a360minfrinstatic void accept_mutex_off(void)
f58bb3da705eb7ec926f4883597fc2eb1336a360minfrin/* This code probably only works on Solaris ... but it works really fast
f58bb3da705eb7ec926f4883597fc2eb1336a360minfrin * on Solaris. Note that pthread mutexes are *NOT* released when a task
f58bb3da705eb7ec926f4883597fc2eb1336a360minfrin * dies ... the task has to free it itself. So we block signals and
f58bb3da705eb7ec926f4883597fc2eb1336a360minfrin * try to be nice about releasing the mutex.
f58bb3da705eb7ec926f4883597fc2eb1336a360minfrinstatic pthread_mutex_t *accept_mutex = (void *)(caddr_t) -1;
f58bb3da705eb7ec926f4883597fc2eb1336a360minfrin ap_register_cleanup(p, NULL, accept_mutex_child_cleanup, ap_null_cleanup);
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd && munmap((caddr_t) accept_mutex, sizeof(*accept_mutex))) {
f58bb3da705eb7ec926f4883597fc2eb1336a360minfrin accept_mutex = (pthread_mutex_t *) mmap((caddr_t) 0, sizeof(*accept_mutex),
f58bb3da705eb7ec926f4883597fc2eb1336a360minfrin if ((errno = pthread_mutex_init(accept_mutex, &mattr))) {
f58bb3da705eb7ec926f4883597fc2eb1336a360minfrin ap_register_cleanup(p, NULL, accept_mutex_cleanup, ap_null_cleanup);
f58bb3da705eb7ec926f4883597fc2eb1336a360minfrinstatic void accept_mutex_on(void)
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz if (sigprocmask(SIG_BLOCK, &accept_block_mask, &accept_previous_mask)) {
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantzstatic void accept_mutex_off(void)
5876f43a746f688a32b7201bced8591ddf19bd43minfrin /* There is a slight race condition right here... if we were to die right
5876f43a746f688a32b7201bced8591ddf19bd43minfrin * now, we'd do another pthread_mutex_unlock. Now, doing that would let
5876f43a746f688a32b7201bced8591ddf19bd43minfrin * another process into the mutex. pthread mutexes are designed to be
5876f43a746f688a32b7201bced8591ddf19bd43minfrin * fast, as such they don't have protection for things like testing if the
5876f43a746f688a32b7201bced8591ddf19bd43minfrin * thread owning a mutex is actually unlocking it (or even any way of
5876f43a746f688a32b7201bced8591ddf19bd43minfrin * testing who owns the mutex).
5876f43a746f688a32b7201bced8591ddf19bd43minfrin * If we were to unset have_accept_mutex prior to releasing the mutex
5876f43a746f688a32b7201bced8591ddf19bd43minfrin * then the race could result in the server unable to serve hits. Doing
5876f43a746f688a32b7201bced8591ddf19bd43minfrin * it this way means that the server can continue, but an additional
5876f43a746f688a32b7201bced8591ddf19bd43minfrin * child might be in the critical section ... at least it's still serving
5876f43a746f688a32b7201bced8591ddf19bd43minfrin if (sigprocmask(SIG_SETMASK, &accept_previous_mask, NULL)) {
5876f43a746f688a32b7201bced8591ddf19bd43minfrin/* it makes no sense, but this isn't defined on solaris */
5876f43a746f688a32b7201bced8591ddf19bd43minfrin/* We get a random semaphore ... the lame sysv semaphore interface
5876f43a746f688a32b7201bced8591ddf19bd43minfrin * means we have to be sure to clean this up or else we'll leak
5876f43a746f688a32b7201bced8591ddf19bd43minfrin * semaphores.
5876f43a746f688a32b7201bced8591ddf19bd43minfrin /* this is ignored anyhow */
5876f43a746f688a32b7201bced8591ddf19bd43minfrin /* acquire the semaphore */
5876f43a746f688a32b7201bced8591ddf19bd43minfrin /* restrict it to use only by the appropriate user_id ... not that this
5876f43a746f688a32b7201bced8591ddf19bd43minfrin * stops CGIs from acquiring it and dinking around with it.
5876f43a746f688a32b7201bced8591ddf19bd43minfrin ap_register_cleanup(p, NULL, accept_mutex_cleanup, ap_null_cleanup);
5876f43a746f688a32b7201bced8591ddf19bd43minfrin /* preinitialize these */
5876f43a746f688a32b7201bced8591ddf19bd43minfrinstatic void accept_mutex_on(void)
5876f43a746f688a32b7201bced8591ddf19bd43minfrinstatic void accept_mutex_off(void)
5876f43a746f688a32b7201bced8591ddf19bd43minfrin * Initialize mutex lock.
5876f43a746f688a32b7201bced8591ddf19bd43minfrin * Must be safe to call this on a restart.
5876f43a746f688a32b7201bced8591ddf19bd43minfrin lock_it.l_whence = SEEK_SET; /* from current point */
5876f43a746f688a32b7201bced8591ddf19bd43minfrin lock_it.l_type = F_WRLCK; /* set exclusive/write lock */
5876f43a746f688a32b7201bced8591ddf19bd43minfrin lock_it.l_pid = 0; /* pid not actually interesting */
5876f43a746f688a32b7201bced8591ddf19bd43minfrin unlock_it.l_whence = SEEK_SET; /* from current point */
5876f43a746f688a32b7201bced8591ddf19bd43minfrin unlock_it.l_type = F_UNLCK; /* set exclusive/write lock */
5876f43a746f688a32b7201bced8591ddf19bd43minfrin unlock_it.l_pid = 0; /* pid not actually interesting */
5876f43a746f688a32b7201bced8591ddf19bd43minfrin ap_open(&tempfile, ap_lock_fname, APR_CREATE | APR_WRITE | APR_EXCL,
5876f43a746f688a32b7201bced8591ddf19bd43minfrin ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
5876f43a746f688a32b7201bced8591ddf19bd43minfrinstatic void accept_mutex_on(void)
5876f43a746f688a32b7201bced8591ddf19bd43minfrin while ((ret = fcntl(lock_fd, F_SETLKW, &lock_it)) < 0 && errno == EINTR) {
5876f43a746f688a32b7201bced8591ddf19bd43minfrin ap_log_error(APLOG_MARK, APLOG_EMERG, errno, server_conf,
5876f43a746f688a32b7201bced8591ddf19bd43minfrin "fcntl: F_SETLKW: Error getting accept lock, exiting! "
5876f43a746f688a32b7201bced8591ddf19bd43minfrin "Perhaps you need to use the LockFile directive to place "
5876f43a746f688a32b7201bced8591ddf19bd43minfrin "your lock file on a local disk!");
5876f43a746f688a32b7201bced8591ddf19bd43minfrinstatic void accept_mutex_off(void)
5876f43a746f688a32b7201bced8591ddf19bd43minfrin while ((ret = fcntl(lock_fd, F_SETLKW, &unlock_it)) < 0 && errno == EINTR) {
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz ap_log_error(APLOG_MARK, APLOG_EMERG, errno, server_conf,
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz "fcntl: F_SETLKW: Error freeing accept lock, exiting! "
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz "Perhaps you need to use the LockFile directive to place "
f58bb3da705eb7ec926f4883597fc2eb1336a360minfrin "your lock file on a local disk!");
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * Initialize mutex lock.
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd * Done by each child at it's birth
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd ret=ap_open(&tempfile, ap_lock_fname, APR_WRITE, APR_UREAD|APR_UWRITE, p);
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz ap_log_error(APLOG_MARK, APLOG_EMERG, ret, server_conf,
f58bb3da705eb7ec926f4883597fc2eb1336a360minfrin * Initialize mutex lock.
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd * Must be safe to call this on a restart.
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd ret=ap_open(&tempfile, ap_lock_fname, APR_CREATE|APR_WRITE|APR_EXCL,
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz ap_log_error(APLOG_MARK, APLOG_EMERG, ret, server_conf,
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd ap_register_cleanup(p, NULL, accept_mutex_cleanup, ap_null_cleanup);
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9ndstatic void accept_mutex_on(void)
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd while ((ret = flock(lock_fd, LOCK_EX)) < 0 && errno == EINTR)
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd if (ret < 0) {
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd ap_log_error(APLOG_MARK, APLOG_EMERG, errno, server_conf,
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd "flock: LOCK_EX: Error getting accept lock. Exiting!");
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9ndstatic void accept_mutex_off(void)
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd ap_log_error(APLOG_MARK, APLOG_EMERG, errno, server_conf,
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd "flock: LOCK_UN: Error freeing accept lock. Exiting!");
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd * Initialize mutex lock.
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd * Done by each child at it's birth
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd if (rc != 0) {
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_EMERG, server_conf,
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd ap_register_cleanup(p, NULL, accept_mutex_cleanup, ap_null_cleanup);
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd * Initialize mutex lock.
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd * Must be safe to call this on a restart.
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd int rc = DosCreateMutexSem(NULL, &lock_sem, DC_SEM_SHARED, FALSE);
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd if (rc != 0) {
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_EMERG, server_conf,
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd ap_register_cleanup(p, NULL, accept_mutex_cleanup, ap_null_cleanup);
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9ndstatic void accept_mutex_on(void)
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd int rc = DosRequestMutexSem(lock_sem, SEM_INDEFINITE_WAIT);
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd if (rc != 0) {
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_EMERG, server_conf,
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9ndstatic void accept_mutex_off(void)
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd if (rc != 0) {
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_EMERG, server_conf,
7585f3892ce3057554a5bef740302dd479b223b2nd ap_register_cleanup(p, NULL, accept_mutex_cleanup, ap_null_cleanup);
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantzstatic void accept_mutex_on(void)
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9ndstatic void accept_mutex_off(void)
13be69a729c912bea7d0aa22596b92717df92551pquerna/* Default --- no serialization. Other methods *could* go here,
13be69a729c912bea7d0aa22596b92717df92551pquerna * as #elifs...
13be69a729c912bea7d0aa22596b92717df92551pquerna/* Multithreaded systems don't complete between processes for
13be69a729c912bea7d0aa22596b92717df92551pquerna * the sockets. */
f58bb3da705eb7ec926f4883597fc2eb1336a360minfrin/* On some architectures it's safe to do unserialized accept()s in the single
f58bb3da705eb7ec926f4883597fc2eb1336a360minfrin * Listen case. But it's never safe to do it in the case where there's
9ee5ae3a993134d40e9fb156b44b610ce261875cminfrin * multiple Listen statements. Define SINGLE_LISTEN_UNSERIALIZED_ACCEPT
13be69a729c912bea7d0aa22596b92717df92551pquerna * when it's safe in the single Listen case.
13be69a729c912bea7d0aa22596b92717df92551pquerna#define SAFE_ACCEPT(stmt) do {if (ap_listeners->next) {stmt;}} while(0)
e8f95a682820a599fe41b22977010636be5c2717jim/*****************************************************************
13be69a729c912bea7d0aa22596b92717df92551pquerna * dealing with other children
f58bb3da705eb7ec926f4883597fc2eb1336a360minfrin void (*maintenance) (int reason, void *, ap_wait_t status),
f58bb3da705eb7ec926f4883597fc2eb1336a360minfrin/* note that since this can be called by a maintenance function while we're
af91703d7657e52921bb36c44ff093b2d2077d0cminfrin * scanning the other_children list, all scanners should protect themself
af91703d7657e52921bb36c44ff093b2d2077d0cminfrin * by loading ocr->next before calling any maintenance function.
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantzAPI_EXPORT(void) ap_unregister_other_child(void *data)
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz for (pocr = &other_children; *pocr; pocr = &(*pocr)->next) {
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz (*(*pocr)->maintenance) (OC_REASON_UNREGISTER, (*pocr)->data, -1);
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz /* XXX: um, well we've just wasted some space in pconf ? */
f58bb3da705eb7ec926f4883597fc2eb1336a360minfrin/* test to ensure that the write_fds are all still writable, otherwise
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * invoke the maintenance functions as appropriate */
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantzstatic void probe_writable_fds(void)
13be69a729c912bea7d0aa22596b92717df92551pquerna rc = ap_select(fd_max + 1, NULL, &writable_fds, NULL, &tv);
f58bb3da705eb7ec926f4883597fc2eb1336a360minfrin /* XXX: uhh this could be really bad, we could have a bad file
f58bb3da705eb7ec926f4883597fc2eb1336a360minfrin * descriptor due to a bug in one of the maintenance routines */
9ee5ae3a993134d40e9fb156b44b610ce261875cminfrin (*ocr->maintenance) (OC_REASON_UNWRITABLE, ocr->data, -1);
9ee5ae3a993134d40e9fb156b44b610ce261875cminfrin/* possibly reap an other_child, return 0 if yes, -1 if not */
9ee5ae3a993134d40e9fb156b44b610ce261875cminfrinstatic int reap_other_child(int pid, ap_wait_t status)
9ee5ae3a993134d40e9fb156b44b610ce261875cminfrin (*ocr->maintenance) (OC_REASON_DEATH, ocr->data, status);
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd const char *fname;
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz fname = ap_server_root_relative(p, ap_scoreboard_fname);
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz if (ap_shm_init(&scoreboard_shm, SCOREBOARD_SIZE + NEW_SCOREBOARD_SIZE + 40, fname, p) != APR_SUCCESS) {
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd ap_snprintf(buf, sizeof(buf), "%s: could not open(create) scoreboard",
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd ap_scoreboard_image = ap_shm_malloc(scoreboard_shm, SCOREBOARD_SIZE);
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz ap_new_scoreboard_image = ap_shm_malloc(scoreboard_shm, NEW_SCOREBOARD_SIZE);
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz ap_snprintf(buf, sizeof(buf), "%s: cannot allocate scoreboard",
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz ap_register_cleanup(p, NULL, cleanup_shared_mem, ap_null_cleanup);
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz ap_scoreboard_image->global.running_generation = 0;
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz/* Called by parent process */
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd running_gen = ap_scoreboard_image->global.running_generation;
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz memset(ap_scoreboard_image, 0, SCOREBOARD_SIZE);
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz ap_scoreboard_image->global.running_generation = running_gen;
f58bb3da705eb7ec926f4883597fc2eb1336a360minfrin/* Routines called to deal with the scoreboard image
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * --- note that we do *not* need write locks, since update_child_status
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd * only updates a *single* record in place, and only one process writes to
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * a given scoreboard slot at a time (either the child process owning that
9fe23388f983cb652b5d68e2bd92aa9f0568c574minfrin * slot, or the parent, noting that the child has died).
9fe23388f983cb652b5d68e2bd92aa9f0568c574minfrin * As a final note --- setting the score entry to getpid() is always safe,
9fe23388f983cb652b5d68e2bd92aa9f0568c574minfrin * since when the parent is writing an entry, it's only noting SERVER_DEAD
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz force_read(scoreboard_fd, ap_scoreboard_image, sizeof(*ap_scoreboard_image))
9fe23388f983cb652b5d68e2bd92aa9f0568c574minfrinstatic ap_inline void put_scoreboard_info(int child_num,
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz lseek(scoreboard_fd, (long) child_num * sizeof(short_score), 0);
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz force_write(scoreboard_fd, new_score_rec, sizeof(short_score));
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantzint ap_update_child_status(int child_num, int status, request_rec *r)
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz if (status == SERVER_READY || status == SERVER_DEAD) {
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * Reset individual counters
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd ap_cpystrn(ss->client, ap_get_remote_host(c, r->per_dir_config,
f58bb3da705eb7ec926f4883597fc2eb1336a360minfrin ap_cpystrn(ss->request, "NULL", sizeof(ss->request));
51c6a215cedf19fe46a20b5cbb57f01ec4d5e8c4fuankg ap_cpystrn(ss->request, r->the_request, sizeof(ss->request));
9fe23388f983cb652b5d68e2bd92aa9f0568c574minfrin /* Don't reveal the password in the server-status view */
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz ap_cpystrn(ss->request, ap_pstrcat(r->pool, r->method, " ",
f58bb3da705eb7ec926f4883597fc2eb1336a360minfrin ap_unparse_uri_components(r->pool, &r->parsed_uri, UNP_OMITPASSWORD),
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz /* clean up the slot's vhostrec pointer (maybe re-used)
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * and mark the slot as belonging to a new generation.
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz ap_scoreboard_image->parent[child_num].generation = ap_my_generation;
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz lseek(scoreboard_fd, XtOffsetOf(scoreboard, parent[child_num]), 0);
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz force_write(scoreboard_fd, &ap_scoreboard_image->parent[child_num],
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9ndstatic void update_scoreboard_global(void)
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz (char *) &ap_scoreboard_image->global -(char *) ap_scoreboard_image, 0);
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz force_write(scoreboard_fd, &ap_scoreboard_image->global,
9fe23388f983cb652b5d68e2bd92aa9f0568c574minfrinvoid ap_time_process_request(int child_num, int status)
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz#if !defined(HAVE_GETTIMEOFDAY) && defined(HAVE_TIMES)
2c2ced9d18f0b065f620b0ead09ba25e955c3cc7sf#endif /* HAVE_TIMES */
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin if (gettimeofday(&ss->start_time, (struct timezone *) 0) < 0)
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin if (gettimeofday(&ss->stop_time, (struct timezone *) 0) < 0)
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrinstatic void increment_counts(int child_num, request_rec *r)
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin long int bs = 0;
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin short_score *ss;
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin ap_sync_scoreboard_image();
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin ss = &ap_scoreboard_image->servers[child_num];
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin if (r->sent_bodyct)
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin ap_bgetopt(r->connection->client, BO_BYTECT, &bs);
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin#ifdef HAVE_TIMES
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin times(&ss->times);
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin ss->access_count++;
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin ss->my_access_count++;
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin ss->conn_count++;
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin ss->bytes_served += (unsigned long) bs;
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin ss->my_bytes_served += (unsigned long) bs;
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin ss->conn_bytes += (unsigned long) bs;
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin put_scoreboard_info(child_num, ss);
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin for (i = 0; i < max_daemons_limit; ++i)
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin for (tries = terminate ? 4 : 1; tries <= 9; ++tries) {
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin /* don't want to hold up progress any more than
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin * necessary, but we need to allow children a few moments to exit.
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin * Set delay with an exponential backoff.
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin /* now see who is done */
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin for (i = 0; i < max_daemons_limit; ++i) {
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin /* perhaps it missed the SIGHUP, lets try again */
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING,
2c2ced9d18f0b065f620b0ead09ba25e955c3cc7sf "child process %d did not exit, sending another SIGHUP",
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin /* ok, now it's being annoying */
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING,
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin "child process %d still did not exit, sending a SIGTERM",
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin /* die child scum */
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, server_conf,
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin "child process %d still did not exit, sending a SIGKILL",
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin /* gave it our best shot, but alas... If this really
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin * is a child we are trying to kill and it really hasn't
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin * exited, we will likely fail to bind to the port
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin * after the restart.
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, server_conf,
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin "could not make child process %d exit, "
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin (*ocr->maintenance) (OC_REASON_DEATH, ocr->data, status);
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin else if (waitret == 0) {
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin (*ocr->maintenance) (OC_REASON_RESTART, ocr->data, -1);
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin /* uh what the heck? they didn't call unregister? */
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin (*ocr->maintenance) (OC_REASON_LOST, ocr->data, -1);
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin /* nothing left to wait for */
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin#endif /* ndef MULTITHREAD */
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin Systems without a real waitpid sometimes lose a child's exit while waiting
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin for another. Search through the scoreboard for missing children.
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz for (n = 0; n < max_daemons_limit; ++n) {
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz if (ap_scoreboard_image->servers[n].status != SERVER_DEAD &&
2d728410bcf9e6e53698bb035f516e18efd76d8bnd kill((pid = ap_scoreboard_image->parent[n].pid), 0) == -1) {
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz /* just mark it as having a successful exit status */
487d8b4e063696dd9698792a13c8e426635f1072nd/* Finally, this routine is used by the caretaker process to wait for
2d728410bcf9e6e53698bb035f516e18efd76d8bnd * a while...
2d728410bcf9e6e53698bb035f516e18efd76d8bnd/* number of calls to wait_or_timeout between writable probes */
2d728410bcf9e6e53698bb035f516e18efd76d8bnd if (wait_or_timeout_counter == INTERVAL_OF_WRITABLE_PROBES) {
2d728410bcf9e6e53698bb035f516e18efd76d8bnd if (ret > 0) {
f58bb3da705eb7ec926f4883597fc2eb1336a360minfrin tv.tv_usec = SCOREBOARD_MAINTENANCE_INTERVAL % 1000000;
2d728410bcf9e6e53698bb035f516e18efd76d8bnd return -1;
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin/* handle all varieties of core dumping signals */
5876f43a746f688a32b7201bced8591ddf19bd43minfrin /* At this point we've got sig blocked, because we're still inside
5876f43a746f688a32b7201bced8591ddf19bd43minfrin * the signal handler. When we leave the signal handler it will
5876f43a746f688a32b7201bced8591ddf19bd43minfrin * be unblocked, and we'll take the signal... and coredump or whatever
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin * is appropriate for this particular Unix. In addition the parent
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin * will see the real signal we received -- whereas if we called
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin * abort() here, the parent would only see SIGABRT.
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin/*****************************************************************
2d728410bcf9e6e53698bb035f516e18efd76d8bnd * Connection structures and accounting...
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantzstatic int volatile deferred_die;
4e1b035de81cbd18cfaea3604d40209bc6919bd9trawickstatic int volatile usr1_just_die;
fc1206972499ab73c4dfded43cef279d8bf01ad9minfrin/* volatile just in case */
fc1206972499ab73c4dfded43cef279d8bf01ad9minfrinstatic int volatile shutdown_pending;
5c345baea74f2eb2d74548bed271370b972499e5minfrinstatic int volatile restart_pending;
5c345baea74f2eb2d74548bed271370b972499e5minfrinstatic int volatile is_graceful;
fc1206972499ab73c4dfded43cef279d8bf01ad9minfrin /* Um, is this _probably_ not an error, if the user has
fc1206972499ab73c4dfded43cef279d8bf01ad9minfrin * tried to do a shutdown twice quickly, so we won't
fc1206972499ab73c4dfded43cef279d8bf01ad9minfrin * worry about reporting it.
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz /* Probably not an error - don't bother reporting it */
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz ap_kill_cleanup(pconf, NULL, cleanup_shared_mem);
fc1206972499ab73c4dfded43cef279d8bf01ad9minfrinstatic void set_signals(void)
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGSEGV)");
663c339c8a4663cf1977f890481f8b7e251d3221jerenkrantz ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGBUS)");
fc1206972499ab73c4dfded43cef279d8bf01ad9minfrin ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGABORT)");
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGABRT)");
2d728410bcf9e6e53698bb035f516e18efd76d8bnd ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGILL)");
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGTERM)");
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGINT)");
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGXCPU)");
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGXFSZ)");
fac37c9794a18c24d187f4e0f97a9476c4344118minfrin ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGPIPE)");
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd /* we want to ignore HUPs and USR1 while we're busy processing one */
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGHUP)");
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGUSR1)");
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz#endif /* SIGBUS */
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd#endif /* SIGABORT */
e8f95a682820a599fe41b22977010636be5c2717jim#endif /* SIGABRT */
4e1b035de81cbd18cfaea3604d40209bc6919bd9trawick#endif /* SIGILL */
663c339c8a4663cf1977f890481f8b7e251d3221jerenkrantz#endif /* SIGXCPU */
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd#endif /* SIGXFSZ */
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd#endif /* SIGHUP */
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd#endif /* SIGUSR1 */
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz#endif /* SIGPIPE */
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd#if defined(TCP_NODELAY) && !defined(MPE) && !defined(TPF)
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantzstatic void sock_disable_nagle(int s)
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz /* The Nagle algorithm says that we should delay sending partial
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * packets in hopes of getting more data. We don't want to do
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * this; we are not telnet. There are bad interactions between
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd * persistent connections and Nagle's algorithm that have very severe
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * performance penalties. (Failing to disable Nagle is not much of a
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd * problem with simple HTTP.)
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd * In spite of these problems, failure here is not a shooting offense.
487d8b4e063696dd9698792a13c8e426635f1072nd if (setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (char *) &just_say_no,
487d8b4e063696dd9698792a13c8e426635f1072nd sizeof(int)) < 0) {
487d8b4e063696dd9698792a13c8e426635f1072nd ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf,
487d8b4e063696dd9698792a13c8e426635f1072nd "setsockopt: (TCP_NODELAY)");
487d8b4e063696dd9698792a13c8e426635f1072nd/*****************************************************************
487d8b4e063696dd9698792a13c8e426635f1072nd * Child process main loop.
487d8b4e063696dd9698792a13c8e426635f1072nd * The following vars are static to avoid getting clobbered by longjmp();
487d8b4e063696dd9698792a13c8e426635f1072nd * they are really private to child_main.
f58bb3da705eb7ec926f4883597fc2eb1336a360minfrin ap_scoreboard_image->global.running_generation != ap_my_generation) {
f58bb3da705eb7ec926f4883597fc2eb1336a360minfrin/* XXX replace int with NET_SIZE_T, this is defined in ap_config.h which
f58bb3da705eb7ec926f4883597fc2eb1336a360minfrin has macros we can't make visible to this file, but it is the original
f58bb3da705eb7ec926f4883597fc2eb1336a360minfrin type for clen.
5876f43a746f688a32b7201bced8591ddf19bd43minfrin /* Get a sub context for global allocations in this child, so that
5876f43a746f688a32b7201bced8591ddf19bd43minfrin * we can have cleanups occur when the child exits.
5876f43a746f688a32b7201bced8591ddf19bd43minfrin /* needs to be done before we switch UIDs so we have permissions */
1018201f5223624476334c6e23aead02db7c4040minfrin (void) ap_update_child_status(my_child_num, SERVER_READY, (request_rec *) NULL);
fc1206972499ab73c4dfded43cef279d8bf01ad9minfrin/* Stop Ctrl-C/Ctrl-Break signals going to child processes */
5dc4220fc22561537ce1421a03e11846a5b719ebminfrin unsigned long ulTimes;
fac37c9794a18c24d187f4e0f97a9476c4344118minfrin /* Prepare to receive a SIGUSR1 due to graceful restart so that
fac37c9794a18c24d187f4e0f97a9476c4344118minfrin * we can exit cleanly.
fac37c9794a18c24d187f4e0f97a9476c4344118minfrin * (Re)initialize this child to a pre-connection state.
fac37c9794a18c24d187f4e0f97a9476c4344118minfrin && requests_this_child++ >= ap_max_requests_per_child)) {
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd (void) ap_update_child_status(my_child_num, SERVER_READY, (request_rec *) NULL);
c42b94a839cae93073d33b0d21f0ff1118d958e8poirier * Wait for an acceptable connection to arrive.
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin /* Lock around "accept", if necessary */
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin /* more than one socket */
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin srv = ap_select(listenmaxfd + 1, &main_fds, NULL, NULL, NULL);
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin /* Single Unix documents select as returning errnos
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin * EBADF, EINTR, and EINVAL... and in none of those
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin * cases does it make sense to continue. In fact
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin * on Linux 2.0.x we seem to end up with EFAULT
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin * occasionally, and we'd loop forever due to it.
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin ap_log_error(APLOG_MARK, APLOG_ERR, errno, server_conf, "select: (listen)");
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin /* we remember the last_lr we searched last time around so that
6fee4e2faa2e45fe2636d01e35d03c2cf0c9d431minfrin we don't end up starving any particular listening socket */
5876f43a746f688a32b7201bced8591ddf19bd43minfrin /* FIXME: if we get here, something bad has happened, and we're
5876f43a746f688a32b7201bced8591ddf19bd43minfrin probably gonna spin forever.
1018201f5223624476334c6e23aead02db7c4040minfrin /* only one socket, just pretend we did the other stuff */
f58bb3da705eb7ec926f4883597fc2eb1336a360minfrin /* if we accept() something we don't want to die, so we have to
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * defer the exit
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz /* we didn't get a socket, and we were told to die */
03ee592beedc99301c3c79838af79a333af47361minfrin break; /* We have a socket ready for reading */
5876f43a746f688a32b7201bced8591ddf19bd43minfrin/* TODO: this accept result handling stuff should be abstracted...
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * it's already out of date between the various unix mpms
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz /* Our old behaviour here was to continue after accept()
fc1206972499ab73c4dfded43cef279d8bf01ad9minfrin * errors. But this leads us into lots of troubles
fc1206972499ab73c4dfded43cef279d8bf01ad9minfrin * because most of the errors are quite fatal. For
fc1206972499ab73c4dfded43cef279d8bf01ad9minfrin * example, EMFILE can be caused by slow descriptor
5dc4220fc22561537ce1421a03e11846a5b719ebminfrin * leaks (say in a 3rd party module, or libc). It's
fc1206972499ab73c4dfded43cef279d8bf01ad9minfrin * foolish for us to continue after an EMFILE. We also
fc1206972499ab73c4dfded43cef279d8bf01ad9minfrin * seem to tickle kernel bugs on some platforms which
fc1206972499ab73c4dfded43cef279d8bf01ad9minfrin * lead to never-ending loops here. So it seems best
5dc4220fc22561537ce1421a03e11846a5b719ebminfrin * to just exit in most cases.
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd /* EPROTO on certain older kernels really means
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * ECONNABORTED, so we need to ignore it for them.
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * See discussion in new-httpd archives nh.9701
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * search for EPROTO.
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * Also see nh.9603, search for EPROTO:
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * There is potentially a bug in Solaris 2.x x<6,
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * and other boxes that implement tcp sockets in
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * userland (i.e. on top of STREAMS). On these
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * systems, EPROTO can actually result in a fatal
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * loop. See PR#981 for example. It's hard to
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * handle both uses of EPROTO.
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd /* Linux generates the rest of these, other tcp
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd * stacks (i.e. bsd) tend to hide them behind
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * getsockopt() interfaces. They occur when
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd * the net goes sour or the client disconnects
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd * after the three-way handshake has been done
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * in the kernel but before userland has picked
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd * up the socket.
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd * When the network layer has been shut down, there
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * is not much use in simply exiting: the parent
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd * would simply re-create us (and we'd fail again).
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd * Use the CHILDFATAL code to tear the server down.
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd * @@@ Martin's idea for possible improvement:
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd * A different approach would be to define
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * a new APEXIT_NETDOWN exit code, the reception
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * of which would make the parent shutdown all
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * children, then idle-loop until it detected that
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * the network is up again, and restart the children.
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * Ben Hyde noted that temporary ENETDOWN situations
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * occur in mobile IP.
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz ap_log_error(APLOG_MARK, APLOG_EMERG, errno, server_conf,
f58bb3da705eb7ec926f4883597fc2eb1336a360minfrin "accept: giving up.");
f58bb3da705eb7ec926f4883597fc2eb1336a360minfrin#endif /*ENETDOWN*/
a51acf58d9d82f52e0ee56106cd9282030f3f3bend ap_log_error(APLOG_MARK, APLOG_EMERG, errno, server_conf,
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz "offload device inactive");
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, server_conf,
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz "accept: (client socket)");
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz SAFE_ACCEPT(accept_mutex_off()); /* unlock after "accept" */
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd /* We've got a socket, let's at least process one request off the
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * socket before we accept a graceful restart request. We set
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd * the signal to ignore because we don't want to disturb any
03bdb4fb430b0d4e502ddfc75f7e9dbd91db72e9nd * third party code.
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * We now have a connection, so set it up with the appropriate
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz * socket options, file descriptors, and read/write buffers.
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz if (getsockname(sockdes, &sa_server, &clen) < 0) {
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz ap_log_error(APLOG_MARK, APLOG_ERR, errno, server_conf, "getsockname");
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, NULL,
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz "filedescriptor (%u) larger than FD_SETSIZE (%u) "
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz "found, you probably need to rebuild Apache with a "
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz ap_log_error(APLOG_MARK, APLOG_WARNING, errno, NULL,
9fe74ffcdea85800f04a7222f716f78ae60cce51jerenkrantz "error attaching to socket");
int pid;
if (one_process) {
#ifdef SIGQUIT
#ifdef _OSD_POSIX
if (!pid) {
#ifdef AIX_BIND_PROCESSOR
#ifdef SCOREBOARD_FILE
sizeof(parent_score));
#ifndef MAX_SPAWN_RATE
static int hold_off_on_exponential_spawning;
static void perform_idle_server_maintenance(void)
int to_kill;
int idle_count;
int free_length;
int last_non_dead;
int total_non_dead;
free_length = 0;
idle_count = 0;
total_non_dead = 0;
for (i = 0; i < ap_daemons_limit; ++i) {
int status;
++free_length;
++ idle_count;
to_kill = i;
last_non_dead = i;
if (free_length == 0) {
static int reported = 0;
if (!reported) {
"to increase StartServers, or Min/MaxSpareServers), "
for (i = 0; i < free_length; ++i) {
#ifdef TPF
pid);
case SIGTERM:
case SIGHUP:
case SIGUSR1:
case SIGKILL:
#ifdef SYS_SIGLIST
#ifdef WCOREDUMP
0, server_conf,
0, server_conf,
#ifdef WCOREDUMP
int sockdes;
for (i = 0; i < STATUSES_PER_CONNECTION; i++) {
if (maintain_connection_status) {
server_conf = s;
if (setup_listeners(s)) {
if (!is_graceful) {
#ifdef SCOREBOARD_FILE
set_signals();
if (!is_graceful) {
int child_slot;
if (pid >= 0) {
if (child_slot >= 0) {
#ifdef HAS_OTHER_CHILD
else if (is_graceful) {
0, server_conf,
else if (remaining_children_to_start) {
#ifdef TPF
if (shutdown_pending) {
0, server_conf,
if (one_process) {
if (is_graceful) {
#ifndef SCOREBOARD_FILE
#ifndef SCOREBOARD_FILE
for (i = 0; i < ap_daemons_limit; ++i) {
if (!is_graceful) {
static int restart_num = 0;
is_graceful = 0;
if (!one_process) {
unixd_detach();
ap_extended_status = 0;
static void prefork_hooks(void)
INIT_SIGLIST();
#ifdef AUX3
(void) set42sig();
return err;
return NULL;
return err;
return NULL;
return err;
return NULL;
return err;
return NULL;
return err;
if (ap_daemons_min_free <= 0) {
return NULL;
return err;
return NULL;
return err;
return NULL;
return err;
return NULL;
const char *fname;
return err;
return NULL;
while (i < STATUSES_PER_CONNECTION) {
return NULL;
long *array_slot;
for (i = 0; i < max_daemons_limit; i++) {
*array_slot = i;
return connection_list;
char **array_slot;
while (i < STATUSES_PER_CONNECTION) {
return key_list;
const char *value)
if (!maintain_connection_status) return;
while (i < STATUSES_PER_CONNECTION) {
if (i >= STATUSES_PER_CONNECTION) {
for (i = 0; i < max_daemons_limit; i++) {
for (j = 0; j < STATUSES_PER_CONNECTION; j++) {
return server_status;
{ NULL }