mpmt_pthread.c revision cb5a017cbad1e36dc501d8afc65636b8c2edf2d8
842ae4bd224140319ae7feec1872b93dfd491143fielding/* ====================================================================
842ae4bd224140319ae7feec1872b93dfd491143fielding * Copyright (c) 1995-1999 The Apache Group. All rights reserved.
842ae4bd224140319ae7feec1872b93dfd491143fielding *
842ae4bd224140319ae7feec1872b93dfd491143fielding * Redistribution and use in source and binary forms, with or without
842ae4bd224140319ae7feec1872b93dfd491143fielding * modification, are permitted provided that the following conditions
842ae4bd224140319ae7feec1872b93dfd491143fielding * are met:
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein *
71da3cca78eea6010f89b139ecadb79e6d213c4fnd * 1. Redistributions of source code must retain the above copyright
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * notice, this list of conditions and the following disclaimer.
71da3cca78eea6010f89b139ecadb79e6d213c4fnd *
71da3cca78eea6010f89b139ecadb79e6d213c4fnd * 2. Redistributions in binary form must reproduce the above copyright
71da3cca78eea6010f89b139ecadb79e6d213c4fnd * notice, this list of conditions and the following disclaimer in
71da3cca78eea6010f89b139ecadb79e6d213c4fnd * the documentation and/or other materials provided with the
71da3cca78eea6010f89b139ecadb79e6d213c4fnd * distribution.
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein *
f4c310fd2555c6faca1f980f00b161eadb089023gstein * 3. All advertising materials mentioning features or use of this
f4c310fd2555c6faca1f980f00b161eadb089023gstein * software must display the following acknowledgment:
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * "This product includes software developed by the Apache Group
f4c310fd2555c6faca1f980f00b161eadb089023gstein * for use in the Apache HTTP server project (http://www.apache.org/)."
f4c310fd2555c6faca1f980f00b161eadb089023gstein *
f4c310fd2555c6faca1f980f00b161eadb089023gstein * 4. The names "Apache Server" and "Apache Group" must not be used to
1b21d7b3d97def358b2e923655edeb16613a1c31gstein * endorse or promote products derived from this software without
952023a04a2f9d51553babd9094fb857f1c97548trawick * prior written permission. For written permission, please contact
1b21d7b3d97def358b2e923655edeb16613a1c31gstein * apache@apache.org.
1b21d7b3d97def358b2e923655edeb16613a1c31gstein *
1b21d7b3d97def358b2e923655edeb16613a1c31gstein * 5. Products derived from this software may not be called "Apache"
1b21d7b3d97def358b2e923655edeb16613a1c31gstein * nor may "Apache" appear in their names without prior written
f4c310fd2555c6faca1f980f00b161eadb089023gstein * permission of the Apache Group.
f4c310fd2555c6faca1f980f00b161eadb089023gstein *
f4c310fd2555c6faca1f980f00b161eadb089023gstein * 6. Redistributions of any form whatsoever must retain the following
f4c310fd2555c6faca1f980f00b161eadb089023gstein * acknowledgment:
f4c310fd2555c6faca1f980f00b161eadb089023gstein * "This product includes software developed by the Apache Group
f4c310fd2555c6faca1f980f00b161eadb089023gstein * for use in the Apache HTTP server project (http://www.apache.org/)."
f4c310fd2555c6faca1f980f00b161eadb089023gstein *
f4c310fd2555c6faca1f980f00b161eadb089023gstein * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
99d46a23c6eac800f327b29f8009f7d7da986230trawick * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
99d46a23c6eac800f327b29f8009f7d7da986230trawick * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
f4c310fd2555c6faca1f980f00b161eadb089023gstein * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
f4c310fd2555c6faca1f980f00b161eadb089023gstein * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
f4c310fd2555c6faca1f980f00b161eadb089023gstein * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
f4c310fd2555c6faca1f980f00b161eadb089023gstein * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
f4c310fd2555c6faca1f980f00b161eadb089023gstein * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
f4c310fd2555c6faca1f980f00b161eadb089023gstein * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
f4c310fd2555c6faca1f980f00b161eadb089023gstein * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
99d46a23c6eac800f327b29f8009f7d7da986230trawick * OF THE POSSIBILITY OF SUCH DAMAGE.
f4c310fd2555c6faca1f980f00b161eadb089023gstein * ====================================================================
f4c310fd2555c6faca1f980f00b161eadb089023gstein *
f4c310fd2555c6faca1f980f00b161eadb089023gstein * This software consists of voluntary contributions made by many
f4c310fd2555c6faca1f980f00b161eadb089023gstein * individuals on behalf of the Apache Group and was originally based
e8f95a682820a599fe41b22977010636be5c2717jim * on public domain software written at the National Center for
99d46a23c6eac800f327b29f8009f7d7da986230trawick * Supercomputing Applications, University of Illinois, Urbana-Champaign.
99d46a23c6eac800f327b29f8009f7d7da986230trawick * For more information on the Apache Group and the Apache HTTP server
5b03ba47ff7225cacb131f14b019332af27da960gstein * project, please see <http://www.apache.org/>.
5b03ba47ff7225cacb131f14b019332af27da960gstein *
5b03ba47ff7225cacb131f14b019332af27da960gstein */
99d46a23c6eac800f327b29f8009f7d7da986230trawick
5b03ba47ff7225cacb131f14b019332af27da960gstein#define CORE_PRIVATE
5b03ba47ff7225cacb131f14b019332af27da960gstein
5b03ba47ff7225cacb131f14b019332af27da960gstein#include "apr_portable.h"
5b03ba47ff7225cacb131f14b019332af27da960gstein#include "httpd.h"
5b03ba47ff7225cacb131f14b019332af27da960gstein#include "http_main.h"
5b03ba47ff7225cacb131f14b019332af27da960gstein#include "http_log.h"
5b03ba47ff7225cacb131f14b019332af27da960gstein#include "http_config.h" /* for read_config */
5b03ba47ff7225cacb131f14b019332af27da960gstein#include "http_core.h" /* for get_remote_host */
e8f95a682820a599fe41b22977010636be5c2717jim#include "http_connection.h"
e8f95a682820a599fe41b22977010636be5c2717jim#include "ap_mpm.h"
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe#include "unixd.h"
f4c310fd2555c6faca1f980f00b161eadb089023gstein#include "iol_socket.h"
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm#include "ap_listen.h"
f4c310fd2555c6faca1f980f00b161eadb089023gstein#include "scoreboard.h"
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein#include <netinet/tcp.h>
f4c310fd2555c6faca1f980f00b161eadb089023gstein#include <pthread.h>
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/*
f4c310fd2555c6faca1f980f00b161eadb089023gstein * Actual definitions of config globals
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
691db92094897494d6c31326108da20088bc175etrawickint ap_threads_per_child=0; /* Worker threads per child */
691db92094897494d6c31326108da20088bc175etrawickint ap_max_requests_per_child=0;
691db92094897494d6c31326108da20088bc175etrawickstatic char *ap_pid_fname=NULL;
691db92094897494d6c31326108da20088bc175etrawickstatic char *ap_scoreboard_fname=NULL;
691db92094897494d6c31326108da20088bc175etrawickstatic int ap_daemons_to_start=0;
691db92094897494d6c31326108da20088bc175etrawickstatic int min_spare_threads=0;
691db92094897494d6c31326108da20088bc175etrawickstatic int max_spare_threads=0;
691db92094897494d6c31326108da20088bc175etrawickstatic int ap_daemons_limit=0;
691db92094897494d6c31326108da20088bc175etrawickstatic time_t ap_restart_time=0;
691db92094897494d6c31326108da20088bc175etrawickAPI_VAR_EXPORT int ap_extended_status = 0;
691db92094897494d6c31326108da20088bc175etrawickstatic int workers_may_exit = 0;
691db92094897494d6c31326108da20088bc175etrawickstatic int requests_this_child;
691db92094897494d6c31326108da20088bc175etrawickstatic int num_listensocks = 0;
691db92094897494d6c31326108da20088bc175etrawickstatic ap_socket_t **listensocks;
691db92094897494d6c31326108da20088bc175etrawick
691db92094897494d6c31326108da20088bc175etrawick/* The structure used to pass unique initialization info to each thread */
691db92094897494d6c31326108da20088bc175etrawicktypedef struct {
691db92094897494d6c31326108da20088bc175etrawick int pid;
691db92094897494d6c31326108da20088bc175etrawick int tid;
691db92094897494d6c31326108da20088bc175etrawick int sd;
691db92094897494d6c31326108da20088bc175etrawick ap_context_t *tpool; /* "pthread" would be confusing */
691db92094897494d6c31326108da20088bc175etrawick} proc_info;
691db92094897494d6c31326108da20088bc175etrawick
691db92094897494d6c31326108da20088bc175etrawick/*
e8f95a682820a599fe41b22977010636be5c2717jim * The max child slot ever assigned, preserved across restarts. Necessary
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe * to deal with MaxClients changes across SIGWINCH restarts. We use this
f4c310fd2555c6faca1f980f00b161eadb089023gstein * value to optimize routines that have to scan the entire scoreboard.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int max_daemons_limit = -1;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic char ap_coredump_dir[MAX_STRING_LEN];
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowestatic int pipe_of_death[2];
6f15570e3adc0faf87bf55f70857028276fc9e32wrowestatic pthread_mutex_t pipe_of_death_mutex;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* *Non*-shared http_main globals... */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic server_rec *server_conf;
e8f95a682820a599fe41b22977010636be5c2717jim
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe/* one_process --- debugging mode variable; can be set from the command line
f4c310fd2555c6faca1f980f00b161eadb089023gstein * with the -X flag. If set, this gets you the child_main loop running
f4c310fd2555c6faca1f980f00b161eadb089023gstein * in the process which originally started up (no detach, no make_child),
f4c310fd2555c6faca1f980f00b161eadb089023gstein * which is a pretty nice debugging environment. (You'll get a SIGHUP
f4c310fd2555c6faca1f980f00b161eadb089023gstein * early in standalone_main; just continue through. This is the server
f4c310fd2555c6faca1f980f00b161eadb089023gstein * trying to kill off any child processes which it might have lying
f4c310fd2555c6faca1f980f00b161eadb089023gstein * around --- Apache doesn't keep track of their pids, it just sends
f4c310fd2555c6faca1f980f00b161eadb089023gstein * SIGHUP to the process group, ignoring it in the root process.
f4c310fd2555c6faca1f980f00b161eadb089023gstein * Continue through and you'll be fine.).
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowestatic int one_process = 0;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
f4c310fd2555c6faca1f980f00b161eadb089023gstein#ifdef DEBUG_SIGSTOP
6f15570e3adc0faf87bf55f70857028276fc9e32wroweint raise_sigstop_flags;
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein#ifdef HAS_OTHER_CHILD
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* used to maintain list of children which aren't part of the scoreboard */
f4c310fd2555c6faca1f980f00b161eadb089023gsteintypedef struct other_child_rec other_child_rec;
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstruct other_child_rec {
e8f95a682820a599fe41b22977010636be5c2717jim other_child_rec *next;
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe int pid;
f4c310fd2555c6faca1f980f00b161eadb089023gstein void (*maintenance) (int, void *, ap_wait_t);
f4c310fd2555c6faca1f980f00b161eadb089023gstein void *data;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int write_fd;
f4c310fd2555c6faca1f980f00b161eadb089023gstein};
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic other_child_rec *other_children;
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif
e8f95a682820a599fe41b22977010636be5c2717jim
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowestatic ap_context_t *pconf; /* Pool for config stuff */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic ap_context_t *pchild; /* Pool for httpd child stuff */
58fd79b56eb624bf011772994e9761d3c2e228c1orlikowski
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int my_pid; /* Linux getpid() doesn't work except in main thread. Use
f4c310fd2555c6faca1f980f00b161eadb089023gstein this instead */
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* Keep track of the number of worker threads currently active */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int worker_thread_count;
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic pthread_mutex_t worker_thread_count_mutex;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* Locks for accept serialization */
e8f95a682820a599fe41b22977010636be5c2717jimstatic pthread_mutex_t thread_accept_mutex = PTHREAD_MUTEX_INITIALIZER;
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowestatic ap_lock_t *process_accept_mutex;
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic char *lock_fname;
58fd79b56eb624bf011772994e9761d3c2e228c1orlikowski
f4c310fd2555c6faca1f980f00b161eadb089023gstein#ifdef NO_SERIALIZED_ACCEPT
f4c310fd2555c6faca1f980f00b161eadb089023gstein#define SAFE_ACCEPT(stmt) APR_SUCCESS
f4c310fd2555c6faca1f980f00b161eadb089023gstein#else
f4c310fd2555c6faca1f980f00b161eadb089023gstein#define SAFE_ACCEPT(stmt) (stmt)
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif
f4c310fd2555c6faca1f980f00b161eadb089023gstein
e8f95a682820a599fe41b22977010636be5c2717jim
e8f95a682820a599fe41b22977010636be5c2717jim/* Global, alas, so http_core can talk to us */
98e9c4a310bb623ff788680f88b6bd200ff36a24wroweenum server_token_type ap_server_tokens = SrvTk_FULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinAPI_EXPORT(const server_rec *) ap_get_server_conf(void)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein return (server_conf);
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinAPI_EXPORT(int) ap_get_max_daemons(void)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein return max_daemons_limit;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* a clean exit from a child with proper cleanup
f4c310fd2555c6faca1f980f00b161eadb089023gstein static void clean_child_exit(int code) __attribute__ ((noreturn)); */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinvoid clean_child_exit(int code)
0206c121a68a63559b2e843288e81bcf16093e46jerenkrantz{
0206c121a68a63559b2e843288e81bcf16093e46jerenkrantz if (pchild) {
0206c121a68a63559b2e843288e81bcf16093e46jerenkrantz ap_destroy_pool(pchild);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein exit(code);
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
91644a5f4d3e992dc208304b50e80bbb236fca89trawick
8b99f2a316c5e2fa6ab208206fdd7fc2bfc4a921dougm/*****************************************************************
f4c310fd2555c6faca1f980f00b161eadb089023gstein * dealing with other children
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein#ifdef HAS_OTHER_CHILD
8b99f2a316c5e2fa6ab208206fdd7fc2bfc4a921dougmAPI_EXPORT(void) ap_register_other_child(int pid,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe void (*maintenance) (int reason, void *, ap_wait_t status),
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe void *data, int write_fd)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe{
f4c310fd2555c6faca1f980f00b161eadb089023gstein other_child_rec *ocr;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein ocr = ap_palloc(pconf, sizeof(*ocr));
48f35e10f195dd594d75738fc536bb885eda537cgstein ocr->pid = pid;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ocr->maintenance = maintenance;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ocr->data = data;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ocr->write_fd = write_fd;
f4c310fd2555c6faca1f980f00b161eadb089023gstein ocr->next = other_children;
f4c310fd2555c6faca1f980f00b161eadb089023gstein other_children = ocr;
48f35e10f195dd594d75738fc536bb885eda537cgstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe/* note that since this can be called by a maintenance function while we're
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * scanning the other_children list, all scanners should protect themself
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * by loading ocr->next before calling any maintenance function.
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe */
6f15570e3adc0faf87bf55f70857028276fc9e32wroweAPI_EXPORT(void) ap_unregister_other_child(void *data)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein other_child_rec **pocr, *nocr;
48f35e10f195dd594d75738fc536bb885eda537cgstein
48f35e10f195dd594d75738fc536bb885eda537cgstein for (pocr = &other_children; *pocr; pocr = &(*pocr)->next) {
48f35e10f195dd594d75738fc536bb885eda537cgstein if ((*pocr)->data == data) {
48f35e10f195dd594d75738fc536bb885eda537cgstein nocr = (*pocr)->next;
48f35e10f195dd594d75738fc536bb885eda537cgstein (*(*pocr)->maintenance) (OC_REASON_UNREGISTER, (*pocr)->data, -1);
48f35e10f195dd594d75738fc536bb885eda537cgstein *pocr = nocr;
48f35e10f195dd594d75738fc536bb885eda537cgstein /* XXX: um, well we've just wasted some space in pconf ? */
48f35e10f195dd594d75738fc536bb885eda537cgstein return;
48f35e10f195dd594d75738fc536bb885eda537cgstein }
48f35e10f195dd594d75738fc536bb885eda537cgstein }
48f35e10f195dd594d75738fc536bb885eda537cgstein}
48f35e10f195dd594d75738fc536bb885eda537cgstein
48f35e10f195dd594d75738fc536bb885eda537cgstein/* test to ensure that the write_fds are all still writable, otherwise
7b6ba9c468f26bdb3492d5e8cb79628a3b04e8c8wrowe * invoke the maintenance functions as appropriate */
48f35e10f195dd594d75738fc536bb885eda537cgsteinstatic void probe_writable_fds(void)
48f35e10f195dd594d75738fc536bb885eda537cgstein{
48f35e10f195dd594d75738fc536bb885eda537cgstein return;
24efed0910118b762a4eb84830875d4714b8d315ianh#if 0
48f35e10f195dd594d75738fc536bb885eda537cgstein fd_set writable_fds;
48f35e10f195dd594d75738fc536bb885eda537cgstein int fd_max;
48f35e10f195dd594d75738fc536bb885eda537cgstein other_child_rec *ocr, *nocr;
48f35e10f195dd594d75738fc536bb885eda537cgstein struct timeval tv;
c1b808d160bfb5c849263be8d4acff600853a328trawick int rc;
77c2148c53e0a4a20a80af735caa4e0e6bd448e0gstein
77c2148c53e0a4a20a80af735caa4e0e6bd448e0gstein if (other_children == NULL)
77c2148c53e0a4a20a80af735caa4e0e6bd448e0gstein return;
77c2148c53e0a4a20a80af735caa4e0e6bd448e0gstein
77c2148c53e0a4a20a80af735caa4e0e6bd448e0gstein fd_max = 0;
48f35e10f195dd594d75738fc536bb885eda537cgstein FD_ZERO(&writable_fds);
48f35e10f195dd594d75738fc536bb885eda537cgstein do {
48f35e10f195dd594d75738fc536bb885eda537cgstein for (ocr = other_children; ocr; ocr = ocr->next) {
48f35e10f195dd594d75738fc536bb885eda537cgstein if (ocr->write_fd == -1)
48f35e10f195dd594d75738fc536bb885eda537cgstein continue;
48f35e10f195dd594d75738fc536bb885eda537cgstein FD_SET(ocr->write_fd, &writable_fds);
48f35e10f195dd594d75738fc536bb885eda537cgstein if (ocr->write_fd > fd_max) {
48f35e10f195dd594d75738fc536bb885eda537cgstein fd_max = ocr->write_fd;
48f35e10f195dd594d75738fc536bb885eda537cgstein }
48f35e10f195dd594d75738fc536bb885eda537cgstein }
48f35e10f195dd594d75738fc536bb885eda537cgstein if (fd_max == 0)
48f35e10f195dd594d75738fc536bb885eda537cgstein return;
48f35e10f195dd594d75738fc536bb885eda537cgstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein tv.tv_sec = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein tv.tv_usec = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein rc = ap_select(fd_max + 1, NULL, &writable_fds, NULL, &tv);
e8f95a682820a599fe41b22977010636be5c2717jim } while (rc == -1 && errno == EINTR);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (rc == -1) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* XXX: uhh this could be really bad, we could have a bad file
f4c310fd2555c6faca1f980f00b161eadb089023gstein * descriptor due to a bug in one of the maintenance routines */
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_unixerr("probe_writable_fds", "select",
f4c310fd2555c6faca1f980f00b161eadb089023gstein "could not probe writable fds", server_conf);
f4c310fd2555c6faca1f980f00b161eadb089023gstein return;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (rc == 0)
f4c310fd2555c6faca1f980f00b161eadb089023gstein return;
48f35e10f195dd594d75738fc536bb885eda537cgstein
48f35e10f195dd594d75738fc536bb885eda537cgstein for (ocr = other_children; ocr; ocr = nocr) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe nocr = ocr->next;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (ocr->write_fd == -1)
f4c310fd2555c6faca1f980f00b161eadb089023gstein continue;
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (FD_ISSET(ocr->write_fd, &writable_fds))
f4c310fd2555c6faca1f980f00b161eadb089023gstein continue;
f4c310fd2555c6faca1f980f00b161eadb089023gstein (*ocr->maintenance) (OC_REASON_UNWRITABLE, ocr->data, -1);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
77c2148c53e0a4a20a80af735caa4e0e6bd448e0gstein#endif
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe/* possibly reap an other_child, return 0 if yes, -1 if not */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowestatic int reap_other_child(int pid, ap_wait_t status)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe{
f4c310fd2555c6faca1f980f00b161eadb089023gstein other_child_rec *ocr, *nocr;
77c2148c53e0a4a20a80af735caa4e0e6bd448e0gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein for (ocr = other_children; ocr; ocr = nocr) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein nocr = ocr->next;
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (ocr->pid != pid)
f4c310fd2555c6faca1f980f00b161eadb089023gstein continue;
f4c310fd2555c6faca1f980f00b161eadb089023gstein ocr->pid = -1;
8b99f2a316c5e2fa6ab208206fdd7fc2bfc4a921dougm (*ocr->maintenance) (OC_REASON_DEATH, ocr->data, status);
f4c310fd2555c6faca1f980f00b161eadb089023gstein return 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein return -1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f958dac1550254a59b45f4655138bb34dad5e76egsteinstatic void reclaim_child_processes(int terminate)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein int i, status;
f4c310fd2555c6faca1f980f00b161eadb089023gstein long int waittime = 1024 * 16; /* in usecs */
f4c310fd2555c6faca1f980f00b161eadb089023gstein struct timeval tv;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int waitret, tries;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int not_dead_yet;
f4c310fd2555c6faca1f980f00b161eadb089023gstein#ifdef HAS_OTHER_CHILD
f4c310fd2555c6faca1f980f00b161eadb089023gstein other_child_rec *ocr, *nocr;
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif
f4c310fd2555c6faca1f980f00b161eadb089023gstein
0206c121a68a63559b2e843288e81bcf16093e46jerenkrantz ap_sync_scoreboard_image();
0206c121a68a63559b2e843288e81bcf16093e46jerenkrantz
f4c310fd2555c6faca1f980f00b161eadb089023gstein for (tries = terminate ? 4 : 1; tries <= 9; ++tries) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* don't want to hold up progress any more than
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * necessary, but we need to allow children a few moments to exit.
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * Set delay with an exponential backoff.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein tv.tv_sec = waittime / 1000000;
f4c310fd2555c6faca1f980f00b161eadb089023gstein tv.tv_usec = waittime % 1000000;
e8f95a682820a599fe41b22977010636be5c2717jim waittime = waittime * 4;
0206c121a68a63559b2e843288e81bcf16093e46jerenkrantz ap_select(0, NULL, NULL, NULL, &tv);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe /* now see who is done */
f4c310fd2555c6faca1f980f00b161eadb089023gstein not_dead_yet = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein for (i = 0; i < max_daemons_limit; ++i) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe int pid = ap_scoreboard_image->parent[i].pid;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (pid == my_pid || pid == 0)
f4c310fd2555c6faca1f980f00b161eadb089023gstein continue;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f39230a531b23d94f86a087963299bbe2e431a4agstein waitret = waitpid(pid, &status, WNOHANG);
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe if (waitret == pid || waitret == -1) {
f39230a531b23d94f86a087963299bbe2e431a4agstein ap_scoreboard_image->parent[i].pid = 0;
f39230a531b23d94f86a087963299bbe2e431a4agstein continue;
f39230a531b23d94f86a087963299bbe2e431a4agstein }
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe ++not_dead_yet;
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe switch (tries) {
f39230a531b23d94f86a087963299bbe2e431a4agstein case 1: /* 16ms */
f39230a531b23d94f86a087963299bbe2e431a4agstein case 2: /* 82ms */
f39230a531b23d94f86a087963299bbe2e431a4agstein break;
1e2133fe37e6cbcd683233057ef62236bc8e5826trawick case 3: /* 344ms */
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein case 4: /* 16ms */
f39230a531b23d94f86a087963299bbe2e431a4agstein case 5: /* 82ms */
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein case 6: /* 344ms */
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein case 7: /* 1.4sec */
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein /* ok, now it's being annoying */
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING,
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein 0, server_conf,
f39230a531b23d94f86a087963299bbe2e431a4agstein "child process %d still did not exit, sending a SIGTERM",
f39230a531b23d94f86a087963299bbe2e431a4agstein pid);
f39230a531b23d94f86a087963299bbe2e431a4agstein kill(pid, SIGTERM);
f39230a531b23d94f86a087963299bbe2e431a4agstein break;
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein case 8: /* 6 sec */
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein /* die child scum */
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, server_conf,
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein "child process %d still did not exit, sending a SIGKILL",
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein pid);
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein kill(pid, SIGKILL);
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein break;
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein case 9: /* 14 sec */
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein /* gave it our best shot, but alas... If this really
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein * is a child we are trying to kill and it really hasn't
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein * exited, we will likely fail to bind to the port
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein * after the restart.
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein */
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, server_conf,
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein "could not make child process %d exit, "
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein "attempting to continue anyway", pid);
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein break;
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein }
f39230a531b23d94f86a087963299bbe2e431a4agstein }
f39230a531b23d94f86a087963299bbe2e431a4agstein#ifdef HAS_OTHER_CHILD
f39230a531b23d94f86a087963299bbe2e431a4agstein for (ocr = other_children; ocr; ocr = nocr) {
f39230a531b23d94f86a087963299bbe2e431a4agstein nocr = ocr->next;
f39230a531b23d94f86a087963299bbe2e431a4agstein if (ocr->pid == -1)
f39230a531b23d94f86a087963299bbe2e431a4agstein continue;
f39230a531b23d94f86a087963299bbe2e431a4agstein
f39230a531b23d94f86a087963299bbe2e431a4agstein waitret = waitpid(ocr->pid, &status, WNOHANG);
f39230a531b23d94f86a087963299bbe2e431a4agstein if (waitret == ocr->pid) {
f39230a531b23d94f86a087963299bbe2e431a4agstein ocr->pid = -1;
f39230a531b23d94f86a087963299bbe2e431a4agstein (*ocr->maintenance) (OC_REASON_DEATH, ocr->data, status);
f39230a531b23d94f86a087963299bbe2e431a4agstein }
f39230a531b23d94f86a087963299bbe2e431a4agstein else if (waitret == 0) {
f39230a531b23d94f86a087963299bbe2e431a4agstein (*ocr->maintenance) (OC_REASON_RESTART, ocr->data, -1);
f39230a531b23d94f86a087963299bbe2e431a4agstein ++not_dead_yet;
f39230a531b23d94f86a087963299bbe2e431a4agstein }
f39230a531b23d94f86a087963299bbe2e431a4agstein else if (waitret == -1) {
f39230a531b23d94f86a087963299bbe2e431a4agstein /* uh what the heck? they didn't call unregister? */
f39230a531b23d94f86a087963299bbe2e431a4agstein ocr->pid = -1;
f39230a531b23d94f86a087963299bbe2e431a4agstein (*ocr->maintenance) (OC_REASON_LOST, ocr->data, -1);
f39230a531b23d94f86a087963299bbe2e431a4agstein }
f39230a531b23d94f86a087963299bbe2e431a4agstein }
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein#endif
f39230a531b23d94f86a087963299bbe2e431a4agstein if (!not_dead_yet) {
f39230a531b23d94f86a087963299bbe2e431a4agstein /* nothing left to wait for */
f39230a531b23d94f86a087963299bbe2e431a4agstein break;
f39230a531b23d94f86a087963299bbe2e431a4agstein }
f39230a531b23d94f86a087963299bbe2e431a4agstein }
f39230a531b23d94f86a087963299bbe2e431a4agstein}
f39230a531b23d94f86a087963299bbe2e431a4agstein
f39230a531b23d94f86a087963299bbe2e431a4agstein/* Finally, this routine is used by the caretaker process to wait for
f39230a531b23d94f86a087963299bbe2e431a4agstein * a while...
f39230a531b23d94f86a087963299bbe2e431a4agstein */
f39230a531b23d94f86a087963299bbe2e431a4agstein
f39230a531b23d94f86a087963299bbe2e431a4agstein/* number of calls to wait_or_timeout between writable probes */
f39230a531b23d94f86a087963299bbe2e431a4agstein#ifndef INTERVAL_OF_WRITABLE_PROBES
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein#define INTERVAL_OF_WRITABLE_PROBES 10
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein#endif
b5989e567e4fac5b3ab1252024ae19b0a54893a7gsteinstatic int wait_or_timeout_counter;
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein
6810bf1570bed88d16239b27ce47d48408bb2e51gsteinstatic int wait_or_timeout(ap_wait_t *status)
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein{
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein struct timeval tv;
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein int ret;
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein ++wait_or_timeout_counter;
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein if (wait_or_timeout_counter == INTERVAL_OF_WRITABLE_PROBES) {
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein wait_or_timeout_counter = 0;
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein#ifdef HAS_OTHER_CHILD
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein probe_writable_fds();
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein#endif
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein }
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein ret = waitpid(-1, status, WNOHANG);
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein if (ret == -1 && errno == EINTR) {
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein return -1;
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein }
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein if (ret > 0) {
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein return ret;
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein }
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein tv.tv_sec = SCOREBOARD_MAINTENANCE_INTERVAL / 1000000;
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein tv.tv_usec = SCOREBOARD_MAINTENANCE_INTERVAL % 1000000;
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein ap_select(0, NULL, NULL, NULL, &tv);
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein return -1;
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein}
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein/* handle all varieties of core dumping signals */
b5989e567e4fac5b3ab1252024ae19b0a54893a7gsteinstatic void sig_coredump(int sig)
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein{
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein chdir(ap_coredump_dir);
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein signal(sig, SIG_DFL);
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein kill(my_pid, sig);
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein /* At this point we've got sig blocked, because we're still inside
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein * the signal handler. When we leave the signal handler it will
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein * be unblocked, and we'll take the signal... and coredump or whatever
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein * is appropriate for this particular Unix. In addition the parent
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein * will see the real signal we received -- whereas if we called
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein * abort() here, the parent would only see SIGABRT.
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein */
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein}
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein
b5989e567e4fac5b3ab1252024ae19b0a54893a7gsteinstatic void just_die(int sig)
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein{
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein clean_child_exit(0);
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein}
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein/*****************************************************************
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein * Connection structures and accounting...
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein */
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein/* volatile just in case */
b5989e567e4fac5b3ab1252024ae19b0a54893a7gsteinstatic int volatile shutdown_pending;
b5989e567e4fac5b3ab1252024ae19b0a54893a7gsteinstatic int volatile restart_pending;
b5989e567e4fac5b3ab1252024ae19b0a54893a7gsteinstatic int volatile is_graceful;
b5989e567e4fac5b3ab1252024ae19b0a54893a7gsteinap_generation_t volatile ap_my_generation;
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein/*
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein * ap_start_shutdown() and ap_start_restart(), below, are a first stab at
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein * functions to initiate shutdown or restart without relying on signals.
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe * Previously this was initiated in sig_term() and restart() signal handlers,
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein * but we want to be able to start a shutdown/restart from other sources --
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein * e.g. on Win32, from the service manager. Now the service manager can
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein * call ap_start_shutdown() or ap_start_restart() as appropiate. Note that
f4c310fd2555c6faca1f980f00b161eadb089023gstein * these functions can also be called by the child processes, since global
f4c310fd2555c6faca1f980f00b161eadb089023gstein * variables are no longer used to pass on the required action to the parent.
f4c310fd2555c6faca1f980f00b161eadb089023gstein *
f4c310fd2555c6faca1f980f00b161eadb089023gstein * These should only be called from the parent process itself, since the
f4c310fd2555c6faca1f980f00b161eadb089023gstein * parent process will use the shutdown_pending and restart_pending variables
f4c310fd2555c6faca1f980f00b161eadb089023gstein * to determine whether to shutdown or restart. The child process should
f4c310fd2555c6faca1f980f00b161eadb089023gstein * call signal_parent() directly to tell the parent to die -- this will
f4c310fd2555c6faca1f980f00b161eadb089023gstein * cause neither of those variable to be set, which the parent will
f4c310fd2555c6faca1f980f00b161eadb089023gstein * assume means something serious is wrong (which it will be, for the
f4c310fd2555c6faca1f980f00b161eadb089023gstein * child to force an exit) and so do an exit anyway.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinvoid ap_start_shutdown(void)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
0206c121a68a63559b2e843288e81bcf16093e46jerenkrantz if (shutdown_pending == 1) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Um, is this _probably_ not an error, if the user has
f4c310fd2555c6faca1f980f00b161eadb089023gstein * tried to do a shutdown twice quickly, so we won't
f4c310fd2555c6faca1f980f00b161eadb089023gstein * worry about reporting it.
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm */
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm return;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein shutdown_pending = 1;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* do a graceful restart if graceful == 1 */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinvoid ap_start_restart(int graceful)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (restart_pending == 1) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* Probably not an error - don't bother reporting it */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe restart_pending = 1;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe is_graceful = graceful;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe}
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowestatic void sig_term(int sig)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe{
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_start_shutdown();
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe}
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowestatic void restart(int sig)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein#ifndef WIN32
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_start_restart(sig == SIGWINCH);
f4c310fd2555c6faca1f980f00b161eadb089023gstein#else
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_start_restart(1);
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic void set_signals(void)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein#ifndef NO_USE_SIGACTION
f4c310fd2555c6faca1f980f00b161eadb089023gstein struct sigaction sa;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm sigemptyset(&sa.sa_mask);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe sa.sa_flags = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!one_process) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein sa.sa_handler = sig_coredump;
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm#if defined(SA_ONESHOT)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe sa.sa_flags = SA_ONESHOT;
f4c310fd2555c6faca1f980f00b161eadb089023gstein#elif defined(SA_RESETHAND)
f4c310fd2555c6faca1f980f00b161eadb089023gstein sa.sa_flags = SA_RESETHAND;
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (sigaction(SIGSEGV, &sa, NULL) < 0)
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGSEGV)");
f4c310fd2555c6faca1f980f00b161eadb089023gstein#ifdef SIGBUS
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (sigaction(SIGBUS, &sa, NULL) < 0)
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGBUS)");
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif
f4c310fd2555c6faca1f980f00b161eadb089023gstein#ifdef SIGABORT
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm if (sigaction(SIGABORT, &sa, NULL) < 0)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGABORT)");
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe#endif
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe#ifdef SIGABRT
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (sigaction(SIGABRT, &sa, NULL) < 0)
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGABRT)");
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm#ifdef SIGILL
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (sigaction(SIGILL, &sa, NULL) < 0)
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGILL)");
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif
e8f95a682820a599fe41b22977010636be5c2717jim sa.sa_flags = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe sa.sa_handler = sig_term;
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (sigaction(SIGTERM, &sa, NULL) < 0)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGTERM)");
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe#ifdef SIGINT
42f2b4b0e9b84dfd8acbb9c0da18a07c664e30a1jorton if (sigaction(SIGINT, &sa, NULL) < 0)
42f2b4b0e9b84dfd8acbb9c0da18a07c664e30a1jorton ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGINT)");
42f2b4b0e9b84dfd8acbb9c0da18a07c664e30a1jorton#endif
5a8f3bcf803321e69b226d3b98314305a68a586cjerenkrantz#ifdef SIGXCPU
42f2b4b0e9b84dfd8acbb9c0da18a07c664e30a1jorton sa.sa_handler = SIG_DFL;
5a8f3bcf803321e69b226d3b98314305a68a586cjerenkrantz if (sigaction(SIGXCPU, &sa, NULL) < 0)
5a8f3bcf803321e69b226d3b98314305a68a586cjerenkrantz ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGXCPU)");
5a8f3bcf803321e69b226d3b98314305a68a586cjerenkrantz#endif
5a8f3bcf803321e69b226d3b98314305a68a586cjerenkrantz#ifdef SIGXFSZ
5a8f3bcf803321e69b226d3b98314305a68a586cjerenkrantz sa.sa_handler = SIG_DFL;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (sigaction(SIGXFSZ, &sa, NULL) < 0)
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGXFSZ)");
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe#ifdef SIGPIPE
f4c310fd2555c6faca1f980f00b161eadb089023gstein sa.sa_handler = SIG_IGN;
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (sigaction(SIGPIPE, &sa, NULL) < 0)
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGPIPE)");
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* we want to ignore HUPs and WINCH while we're busy processing one */
f4c310fd2555c6faca1f980f00b161eadb089023gstein sigaddset(&sa.sa_mask, SIGHUP);
f4c310fd2555c6faca1f980f00b161eadb089023gstein sigaddset(&sa.sa_mask, SIGWINCH);
f4c310fd2555c6faca1f980f00b161eadb089023gstein sa.sa_handler = restart;
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (sigaction(SIGHUP, &sa, NULL) < 0)
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGHUP)");
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (sigaction(SIGWINCH, &sa, NULL) < 0)
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGWINCH)");
f4c310fd2555c6faca1f980f00b161eadb089023gstein#else
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!one_process) {
e8f95a682820a599fe41b22977010636be5c2717jim signal(SIGSEGV, sig_coredump);
f4c310fd2555c6faca1f980f00b161eadb089023gstein#ifdef SIGBUS
f4c310fd2555c6faca1f980f00b161eadb089023gstein signal(SIGBUS, sig_coredump);
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif /* SIGBUS */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe#ifdef SIGABORT
f4c310fd2555c6faca1f980f00b161eadb089023gstein signal(SIGABORT, sig_coredump);
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif /* SIGABORT */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe#ifdef SIGABRT
f4c310fd2555c6faca1f980f00b161eadb089023gstein signal(SIGABRT, sig_coredump);
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif /* SIGABRT */
f4c310fd2555c6faca1f980f00b161eadb089023gstein#ifdef SIGILL
f4c310fd2555c6faca1f980f00b161eadb089023gstein signal(SIGILL, sig_coredump);
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif /* SIGILL */
f4c310fd2555c6faca1f980f00b161eadb089023gstein#ifdef SIGXCPU
f4c310fd2555c6faca1f980f00b161eadb089023gstein signal(SIGXCPU, SIG_DFL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif /* SIGXCPU */
f4c310fd2555c6faca1f980f00b161eadb089023gstein#ifdef SIGXFSZ
f4c310fd2555c6faca1f980f00b161eadb089023gstein signal(SIGXFSZ, SIG_DFL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif /* SIGXFSZ */
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein signal(SIGTERM, sig_term);
f4c310fd2555c6faca1f980f00b161eadb089023gstein#ifdef SIGHUP
f4c310fd2555c6faca1f980f00b161eadb089023gstein signal(SIGHUP, restart);
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif /* SIGHUP */
f4c310fd2555c6faca1f980f00b161eadb089023gstein#ifdef SIGWINCH
f4c310fd2555c6faca1f980f00b161eadb089023gstein signal(SIGWINCH, restart);
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif /* SIGWINCH */
f4c310fd2555c6faca1f980f00b161eadb089023gstein#ifdef SIGPIPE
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe signal(SIGPIPE, SIG_IGN);
58fd79b56eb624bf011772994e9761d3c2e228c1orlikowski#endif /* SIGPIPE */
99d46a23c6eac800f327b29f8009f7d7da986230trawick
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif
8b99f2a316c5e2fa6ab208206fdd7fc2bfc4a921dougm}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic void process_child_status(int pid, ap_wait_t status)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
e8f95a682820a599fe41b22977010636be5c2717jim /* Child died... if it died due to a fatal error,
f4c310fd2555c6faca1f980f00b161eadb089023gstein * we should simply bail out.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm if ((WIFEXITED(status)) &&
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe WEXITSTATUS(status) == APEXIT_CHILDFATAL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_ALERT|APLOG_NOERRNO, 0, server_conf,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Child %d returned a Fatal error... \n"
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "Apache is exiting!",
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe pid);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe exit(APEXIT_CHILDFATAL);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (WIFSIGNALED(status)) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe switch (WTERMSIG(status)) {
99d46a23c6eac800f327b29f8009f7d7da986230trawick case SIGTERM:
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe case SIGHUP:
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe case SIGUSR1:
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe case SIGKILL:
e8f95a682820a599fe41b22977010636be5c2717jim break;
f4c310fd2555c6faca1f980f00b161eadb089023gstein default:
f4c310fd2555c6faca1f980f00b161eadb089023gstein#ifdef SYS_SIGLIST
f8033d657a57eab45af44368774d8beb3e4f7f35pquerna#ifdef WCOREDUMP
f8033d657a57eab45af44368774d8beb3e4f7f35pquerna if (WCOREDUMP(status)) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE,
99d46a23c6eac800f327b29f8009f7d7da986230trawick 0, server_conf,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "child pid %d exit signal %s (%d), "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "possible coredump in %s",
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe pid, (WTERMSIG(status) >= NumSIG) ? "" :
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe SYS_SIGLIST[WTERMSIG(status)], WTERMSIG(status),
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_coredump_dir);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe else {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe#endif
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe 0, server_conf,
1aac1c71105133d669960501bdf2274e63561054minfrin "child pid %d exit signal %s (%d)", pid,
1aac1c71105133d669960501bdf2274e63561054minfrin SYS_SIGLIST[WTERMSIG(status)], WTERMSIG(status));
1aac1c71105133d669960501bdf2274e63561054minfrin#ifdef WCOREDUMP
1aac1c71105133d669960501bdf2274e63561054minfrin }
1aac1c71105133d669960501bdf2274e63561054minfrin#endif
1aac1c71105133d669960501bdf2274e63561054minfrin#else
1aac1c71105133d669960501bdf2274e63561054minfrin ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe server_conf,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "child pid %d exit signal %d",
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe pid, WTERMSIG(status));
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe#endif
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe}
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowestatic int setup_listeners(server_rec *s)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe{
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_listen_rec *lr;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe int num_listeners = 0;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (ap_listen_open(s->process, s->port)) {
99d46a23c6eac800f327b29f8009f7d7da986230trawick return 0;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe for (lr = ap_listeners; lr; lr = lr->next) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe num_listeners++;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return num_listeners;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe}
99d46a23c6eac800f327b29f8009f7d7da986230trawick
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe/*****************************************************************
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * Here follows a long bunch of generic server bookkeeping stuff...
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe#if defined(TCP_NODELAY) && !defined(MPE) && !defined(TPF)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowestatic void sock_disable_nagle(int s)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe{
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* The Nagle algorithm says that we should delay sending partial
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * packets in hopes of getting more data. We don't want to do
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * this; we are not telnet. There are bad interactions between
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * persistent connections and Nagle's algorithm that have very severe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * performance penalties. (Failing to disable Nagle is not much of a
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * problem with simple HTTP.)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe *
99d46a23c6eac800f327b29f8009f7d7da986230trawick * In spite of these problems, failure here is not a shooting offense.
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe int just_say_no = 1;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (char *) &just_say_no,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe sizeof(int)) < 0) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "setsockopt: (TCP_NODELAY)");
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe}
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe#else
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe#define sock_disable_nagle(s) /* NOOP */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe#endif
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
99d46a23c6eac800f327b29f8009f7d7da986230trawickint ap_graceful_stop_signalled(void)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe{
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* XXX - Does this really work? - Manoj */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return is_graceful;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe}
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe/*****************************************************************
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * Child process main loop.
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowestatic void process_socket(ap_context_t *p, ap_socket_t *sock, int my_child_num, int my_thread_num)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe{
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe BUFF *conn_io;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe conn_rec *current_conn;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_iol *iol;
99d46a23c6eac800f327b29f8009f7d7da986230trawick long conn_id = my_child_num * HARD_THREAD_LIMIT + my_thread_num;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe int csd;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe (void) ap_get_os_sock(&csd, sock);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe sock_disable_nagle(csd);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe iol = unix_attach_socket(sock);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (iol == NULL) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (errno == EBADF) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, NULL,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "filedescriptor (%u) larger than FD_SETSIZE (%u) "
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "found, you probably need to rebuild Apache with a "
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "larger FD_SETSIZE", csd, FD_SETSIZE);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe else {
99d46a23c6eac800f327b29f8009f7d7da986230trawick ap_log_error(APLOG_MARK, APLOG_WARNING, errno, NULL,
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm "error attaching to socket");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_close_socket(sock);
f4c310fd2555c6faca1f980f00b161eadb089023gstein return;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe (void) ap_update_child_status(my_child_num, my_thread_num,
f4c310fd2555c6faca1f980f00b161eadb089023gstein SERVER_BUSY_READ, (request_rec *) NULL);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe conn_io = ap_bcreate(p, B_RDWR);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_bpush_iol(conn_io, iol);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
f4c310fd2555c6faca1f980f00b161eadb089023gstein current_conn = ap_new_apr_connection(p, server_conf, conn_io, sock,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe conn_id);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_process_connection(current_conn);
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe/* Sets workers_may_exit if we received a character on the pipe_of_death */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowestatic void check_pipe_of_death(void)
99d46a23c6eac800f327b29f8009f7d7da986230trawick{
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm pthread_mutex_lock(&pipe_of_death_mutex);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!workers_may_exit) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_status_t ret;
f4c310fd2555c6faca1f980f00b161eadb089023gstein char pipe_read_char;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int n=1;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
f4c310fd2555c6faca1f980f00b161eadb089023gstein ret = ap_recv(listensocks[0], &pipe_read_char, &n);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (ret == APR_EAGAIN) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* It lost the lottery. It must continue to suffer
f4c310fd2555c6faca1f980f00b161eadb089023gstein * through a life of servitude. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* It won the lottery (or something else is very
f4c310fd2555c6faca1f980f00b161eadb089023gstein * wrong). Embrace death with open arms. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein workers_may_exit = 1;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
f4c310fd2555c6faca1f980f00b161eadb089023gstein pthread_mutex_unlock(&pipe_of_death_mutex);
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowestatic void * worker_thread(void * dummy)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe{
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe proc_info * ti = dummy;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe int process_slot = ti->pid;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe int thread_slot = ti->tid;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_context_t *tpool = ti->tpool;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_socket_t *csd = NULL;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_context_t *ptrans; /* Pool for per-transaction stuff */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_socket_t *sd = NULL;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe int n;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe int curr_pollfd, last_pollfd = 0;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_pollfd_t *pollset;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_status_t rv;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe free(ti);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_create_context(&ptrans, tpool);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe pthread_mutex_lock(&worker_thread_count_mutex);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe worker_thread_count++;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe pthread_mutex_unlock(&worker_thread_count_mutex);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_setup_poll(&pollset, num_listensocks+1, tpool);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe for(n=0 ; n <= num_listensocks ; ++n)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_add_poll_socket(pollset, listensocks[n], APR_POLLIN);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* TODO: Switch to a system where threads reuse the results from earlier
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe poll calls - manoj */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe while (!workers_may_exit) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe workers_may_exit |= (ap_max_requests_per_child != 0) && (requests_this_child <= 0);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (workers_may_exit) break;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein (void) ap_update_child_status(process_slot, thread_slot, SERVER_READY,
f4c310fd2555c6faca1f980f00b161eadb089023gstein (request_rec *) NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein pthread_mutex_lock(&thread_accept_mutex);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (workers_may_exit) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein pthread_mutex_unlock(&thread_accept_mutex);
f4c310fd2555c6faca1f980f00b161eadb089023gstein break;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm if ((rv = SAFE_ACCEPT(ap_lock(process_accept_mutex)))
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe != APR_SUCCESS) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_log_error(APLOG_MARK, APLOG_EMERG, rv, server_conf,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "ap_lock failed. Attempting to shutdown "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "process gracefully.");
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe workers_may_exit = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein while (!workers_may_exit) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_status_t ret;
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_int16_t event;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein ret = ap_poll(pollset, &n, -1);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (ret != APR_SUCCESS) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (ret == APR_EINTR) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein continue;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* poll() will only return errors in catastrophic
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe * circumstances. Let's try exiting gracefully, for now. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_ERR, errno, (const server_rec *)
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_get_server_conf(), "poll: (listen)");
f4c310fd2555c6faca1f980f00b161eadb089023gstein workers_may_exit = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (workers_may_exit) break;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_get_revents(&event, listensocks[0], pollset);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (event & APR_POLLIN) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* A process got a signal on the shutdown pipe. Check if we're
f4c310fd2555c6faca1f980f00b161eadb089023gstein * the lucky process to die. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein check_pipe_of_death();
f4c310fd2555c6faca1f980f00b161eadb089023gstein continue;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (num_listensocks == 1) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein sd = ap_listeners->sd;
f4c310fd2555c6faca1f980f00b161eadb089023gstein goto got_fd;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* find a listener */
f4c310fd2555c6faca1f980f00b161eadb089023gstein curr_pollfd = last_pollfd;
f4c310fd2555c6faca1f980f00b161eadb089023gstein do {
f4c310fd2555c6faca1f980f00b161eadb089023gstein curr_pollfd++;
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (curr_pollfd > num_listensocks) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein curr_pollfd = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* XXX: Should we check for POLLERR? */
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_get_revents(&event, listensocks[curr_pollfd], pollset);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (event & APR_POLLIN) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein last_pollfd = curr_pollfd;
f4c310fd2555c6faca1f980f00b161eadb089023gstein sd=listensocks[curr_pollfd];
f4c310fd2555c6faca1f980f00b161eadb089023gstein goto got_fd;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein } while (curr_pollfd != last_pollfd);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe got_fd:
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!workers_may_exit) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_accept(&csd, sd, ptrans);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if ((rv = SAFE_ACCEPT(ap_unlock(process_accept_mutex)))
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe != APR_SUCCESS) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_log_error(APLOG_MARK, APLOG_EMERG, rv, server_conf,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "ap_unlock failed. Attempting to shutdown "
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "process gracefully.");
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe workers_may_exit = 1;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe pthread_mutex_unlock(&thread_accept_mutex);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe process_socket(ptrans, csd, process_slot, thread_slot);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe requests_this_child--;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe else {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if ((rv = SAFE_ACCEPT(ap_unlock(process_accept_mutex)))
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe != APR_SUCCESS) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_log_error(APLOG_MARK, APLOG_EMERG, rv, server_conf,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "ap_unlock failed. Attempting to shutdown "
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "process gracefully.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein workers_may_exit = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
e8f95a682820a599fe41b22977010636be5c2717jim pthread_mutex_unlock(&thread_accept_mutex);
f4c310fd2555c6faca1f980f00b161eadb089023gstein break;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_clear_pool(ptrans);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_destroy_pool(tpool);
99d46a23c6eac800f327b29f8009f7d7da986230trawick ap_update_child_status(process_slot, thread_slot, SERVER_DEAD,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe (request_rec *) NULL);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe pthread_mutex_lock(&worker_thread_count_mutex);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe worker_thread_count--;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (worker_thread_count == 0) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* All the threads have exited, now finish the shutdown process
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * by signalling the sigwait thread */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe kill(my_pid, SIGTERM);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe pthread_mutex_unlock(&worker_thread_count_mutex);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein return NULL;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe}
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowestatic void child_main(int child_num_arg)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein sigset_t sig_mask;
99d46a23c6eac800f327b29f8009f7d7da986230trawick int signal_received;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe pthread_t thread;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe pthread_attr_t thread_attr;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int i;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int my_child_num = child_num_arg;
f4c310fd2555c6faca1f980f00b161eadb089023gstein proc_info *my_info = NULL;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_listen_rec *lr;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_status_t rv;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe my_pid = getpid();
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_create_context(&pchild, pconf);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /*stuff to do before we switch id's, so we have permissions.*/
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe reopen_scoreboard(pchild);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe rv = SAFE_ACCEPT(ap_child_init_lock(&process_accept_mutex, lock_fname,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe pchild));
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (rv != APR_SUCCESS) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_log_error(APLOG_MARK, APLOG_EMERG, rv, server_conf,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "Couldn't initialize cross-process lock in child");
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe clean_child_exit(APEXIT_CHILDFATAL);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (unixd_setup_child()) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein clean_child_exit(APEXIT_CHILDFATAL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_child_init_hook(pchild, server_conf);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /*done with init critical section */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* All threads should mask signals out, accoring to sigwait(2) man page */
f4c310fd2555c6faca1f980f00b161eadb089023gstein sigfillset(&sig_mask);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (pthread_sigmask(SIG_SETMASK, &sig_mask, NULL) != 0) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_log_error(APLOG_MARK, APLOG_ALERT, errno, server_conf, "pthread_sigmask");
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
99d46a23c6eac800f327b29f8009f7d7da986230trawick requests_this_child = ap_max_requests_per_child;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* Set up the pollfd array */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe listensocks = ap_palloc(pchild,
f4c310fd2555c6faca1f980f00b161eadb089023gstein sizeof(*listensocks) * (num_listensocks + 1));
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_create_tcp_socket(&listensocks[0], pchild);
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_put_os_sock(&listensocks[0], &pipe_of_death[0], pchild);
f4c310fd2555c6faca1f980f00b161eadb089023gstein for (lr = ap_listeners, i = 1; i <= num_listensocks; lr = lr->next, ++i)
f4c310fd2555c6faca1f980f00b161eadb089023gstein listensocks[i]=lr->sd;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Setup worker threads */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein worker_thread_count = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein pthread_mutex_init(&worker_thread_count_mutex, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein pthread_mutex_init(&pipe_of_death_mutex, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein pthread_attr_init(&thread_attr);
f4c310fd2555c6faca1f980f00b161eadb089023gstein pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
f4c310fd2555c6faca1f980f00b161eadb089023gstein for (i=0; i < ap_threads_per_child; i++) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein my_info = (proc_info *)malloc(sizeof(proc_info));
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (my_info == NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_ALERT, errno, server_conf,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "malloc: out of memory");
f4c310fd2555c6faca1f980f00b161eadb089023gstein clean_child_exit(APEXIT_CHILDFATAL);
99d46a23c6eac800f327b29f8009f7d7da986230trawick }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe my_info->pid = my_child_num;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe my_info->tid = i;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe my_info->sd = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_create_context(&my_info->tpool, pchild);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* We are creating threads right now */
f4c310fd2555c6faca1f980f00b161eadb089023gstein (void) ap_update_child_status(my_child_num, i, SERVER_STARTING,
f4c310fd2555c6faca1f980f00b161eadb089023gstein (request_rec *) NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein#ifndef NO_THREADS
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (pthread_create(&thread, &thread_attr, worker_thread, my_info)) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_ALERT, errno, server_conf,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "pthread_create: unable to create worker thread");
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* In case system resources are maxxed out, we don't want
f4c310fd2555c6faca1f980f00b161eadb089023gstein Apache running away with the CPU trying to fork over and
f4c310fd2555c6faca1f980f00b161eadb089023gstein over and over again if we exit. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein sleep(10);
f4c310fd2555c6faca1f980f00b161eadb089023gstein clean_child_exit(APEXIT_CHILDFATAL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein#else
f4c310fd2555c6faca1f980f00b161eadb089023gstein worker_thread(my_info);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* The SIGTERM shouldn't let us reach this point, but just in case... */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe clean_child_exit(APEXIT_OK);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe#endif
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* We let each thread update it's own scoreboard entry. This is done
f4c310fd2555c6faca1f980f00b161eadb089023gstein * because it let's us deal with tid better.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein pthread_attr_destroy(&thread_attr);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* This thread will be the one responsible for handling signals */
f4c310fd2555c6faca1f980f00b161eadb089023gstein sigemptyset(&sig_mask);
f4c310fd2555c6faca1f980f00b161eadb089023gstein sigaddset(&sig_mask, SIGTERM);
f4c310fd2555c6faca1f980f00b161eadb089023gstein sigaddset(&sig_mask, SIGINT);
f4c310fd2555c6faca1f980f00b161eadb089023gstein sigwait(&sig_mask, &signal_received);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe switch (signal_received) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe case SIGTERM:
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe case SIGINT:
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe just_die(signal_received);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe break;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe default:
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_log_error(APLOG_MARK, APLOG_ALERT, errno, server_conf,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "received impossible signal: %d", signal_received);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe just_die(SIGTERM);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe}
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowestatic int make_child(server_rec *s, int slot, time_t now)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe{
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe int pid;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (slot + 1 > max_daemons_limit) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe max_daemons_limit = slot + 1;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (one_process) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe set_signals();
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_scoreboard_image->parent[slot].pid = getpid();
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe child_main(slot);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* Tag this slot as occupied so that perform_idle_server_maintenance
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * doesn't try to steal it */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe (void) ap_update_child_status(slot, 0, SERVER_STARTING, (request_rec *) NULL);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if ((pid = fork()) == -1) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_log_error(APLOG_MARK, APLOG_ERR, errno, s, "fork: Unable to fork new process");
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* fork didn't succeed. Fix the scoreboard or else
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * it will say SERVER_STARTING forever and ever
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe */
3ded62d7f2c9b12616d718b8c97d3044baa9ecdbjerenkrantz (void) ap_update_child_status(slot, 0, SERVER_DEAD, (request_rec *) NULL);
3ded62d7f2c9b12616d718b8c97d3044baa9ecdbjerenkrantz
3ded62d7f2c9b12616d718b8c97d3044baa9ecdbjerenkrantz /* In case system resources are maxxed out, we don't want
3ded62d7f2c9b12616d718b8c97d3044baa9ecdbjerenkrantz Apache running away with the CPU trying to fork over and
3ded62d7f2c9b12616d718b8c97d3044baa9ecdbjerenkrantz over and over again. */
3ded62d7f2c9b12616d718b8c97d3044baa9ecdbjerenkrantz sleep(10);
0fad1368edb71b1411d6d00684900e5d2a6e6b78jerenkrantz
0df0055470838140d9797dd186b2fdbe67edcc57jorton return -1;
0df0055470838140d9797dd186b2fdbe67edcc57jorton }
3ded62d7f2c9b12616d718b8c97d3044baa9ecdbjerenkrantz
3ded62d7f2c9b12616d718b8c97d3044baa9ecdbjerenkrantz if (!pid) {
3ded62d7f2c9b12616d718b8c97d3044baa9ecdbjerenkrantz#ifdef AIX_BIND_PROCESSOR
3ded62d7f2c9b12616d718b8c97d3044baa9ecdbjerenkrantz /* By default, AIX binds to a single processor. This bit unbinds
0fad1368edb71b1411d6d00684900e5d2a6e6b78jerenkrantz children which will then bind to another CPU.
0df0055470838140d9797dd186b2fdbe67edcc57jorton */
0df0055470838140d9797dd186b2fdbe67edcc57jorton#include <sys/processor.h>
3ded62d7f2c9b12616d718b8c97d3044baa9ecdbjerenkrantz int status = bindprocessor(BINDPROCESS, (int)getpid(),
3ded62d7f2c9b12616d718b8c97d3044baa9ecdbjerenkrantz PROCESSOR_CLASS_ANY);
3ded62d7f2c9b12616d718b8c97d3044baa9ecdbjerenkrantz if (status != OK)
3ded62d7f2c9b12616d718b8c97d3044baa9ecdbjerenkrantz ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, server_conf,
3ded62d7f2c9b12616d718b8c97d3044baa9ecdbjerenkrantz "processor unbind failed %d", status);
3ded62d7f2c9b12616d718b8c97d3044baa9ecdbjerenkrantz#endif
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe RAISE_SIGSTOP(MAKE_CHILD);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe signal(SIGTERM, just_die);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe child_main(slot);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return 0;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* else */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_scoreboard_image->parent[slot].pid = pid;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return 0;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe}
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe/* start up a bunch of children */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowestatic void startup_children(int number_to_start)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe{
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe int i;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe for (i = 0; number_to_start && i < ap_daemons_limit; ++i) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (ap_scoreboard_image->parent[i].pid != 0) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe continue;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (make_child(server_conf, i, 0) < 0) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe break;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe --number_to_start;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe}
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe/*
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * idle_spawn_rate is the number of children that will be spawned on the
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * next maintenance cycle if there aren't enough idle servers. It is
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * doubled up to MAX_SPAWN_RATE, and reset only when a cycle goes by
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * without the need to spawn.
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowestatic int idle_spawn_rate = 1;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe#ifndef MAX_SPAWN_RATE
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe#define MAX_SPAWN_RATE (32)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe#endif
6f15570e3adc0faf87bf55f70857028276fc9e32wrowestatic int hold_off_on_exponential_spawning;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowestatic void perform_idle_server_maintenance(void)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe{
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe int i, j;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe int idle_thread_count;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe thread_score *ss;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe time_t now = 0;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe int free_length;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe int free_slots[MAX_SPAWN_RATE];
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe int last_non_dead;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe int total_non_dead;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* initialize the free_list */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe free_length = 0;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe idle_thread_count = 0;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe last_non_dead = -1;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe total_non_dead = 0;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_check_signals();
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_sync_scoreboard_image();
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe for (i = 0; i < ap_daemons_limit; ++i) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* Initialization to satisfy the compiler. It doesn't know
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * that ap_threads_per_child is always > 0 */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe int status = SERVER_DEAD;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe int any_dying_threads = 0;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe int all_dead_threads = 1;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe int idle_thread_addition = 0;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (i >= max_daemons_limit && free_length == idle_spawn_rate)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe break;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe for (j = 0; j < ap_threads_per_child; j++) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ss = &ap_scoreboard_image->servers[i][j];
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe status = ss->status;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe any_dying_threads = any_dying_threads || (status == SERVER_DEAD)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe || (status == SERVER_GRACEFUL);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe all_dead_threads = all_dead_threads && (status == SERVER_DEAD);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* We consider a starting server as idle because we started it
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * at least a cycle ago, and if it still hasn't finished starting
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * then we're just going to swamp things worse by forking more.
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * So we hopefully won't need to fork more if we count it.
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * This depends on the ordering of SERVER_READY and SERVER_STARTING.
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (status <= SERVER_READY) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ++idle_thread_addition;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (all_dead_threads && free_length < idle_spawn_rate) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe free_slots[free_length] = i;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ++free_length;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (!all_dead_threads) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein last_non_dead = i;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!any_dying_threads) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ++total_non_dead;
f4c310fd2555c6faca1f980f00b161eadb089023gstein idle_thread_count += idle_thread_addition;
e8f95a682820a599fe41b22977010636be5c2717jim }
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein }
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein max_daemons_limit = last_non_dead + 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (idle_thread_count > max_spare_threads) {
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm /* Kill off one child */
e8f95a682820a599fe41b22977010636be5c2717jim char char_of_death = '!';
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (write(pipe_of_death[1], &char_of_death, 1) == -1) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "write pipe_of_death");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
99d46a23c6eac800f327b29f8009f7d7da986230trawick idle_spawn_rate = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else if (idle_thread_count < min_spare_threads) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* terminate the free list */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (free_length == 0) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* only report this condition once */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe static int reported = 0;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (!reported) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, server_conf,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "server reached MaxClients setting, consider"
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe " raising the MaxClients setting");
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe reported = 1;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe idle_spawn_rate = 1;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe else {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (idle_spawn_rate >= 8) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0, server_conf,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "server seems busy, (you may need "
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "to increase StartServers, ThreadsPerChild "
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "or Min/MaxSparetThreads), "
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "spawning %d children, there are around %d idle "
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "threads, and %d total children", idle_spawn_rate,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe idle_thread_count, total_non_dead);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe for (i = 0; i < free_length; ++i) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe make_child(server_conf, free_slots[i], now);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
42f2b4b0e9b84dfd8acbb9c0da18a07c664e30a1jorton /* the next time around we want to spawn twice as many if this
42f2b4b0e9b84dfd8acbb9c0da18a07c664e30a1jorton * wasn't good enough, but not if we've just done a graceful
42f2b4b0e9b84dfd8acbb9c0da18a07c664e30a1jorton */
42f2b4b0e9b84dfd8acbb9c0da18a07c664e30a1jorton if (hold_off_on_exponential_spawning) {
e8f95a682820a599fe41b22977010636be5c2717jim --hold_off_on_exponential_spawning;
42f2b4b0e9b84dfd8acbb9c0da18a07c664e30a1jorton }
e8f95a682820a599fe41b22977010636be5c2717jim else if (idle_spawn_rate < MAX_SPAWN_RATE) {
42f2b4b0e9b84dfd8acbb9c0da18a07c664e30a1jorton idle_spawn_rate *= 2;
42f2b4b0e9b84dfd8acbb9c0da18a07c664e30a1jorton }
42f2b4b0e9b84dfd8acbb9c0da18a07c664e30a1jorton }
42f2b4b0e9b84dfd8acbb9c0da18a07c664e30a1jorton }
42f2b4b0e9b84dfd8acbb9c0da18a07c664e30a1jorton else {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe idle_spawn_rate = 1;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe}
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowestatic void server_main_loop(int remaining_children_to_start)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe{
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe int child_slot;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_wait_t status;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe int pid;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe int i;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe while (!restart_pending && !shutdown_pending) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe pid = wait_or_timeout(&status);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (pid >= 0) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe process_child_status(pid, status);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* non-fatal death... note that it's gone in the scoreboard. */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe child_slot = find_child_by_pid(pid);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (child_slot >= 0) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe for (i = 0; i < ap_threads_per_child; i++)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_update_child_status(child_slot, i, SERVER_DEAD, (request_rec *) NULL);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (remaining_children_to_start
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe && child_slot < ap_daemons_limit) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* we're still doing a 1-for-1 replacement of dead
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * children with new children
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe make_child(server_conf, child_slot, time(NULL));
f4c310fd2555c6faca1f980f00b161eadb089023gstein --remaining_children_to_start;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
f4c310fd2555c6faca1f980f00b161eadb089023gstein#ifdef HAS_OTHER_CHILD
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else if (reap_other_child(pid, status) == 0) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* handled */
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else if (is_graceful) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Great, we've probably just lost a slot in the
f4c310fd2555c6faca1f980f00b161eadb089023gstein * scoreboard. Somehow we don't know about this
f4c310fd2555c6faca1f980f00b161eadb089023gstein * child.
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, server_conf,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "long lost child came home! (pid %d)", pid);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* Don't perform idle maintenance when a child dies,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * only do it when there's a timeout. Remember only a
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * finite number of children can die, and it's pretty
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * pathological for a lot to die suddenly.
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe continue;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe else if (remaining_children_to_start) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* we hit a 1 second timeout in which none of the previous
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * generation of children needed to be reaped... so assume
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * they're all done, and pick up the slack if any is left.
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe startup_children(remaining_children_to_start);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe remaining_children_to_start = 0;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* In any event we really shouldn't do the code below because
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * few of the servers we just started are in the IDLE state
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * yet, so we'd mistakenly create an extra server.
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe continue;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
f80b9e9d38dff8bc3f51406475adb99d7fe888cegstein
f80b9e9d38dff8bc3f51406475adb99d7fe888cegstein perform_idle_server_maintenance();
f80b9e9d38dff8bc3f51406475adb99d7fe888cegstein }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe}
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wroweint ap_mpm_run(ap_context_t *_pconf, ap_context_t *plog, server_rec *s)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe{
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe int remaining_children_to_start;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_status_t rv;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe pconf = _pconf;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe server_conf = s;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (pipe(pipe_of_death) == -1) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_log_error(APLOG_MARK, APLOG_ERR, errno,
99d46a23c6eac800f327b29f8009f7d7da986230trawick (const server_rec*) server_conf,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "pipe: (pipe_of_death)");
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe exit(1);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe/* XXXXXX Removed because these functions don't exist anymore. When
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe These pipes are changed to apr_types, these functions won't be needed
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe anyway.
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_note_cleanups_for_fd(pconf, pipe_of_death[0]);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_note_cleanups_for_fd(pconf, pipe_of_death[1]);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe*/
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (fcntl(pipe_of_death[0], F_SETFD, O_NONBLOCK) == -1) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_log_error(APLOG_MARK, APLOG_ERR, errno,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe (const server_rec*) server_conf,
99d46a23c6eac800f327b29f8009f7d7da986230trawick "fcntl: O_NONBLOCKing (pipe_of_death)");
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe exit(1);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe server_conf = s;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if ((num_listensocks = setup_listeners(server_conf)) < 1) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* XXX: hey, what's the right way for the mpm to indicate a fatal error? */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ALERT, 0, s,
99d46a23c6eac800f327b29f8009f7d7da986230trawick "no listening sockets available, shutting down");
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return 1;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_log_pid(pconf, ap_pid_fname);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
99d46a23c6eac800f327b29f8009f7d7da986230trawick /* Initialize cross-process accept lock */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe lock_fname = ap_psprintf(_pconf, "%s.%lu",
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_server_root_relative(_pconf, lock_fname),
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe my_pid);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe rv = ap_create_lock(&process_accept_mutex, APR_MUTEX, APR_CROSS_PROCESS,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe lock_fname, _pconf);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (rv != APR_SUCCESS) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Couldn't create cross-process lock");
f4c310fd2555c6faca1f980f00b161eadb089023gstein return 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!is_graceful) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein reinit_scoreboard(pconf);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein set_signals();
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Don't thrash... */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (max_spare_threads < min_spare_threads + ap_threads_per_child)
f4c310fd2555c6faca1f980f00b161eadb089023gstein max_spare_threads = min_spare_threads + ap_threads_per_child;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* If we're doing a graceful_restart then we're going to see a lot
f4c310fd2555c6faca1f980f00b161eadb089023gstein * of children exiting immediately when we get into the main loop
f4c310fd2555c6faca1f980f00b161eadb089023gstein * below (because we just sent them SIGWINCH). This happens pretty
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * rapidly... and for each one that exits we'll start a new one until
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * we reach at least daemons_min_free. But we may be permitted to
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * start more than that, so we'll just keep track of how many we're
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * supposed to start up without the 1 second penalty between each fork.
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe */
f4c310fd2555c6faca1f980f00b161eadb089023gstein remaining_children_to_start = ap_daemons_to_start;
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (remaining_children_to_start > ap_daemons_limit) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein remaining_children_to_start = ap_daemons_limit;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!is_graceful) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein startup_children(remaining_children_to_start);
f4c310fd2555c6faca1f980f00b161eadb089023gstein remaining_children_to_start = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* give the system some time to recover before kicking into
f4c310fd2555c6faca1f980f00b161eadb089023gstein * exponential mode */
f4c310fd2555c6faca1f980f00b161eadb089023gstein hold_off_on_exponential_spawning = 10;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, server_conf,
99d46a23c6eac800f327b29f8009f7d7da986230trawick "%s configured -- resuming normal operations",
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_get_server_version());
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0, server_conf,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "Server built: %s", ap_get_server_built());
f4c310fd2555c6faca1f980f00b161eadb089023gstein restart_pending = shutdown_pending = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
99d46a23c6eac800f327b29f8009f7d7da986230trawick server_main_loop(remaining_children_to_start);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (shutdown_pending) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* Time to gracefully shut down:
f4c310fd2555c6faca1f980f00b161eadb089023gstein * Kill child processes, tell them to call child_exit, etc...
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (ap_killpg(getpgrp(), SIGTERM) < 0) {
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "killpg SIGTERM");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein reclaim_child_processes(1); /* Start with SIGTERM */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* cleanup pid file on normal shutdown */
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe const char *pidfile = NULL;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe pidfile = ap_server_root_relative (pconf, ap_pid_fname);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if ( pidfile != NULL && unlink(pidfile) == 0)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe server_conf,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "removed PID file %s (pid=%ld)",
f4c310fd2555c6faca1f980f00b161eadb089023gstein pidfile, (long)getpid());
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, server_conf,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "caught SIGTERM, shutting down");
f4c310fd2555c6faca1f980f00b161eadb089023gstein
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein return 1;
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* we've been told to restart */
f4c310fd2555c6faca1f980f00b161eadb089023gstein signal(SIGHUP, SIG_IGN);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (one_process) {
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein /* not worth thinking about */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* advance to the next generation */
ef1ab47476366272bf32be1439057f972bfe86edniq /* XXX: we really need to make sure this new generation number isn't in
ef1ab47476366272bf32be1439057f972bfe86edniq * use by any of the children.
ef1ab47476366272bf32be1439057f972bfe86edniq */
ef1ab47476366272bf32be1439057f972bfe86edniq ++ap_my_generation;
ef1ab47476366272bf32be1439057f972bfe86edniq ap_scoreboard_image->global.running_generation = ap_my_generation;
ef1ab47476366272bf32be1439057f972bfe86edniq update_scoreboard_global();
ef1ab47476366272bf32be1439057f972bfe86edniq
ef1ab47476366272bf32be1439057f972bfe86edniq if (is_graceful) {
ef1ab47476366272bf32be1439057f972bfe86edniq int i, j;
5d760c4a4841be07965080c4cec527d8f5172ef5rpluem char char_of_death = '!';
ef1ab47476366272bf32be1439057f972bfe86edniq
ef1ab47476366272bf32be1439057f972bfe86edniq ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, server_conf,
ef1ab47476366272bf32be1439057f972bfe86edniq "SIGWINCH received. Doing graceful restart");
ef1ab47476366272bf32be1439057f972bfe86edniq
ef1ab47476366272bf32be1439057f972bfe86edniq /* give the children the signal to die */
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim for (i = 0; i < ap_daemons_limit;) {
ef1ab47476366272bf32be1439057f972bfe86edniq if (write(pipe_of_death[1], &char_of_death, 1) == -1) {
5d760c4a4841be07965080c4cec527d8f5172ef5rpluem if (errno == EINTR) continue;
ef1ab47476366272bf32be1439057f972bfe86edniq ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "write pipe_of_death");
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim }
ef1ab47476366272bf32be1439057f972bfe86edniq i++;
5d760c4a4841be07965080c4cec527d8f5172ef5rpluem }
5d760c4a4841be07965080c4cec527d8f5172ef5rpluem
5d760c4a4841be07965080c4cec527d8f5172ef5rpluem /* This is mostly for debugging... so that we know what is still
5d760c4a4841be07965080c4cec527d8f5172ef5rpluem * gracefully dealing with existing request.
ef1ab47476366272bf32be1439057f972bfe86edniq */
5d760c4a4841be07965080c4cec527d8f5172ef5rpluem
ef1ab47476366272bf32be1439057f972bfe86edniq for (i = 0; i < ap_daemons_limit; ++i) {
ef1ab47476366272bf32be1439057f972bfe86edniq for (j = 0; j < ap_threads_per_child; j++) {
ef1ab47476366272bf32be1439057f972bfe86edniq if (ap_scoreboard_image->servers[i][j].status != SERVER_DEAD) {
ef1ab47476366272bf32be1439057f972bfe86edniq ap_scoreboard_image->servers[i][j].status = SERVER_GRACEFUL;
ef1ab47476366272bf32be1439057f972bfe86edniq }
ef1ab47476366272bf32be1439057f972bfe86edniq }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Kill 'em all. Since the child acts the same on the parents SIGTERM
f4c310fd2555c6faca1f980f00b161eadb089023gstein * and a SIGHUP, we may as well use the same signal, because some user
f4c310fd2555c6faca1f980f00b161eadb089023gstein * pthreads are stealing signals from us left and right.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (ap_killpg(getpgrp(), SIGTERM) < 0) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "killpg SIGTERM");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein reclaim_child_processes(1); /* Start with SIGTERM */
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, server_conf,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "SIGHUP received. Attempting to restart");
e8f95a682820a599fe41b22977010636be5c2717jim }
0206c121a68a63559b2e843288e81bcf16093e46jerenkrantz if (!is_graceful) {
0206c121a68a63559b2e843288e81bcf16093e46jerenkrantz ap_restart_time = time(NULL);
0206c121a68a63559b2e843288e81bcf16093e46jerenkrantz }
0206c121a68a63559b2e843288e81bcf16093e46jerenkrantz return 0;
0206c121a68a63559b2e843288e81bcf16093e46jerenkrantz}
0206c121a68a63559b2e843288e81bcf16093e46jerenkrantz
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic void mpmt_pthread_pre_config(ap_context_t *pconf, ap_context_t *plog, ap_context_t *ptemp)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein static int restart_num = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein one_process = !!getenv("ONE_PROCESS");
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* sigh, want this only the second time around */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (restart_num++ == 1) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein is_graceful = 0;
ef1ab47476366272bf32be1439057f972bfe86edniq
d64231e66711504d8e33d594fc5c27ae86e7b629rpluem if (!one_process) {
d64231e66711504d8e33d594fc5c27ae86e7b629rpluem unixd_detach();
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein my_pid = getpid();
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
f4c310fd2555c6faca1f980f00b161eadb089023gstein unixd_pre_config();
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_listen_pre_config();
99d46a23c6eac800f327b29f8009f7d7da986230trawick ap_daemons_to_start = DEFAULT_START_DAEMON;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe min_spare_threads = DEFAULT_MIN_FREE_DAEMON * DEFAULT_THREADS_PER_CHILD;
f4c310fd2555c6faca1f980f00b161eadb089023gstein max_spare_threads = DEFAULT_MAX_FREE_DAEMON * DEFAULT_THREADS_PER_CHILD;
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_daemons_limit = HARD_SERVER_LIMIT;
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_threads_per_child = DEFAULT_THREADS_PER_CHILD;
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_pid_fname = DEFAULT_PIDLOG;
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_scoreboard_fname = DEFAULT_SCOREBOARD;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe lock_fname = DEFAULT_LOCKFILE;
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_max_requests_per_child = DEFAULT_MAX_REQUESTS_PER_CHILD;
ef1ab47476366272bf32be1439057f972bfe86edniq ap_extended_status = 0;
d64231e66711504d8e33d594fc5c27ae86e7b629rpluem
d64231e66711504d8e33d594fc5c27ae86e7b629rpluem ap_cpystrn(ap_coredump_dir, ap_server_root, sizeof(ap_coredump_dir));
d64231e66711504d8e33d594fc5c27ae86e7b629rpluem}
d64231e66711504d8e33d594fc5c27ae86e7b629rpluem
d64231e66711504d8e33d594fc5c27ae86e7b629rpluemstatic void mpmt_pthread_hooks(void)
d64231e66711504d8e33d594fc5c27ae86e7b629rpluem{
d64231e66711504d8e33d594fc5c27ae86e7b629rpluem ap_hook_pre_config(mpmt_pthread_pre_config,NULL,NULL,HOOK_MIDDLE);
ef1ab47476366272bf32be1439057f972bfe86edniq INIT_SIGLIST()
e8f95a682820a599fe41b22977010636be5c2717jim one_process = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
d64231e66711504d8e33d594fc5c27ae86e7b629rpluem
d64231e66711504d8e33d594fc5c27ae86e7b629rpluem
d64231e66711504d8e33d594fc5c27ae86e7b629rpluemstatic const char *set_pidfile(cmd_parms *cmd, void *dummy, char *arg)
d64231e66711504d8e33d594fc5c27ae86e7b629rpluem{
d64231e66711504d8e33d594fc5c27ae86e7b629rpluem const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
d64231e66711504d8e33d594fc5c27ae86e7b629rpluem if (err != NULL) {
d64231e66711504d8e33d594fc5c27ae86e7b629rpluem return err;
d64231e66711504d8e33d594fc5c27ae86e7b629rpluem }
d64231e66711504d8e33d594fc5c27ae86e7b629rpluem
d64231e66711504d8e33d594fc5c27ae86e7b629rpluem if (cmd->server->is_virtual) {
d64231e66711504d8e33d594fc5c27ae86e7b629rpluem return "PidFile directive not allowed in <VirtualHost>";
d64231e66711504d8e33d594fc5c27ae86e7b629rpluem }
99d46a23c6eac800f327b29f8009f7d7da986230trawick ap_pid_fname = arg;
f4c310fd2555c6faca1f980f00b161eadb089023gstein return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic const char *set_scoreboard(cmd_parms *cmd, void *dummy, char *arg)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe{
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (err != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return err;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_scoreboard_fname = arg;
f4c310fd2555c6faca1f980f00b161eadb089023gstein return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
6f15570e3adc0faf87bf55f70857028276fc9e32wrowestatic const char *set_lockfile(cmd_parms *cmd, void *dummy, char *arg)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (err != NULL) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return err;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe lock_fname = arg;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return NULL;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe}
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic const char *set_daemons_to_start(cmd_parms *cmd, void *dummy, char *arg)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe{
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (err != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return err;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_daemons_to_start = atoi(arg);
f4c310fd2555c6faca1f980f00b161eadb089023gstein return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic const char *set_min_spare_threads(cmd_parms *cmd, void *dummy, char *arg)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (err != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return err;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein min_spare_threads = atoi(arg);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (min_spare_threads <= 0) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "WARNING: detected MinSpareThreads set to non-positive.");
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
f94aab38f6ee899f463f0118ea395291f7c5b4cegstein "Resetting to 1 to avoid almost certain Apache failure.");
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "Please read the documentation.");
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe min_spare_threads = 1;
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowestatic const char *set_max_spare_threads(cmd_parms *cmd, void *dummy, char *arg)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (err != NULL) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return err;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
f4c310fd2555c6faca1f980f00b161eadb089023gstein max_spare_threads = atoi(arg);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return NULL;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe}
4f71b58f8cd75489a8e7e6e710a016a73a911efcjailletc
6f15570e3adc0faf87bf55f70857028276fc9e32wrowestatic const char *set_server_limit (cmd_parms *cmd, void *dummy, char *arg)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (err != NULL) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return err;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_daemons_limit = atoi(arg);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (ap_daemons_limit > HARD_SERVER_LIMIT) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein "WARNING: MaxClients of %d exceeds compile time limit "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "of %d servers,", ap_daemons_limit, HARD_SERVER_LIMIT);
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein " lowering MaxClients to %d. To increase, please "
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "see the", HARD_SERVER_LIMIT);
99d46a23c6eac800f327b29f8009f7d7da986230trawick ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe " HARD_SERVER_LIMIT define in src/include/httpd.h.");
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_daemons_limit = HARD_SERVER_LIMIT;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe else if (ap_daemons_limit < 1) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, "WARNING: Require MaxClients > 0, setting to 1\n");
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_daemons_limit = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
e8f95a682820a599fe41b22977010636be5c2717jim return NULL;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe}
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowestatic const char *set_threads_per_child (cmd_parms *cmd, void *dummy, char *arg)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe{
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (err != NULL) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return err;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe }
e8f95a682820a599fe41b22977010636be5c2717jim
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_threads_per_child = atoi(arg);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (ap_threads_per_child > HARD_THREAD_LIMIT) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "WARNING: ThreadsPerChild of %d exceeds compile time"
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "limit of %d threads,", ap_threads_per_child,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe HARD_THREAD_LIMIT);
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm " lowering ThreadsPerChild to %d. To increase, please"
f4c310fd2555c6faca1f980f00b161eadb089023gstein "see the", HARD_THREAD_LIMIT);
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
f4c310fd2555c6faca1f980f00b161eadb089023gstein " HARD_THREAD_LIMIT define in src/include/httpd.h.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
e8f95a682820a599fe41b22977010636be5c2717jim else if (ap_threads_per_child < 1) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "WARNING: Require ThreadsPerChild > 0, setting to 1");
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_threads_per_child = 1;
e8f95a682820a599fe41b22977010636be5c2717jim }
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return NULL;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe}
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic const char *set_max_requests(cmd_parms *cmd, void *dummy, char *arg)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (err != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return err;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_max_requests_per_child = atoi(arg);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic const char *set_coredumpdir (cmd_parms *cmd, void *dummy, char *arg)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe struct stat finfo;
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *fname;
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (err != NULL) {
99d46a23c6eac800f327b29f8009f7d7da986230trawick return err;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein fname = ap_server_root_relative(cmd->pool, arg);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((stat(fname, &finfo) == -1) || !S_ISDIR(finfo.st_mode)) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return ap_pstrcat(cmd->pool, "CoreDumpDirectory ", fname,
f4c310fd2555c6faca1f980f00b161eadb089023gstein " does not exist or is not a directory", NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_cpystrn(ap_coredump_dir, fname, sizeof(ap_coredump_dir));
f4c310fd2555c6faca1f980f00b161eadb089023gstein return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic const command_rec mpmt_pthread_cmds[] = {
f4c310fd2555c6faca1f980f00b161eadb089023gsteinUNIX_DAEMON_COMMANDS
1ccd992d37d62c8cb2056126f2234f64ec189bfddougmLISTEN_COMMANDS
f4c310fd2555c6faca1f980f00b161eadb089023gstein{ "PidFile", set_pidfile, NULL, RSRC_CONF, TAKE1,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "A file for logging the server process ID"},
f4c310fd2555c6faca1f980f00b161eadb089023gstein{ "ScoreBoardFile", set_scoreboard, NULL, RSRC_CONF, TAKE1,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "A file for Apache to maintain runtime process management information"},
f4c310fd2555c6faca1f980f00b161eadb089023gstein{ "LockFile", set_lockfile, NULL, RSRC_CONF, TAKE1,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "The lockfile used when Apache needs to lock the accept() call"},
f4c310fd2555c6faca1f980f00b161eadb089023gstein{ "StartServers", set_daemons_to_start, NULL, RSRC_CONF, TAKE1,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Number of child processes launched at server startup" },
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm{ "MinSpareThreads", set_min_spare_threads, NULL, RSRC_CONF, TAKE1,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Minimum number of idle children, to handle request spikes" },
f4c310fd2555c6faca1f980f00b161eadb089023gstein{ "MaxSpareThreads", set_max_spare_threads, NULL, RSRC_CONF, TAKE1,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Maximum number of idle children" },
f4c310fd2555c6faca1f980f00b161eadb089023gstein{ "MaxClients", set_server_limit, NULL, RSRC_CONF, TAKE1,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Maximum number of children alive at the same time" },
f4c310fd2555c6faca1f980f00b161eadb089023gstein{ "ThreadsPerChild", set_threads_per_child, NULL, RSRC_CONF, TAKE1,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Number of threads each child creates" },
f4c310fd2555c6faca1f980f00b161eadb089023gstein{ "MaxRequestsPerChild", set_max_requests, NULL, RSRC_CONF, TAKE1,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Maximum number of requests a particular child serves before dying." },
f4c310fd2555c6faca1f980f00b161eadb089023gstein{ "CoreDumpDirectory", set_coredumpdir, NULL, RSRC_CONF, TAKE1,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "The location of the directory Apache changes to before dumping core" },
99d46a23c6eac800f327b29f8009f7d7da986230trawick{ NULL }
f4c310fd2555c6faca1f980f00b161eadb089023gstein};
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinmodule MODULE_VAR_EXPORT mpm_mpmt_pthread_module = {
f4c310fd2555c6faca1f980f00b161eadb089023gstein STANDARD20_MODULE_STUFF,
f4c310fd2555c6faca1f980f00b161eadb089023gstein NULL, /* create per-directory config structure */
f4c310fd2555c6faca1f980f00b161eadb089023gstein NULL, /* merge per-directory config structures */
f4c310fd2555c6faca1f980f00b161eadb089023gstein NULL, /* create per-server config structure */
f4c310fd2555c6faca1f980f00b161eadb089023gstein NULL, /* merge per-server config structures */
f4c310fd2555c6faca1f980f00b161eadb089023gstein mpmt_pthread_cmds, /* command ap_table_t */
f4c310fd2555c6faca1f980f00b161eadb089023gstein NULL, /* handlers */
f4c310fd2555c6faca1f980f00b161eadb089023gstein mpmt_pthread_hooks /* register_hooks */
f4c310fd2555c6faca1f980f00b161eadb089023gstein};
0206c121a68a63559b2e843288e81bcf16093e46jerenkrantz
e8f95a682820a599fe41b22977010636be5c2717jim