spmt_os2.c revision b31025f6f2c0392dc76eecca7f27faad0b902be0
0b152383e04dbeb10dba29bcdfaa0981e4d9df27Simon Ulbricht/* ====================================================================
0b152383e04dbeb10dba29bcdfaa0981e4d9df27Simon Ulbricht * The Apache Software License, Version 1.1
0b152383e04dbeb10dba29bcdfaa0981e4d9df27Simon Ulbricht * Copyright (c) 2000 The Apache Software Foundation. All rights
0b152383e04dbeb10dba29bcdfaa0981e4d9df27Simon Ulbricht * Redistribution and use in source and binary forms, with or without
0b152383e04dbeb10dba29bcdfaa0981e4d9df27Simon Ulbricht * modification, are permitted provided that the following conditions
0b152383e04dbeb10dba29bcdfaa0981e4d9df27Simon Ulbricht * 1. Redistributions of source code must retain the above copyright
0b152383e04dbeb10dba29bcdfaa0981e4d9df27Simon Ulbricht * notice, this list of conditions and the following disclaimer.
2643008447e30b6025f742eb6a661f38be756b1eSimon Ulbricht * 2. Redistributions in binary form must reproduce the above copyright
9da6e0cb2ea6e43f5b09dcd2a9af5468a5d0fcf4Christian Maeder * notice, this list of conditions and the following disclaimer in
2643008447e30b6025f742eb6a661f38be756b1eSimon Ulbricht * the documentation and/or other materials provided with the
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * distribution.
d815d2b83e945875100ceca322ebd50d96714206Simon Ulbricht * 3. The end-user documentation included with the redistribution,
b0adcc203b4267d5535b430372935a5f36726db1Simon Ulbricht * if any, must include the following acknowledgment:
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * "This product includes software developed by the
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * Apache Software Foundation (http://www.apache.org/)."
abea93ed557b22ea833e1524ee5ca11afc12208aSimon Ulbricht * Alternately, this acknowledgment may appear in the software itself,
a210c2e5add831cd438183c8602ed8e610922beaSimon Ulbricht * if and wherever such third-party acknowledgments normally appear.
a210c2e5add831cd438183c8602ed8e610922beaSimon Ulbricht * 4. The names "Apache" and "Apache Software Foundation" must
6150196e8d99f7161a622fdc1a872fecd378195fSimon Ulbricht * not be used to endorse or promote products derived from this
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * software without prior written permission. For written
9da6e0cb2ea6e43f5b09dcd2a9af5468a5d0fcf4Christian Maeder * permission, please contact apache@apache.org.
3209c34f23fb83a86fbbdd6501db6d4bfb949a57Simon Ulbricht * 5. Products derived from this software may not be called "Apache",
2643008447e30b6025f742eb6a661f38be756b1eSimon Ulbricht * nor may "Apache" appear in their name, without prior written
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * permission of the Apache Software Foundation.
a210c2e5add831cd438183c8602ed8e610922beaSimon Ulbricht * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
a210c2e5add831cd438183c8602ed8e610922beaSimon Ulbricht * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
a210c2e5add831cd438183c8602ed8e610922beaSimon Ulbricht * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
9da6e0cb2ea6e43f5b09dcd2a9af5468a5d0fcf4Christian Maeder * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
9da6e0cb2ea6e43f5b09dcd2a9af5468a5d0fcf4Christian Maeder * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
9da6e0cb2ea6e43f5b09dcd2a9af5468a5d0fcf4Christian Maeder * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9da6e0cb2ea6e43f5b09dcd2a9af5468a5d0fcf4Christian Maeder * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
9da6e0cb2ea6e43f5b09dcd2a9af5468a5d0fcf4Christian Maeder * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
9da6e0cb2ea6e43f5b09dcd2a9af5468a5d0fcf4Christian Maeder * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
9da6e0cb2ea6e43f5b09dcd2a9af5468a5d0fcf4Christian Maeder * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
9da6e0cb2ea6e43f5b09dcd2a9af5468a5d0fcf4Christian Maeder * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
9da6e0cb2ea6e43f5b09dcd2a9af5468a5d0fcf4Christian Maeder * SUCH DAMAGE.
abea93ed557b22ea833e1524ee5ca11afc12208aSimon Ulbricht * ====================================================================
9da6e0cb2ea6e43f5b09dcd2a9af5468a5d0fcf4Christian Maeder * This software consists of voluntary contributions made by many
9da6e0cb2ea6e43f5b09dcd2a9af5468a5d0fcf4Christian Maeder * individuals on behalf of the Apache Software Foundation. For more
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * information on the Apache Software Foundation, please see
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * Portions of this software are based upon public domain software
65660c22133e6de16f9ece7b36ac6423014b20aaChristian Maeder * originally written at the National Center for Supercomputing Applications,
65660c22133e6de16f9ece7b36ac6423014b20aaChristian Maeder * University of Illinois, Urbana-Champaign.
e9a1a4d5820d527a6800d524ebaf29fbad6196c6Simon Ulbricht#include "http_core.h" /* for get_remote_host */
e9a1a4d5820d527a6800d524ebaf29fbad6196c6Simon Ulbricht/* config globals */
432ac7c08e2592af0660e026051ffb052e88a100Simon Ulbricht * The max child slot ever assigned, preserved across restarts. Necessary
432ac7c08e2592af0660e026051ffb052e88a100Simon Ulbricht * to deal with MaxClients changes across SIGUSR1 restarts. We use this
432ac7c08e2592af0660e026051ffb052e88a100Simon Ulbricht * value to optimize routines that have to scan the entire scoreboard.
a210c2e5add831cd438183c8602ed8e610922beaSimon Ulbricht/* *Non*-shared http_main globals... */
65660c22133e6de16f9ece7b36ac6423014b20aaChristian Maeder/* one_process --- debugging mode variable; can be set from the command line
e9a1a4d5820d527a6800d524ebaf29fbad6196c6Simon Ulbricht * with the -X flag. If set, this gets you the child_main loop running
e9a1a4d5820d527a6800d524ebaf29fbad6196c6Simon Ulbricht * in the process which originally started up (no detach, no make_child),
e9a1a4d5820d527a6800d524ebaf29fbad6196c6Simon Ulbricht * which is a pretty nice debugging environment. (You'll get a SIGHUP
e9a1a4d5820d527a6800d524ebaf29fbad6196c6Simon Ulbricht * early in standalone_main; just continue through. This is the server
e9a1a4d5820d527a6800d524ebaf29fbad6196c6Simon Ulbricht * trying to kill off any child processes which it might have lying
e9a1a4d5820d527a6800d524ebaf29fbad6196c6Simon Ulbricht * around --- Apache doesn't keep track of their pids, it just sends
65660c22133e6de16f9ece7b36ac6423014b20aaChristian Maeder * SIGHUP to the process group, ignoring it in the root process.
65660c22133e6de16f9ece7b36ac6423014b20aaChristian Maeder * Continue through and you'll be fine.).
abea93ed557b22ea833e1524ee5ca11afc12208aSimon Ulbrichtstatic apr_pool_t *pconf; /* Pool for config stuff */
abea93ed557b22ea833e1524ee5ca11afc12208aSimon Ulbrichtstatic scoreboard *ap_scoreboard_image = NULL;
abea93ed557b22ea833e1524ee5ca11afc12208aSimon Ulbricht apr_pool_t *pchild; /* Pool for httpd child stuff */
abea93ed557b22ea833e1524ee5ca11afc12208aSimon Ulbrichtstatic struct thread_globals **ppthread_globals = NULL;
abea93ed557b22ea833e1524ee5ca11afc12208aSimon Ulbricht#define THREAD_GLOBAL(gvar) ((*ppthread_globals)->gvar)
65660c22133e6de16f9ece7b36ac6423014b20aaChristian Maeder ap_scoreboard_image = (scoreboard *) malloc(SCOREBOARD_SIZE);
65660c22133e6de16f9ece7b36ac6423014b20aaChristian Maeder ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
a210c2e5add831cd438183c8602ed8e610922beaSimon Ulbricht "Ouch! Out of memory reiniting scoreboard!");
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht memset(ap_scoreboard_image, 0, SCOREBOARD_SIZE);
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht/* a clean exit from a child with proper cleanup */
22a42cbea5bdf4b39b99794550b1403b3820b5e5Christian Maeder ap_scoreboard_image->servers[THREAD_GLOBAL(child_num)].thread_retval = code;
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbrichtstatic apr_status_t accept_mutex_child_cleanup(void *foo)
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * Initialize mutex lock.
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * Done by each child at it's birth
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbrichtstatic void accept_mutex_child_init(apr_pool_t *p)
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht apr_register_cleanup(p, NULL, accept_mutex_child_cleanup, apr_null_cleanup);
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * Initialize mutex lock.
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * Must be safe to call this on a restart.
1651c7f5055453e18a8c34f96c333e2aa702a34eSimon Ulbricht apr_status_t rc = apr_create_lock(&accept_mutex, APR_MUTEX, APR_INTRAPROCESS, NULL, p);
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht ap_log_error(APLOG_MARK, APLOG_EMERG, rc, ap_server_conf,
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht "Error creating accept lock. Exiting!");
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbrichtstatic void accept_mutex_on(void)
a210c2e5add831cd438183c8602ed8e610922beaSimon Ulbricht ap_log_error(APLOG_MARK, APLOG_EMERG, rc, ap_server_conf,
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht "Error getting accept lock. Exiting!");
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbrichtstatic void accept_mutex_off(void)
a210c2e5add831cd438183c8602ed8e610922beaSimon Ulbricht ap_log_error(APLOG_MARK, APLOG_EMERG, rc, ap_server_conf,
1651c7f5055453e18a8c34f96c333e2aa702a34eSimon Ulbricht "Error freeing accept lock. Exiting!");
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht/* On some architectures it's safe to do unserialized accept()s in the single
65660c22133e6de16f9ece7b36ac6423014b20aaChristian Maeder * Listen case. But it's never safe to do it in the case where there's
a210c2e5add831cd438183c8602ed8e610922beaSimon Ulbricht * multiple Listen statements. Define SINGLE_LISTEN_UNSERIALIZED_ACCEPT
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * when it's safe in the single Listen case.
1651c7f5055453e18a8c34f96c333e2aa702a34eSimon Ulbricht#define SAFE_ACCEPT(stmt) do {if (ap_listeners->next) {stmt;}} while(0)
1651c7f5055453e18a8c34f96c333e2aa702a34eSimon UlbrichtAP_DECLARE(int) ap_exists_scoreboard_image(void)
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbrichtint ap_update_child_status(int child_num, int status, request_rec *r)
65660c22133e6de16f9ece7b36ac6423014b20aaChristian Maeder ss = &ap_scoreboard_image->servers[child_num];
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht if (status == SERVER_READY || status == SERVER_DEAD) {
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht * Reset individual counters
369771f5d48a40eda134026b1f45f63b2c00bdb8Simon Ulbricht apr_cpystrn(ss->client, ap_get_remote_host(c, r->per_dir_config,
65660c22133e6de16f9ece7b36ac6423014b20aaChristian Maeder apr_cpystrn(ss->request, "NULL", sizeof(ss->request));
65660c22133e6de16f9ece7b36ac6423014b20aaChristian Maeder } else if (r->parsed_uri.password == NULL) {
a210c2e5add831cd438183c8602ed8e610922beaSimon Ulbricht apr_cpystrn(ss->request, r->the_request, sizeof(ss->request));
53d3b5d18cae658f0e54872ade90ab5259b52b95Simon Ulbricht /* Don't reveal the password in the server-status view */
53d3b5d18cae658f0e54872ade90ab5259b52b95Simon Ulbricht apr_cpystrn(ss->request, apr_pstrcat(r->pool, r->method, " ",
53d3b5d18cae658f0e54872ade90ab5259b52b95Simon Ulbricht ap_unparse_uri_components(r->pool, &r->parsed_uri, UNP_OMITPASSWORD),
c1d06b3018b34ede2b3fb6c7fe2ad28cd5ce5b68Christian Maeder r->assbackwards ? NULL : " ", r->protocol, NULL),
53d3b5d18cae658f0e54872ade90ab5259b52b95Simon Ulbricht if (status == SERVER_STARTING && r == NULL) {
53d3b5d18cae658f0e54872ade90ab5259b52b95Simon Ulbricht /* clean up the slot's vhostrec pointer (maybe re-used)
53d3b5d18cae658f0e54872ade90ab5259b52b95Simon Ulbricht * and mark the slot as belonging to a new generation.
53d3b5d18cae658f0e54872ade90ab5259b52b95Simon Ulbricht ap_scoreboard_image->parent[child_num].generation = ap_scoreboard_image->global.running_generation;
if (child_num < 0)
#ifdef HAVE_TIMES
for (i = 0; i < max_daemons_limit; ++i)
#ifndef INTERVAL_OF_WRITABLE_PROBES
static int wait_or_timeout_counter;
int ret;
tid = 0;
if (ret == 0) {
return tid;
#if defined(NSIG)
static void siglist_init(void)
int sig;
#ifdef SIGHUP
#ifdef SIGINT
#ifdef SIGQUIT
#ifdef SIGILL
#ifdef SIGTRAP
#ifdef SIGIOT
#ifdef SIGABRT
#ifdef SIGEMT
#ifdef SIGFPE
#ifdef SIGKILL
#ifdef SIGBUS
#ifdef SIGSEGV
#ifdef SIGSYS
#ifdef SIGPIPE
#ifdef SIGALRM
#ifdef SIGTERM
#ifdef SIGUSR1
#ifdef SIGUSR2
#ifdef SIGCLD
#ifdef SIGCHLD
#ifdef SIGPWR
#ifdef SIGWINCH
#ifdef SIGURG
#ifdef SIGPOLL
#ifdef SIGIO
#ifdef SIGSTOP
#ifdef SIGTSTP
#ifdef SIGCONT
#ifdef SIGTTIN
#ifdef SIGTTOU
#ifdef SIGVTALRM
#ifdef SIGPROF
#ifdef SIGXCPU
#ifdef SIGXFSZ
clean_child_exit(0);
static int volatile shutdown_pending;
static int volatile restart_pending;
static int volatile is_graceful;
static void set_signals(void)
#ifndef NO_USE_SIGACTION
if (!one_process) {
#if defined(SA_ONESHOT)
#ifdef SIGBUS
#ifdef SIGABORT
#ifdef SIGABRT
#ifdef SIGILL
#ifdef SIGINT
#ifdef SIGXCPU
#ifdef SIGXFSZ
#ifdef SIGPIPE
if (!one_process) {
#ifdef SIGBUS
#ifdef SIGABORT
#ifdef SIGABRT
#ifdef SIGILL
#ifdef SIGXCPU
#ifdef SIGXFSZ
#ifdef SIGHUP
#ifdef SIGUSR1
#ifdef SIGPIPE
int ap_graceful_stop_signalled(void)
ap_scoreboard_image->global.running_generation != ap_scoreboard_image->parent[THREAD_GLOBAL(child_num)].generation) {
int ap_stop_signalled(void)
ap_scoreboard_image->global.running_generation != ap_scoreboard_image->parent[THREAD_GLOBAL(child_num)].generation) {
int numfds = 0;
numfds++;
int requests_this_child = 0;
while (!ap_stop_signalled()) {
int srv;
if ((ap_max_requests_per_child > 0
clean_child_exit(0);
if (ap_stop_signalled()) {
clean_child_exit(0);
if (!lr) {
clean_child_exit(0);
if (ap_stop_signalled()) {
clean_child_exit(0);
clean_child_exit(0);
if (one_process) {
#ifdef SIGQUIT
ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, s, "_beginthread: Unable to create new thread");
#ifndef MAX_SPAWN_RATE
static int hold_off_on_exponential_spawning;
static void perform_idle_server_maintenance(void)
int to_kill;
int idle_count;
int free_length;
int last_non_dead;
int total_non_dead;
free_length = 0;
idle_count = 0;
total_non_dead = 0;
for (i = 0; i < ap_daemons_limit; ++i) {
int status;
++free_length;
++ idle_count;
to_kill = i;
last_non_dead = i;
if (free_length == 0) {
static int reported = 0;
if (!reported) {
"to increase StartServers, or Min/MaxSpareServers), "
for (i = 0; i < free_length; ++i) {
ap_server_conf = s;
if (!is_graceful) {
set_signals();
if (!is_graceful) {
int child_slot;
if (tid >= 0) {
if (child_slot >= 0) {
else if (is_graceful) {
else if (remaining_children_to_start) {
if (shutdown_pending) {
int slot;
DosSleep(0);
if (rc == 0) {
if (rc) {
if (one_process) {
if (is_graceful) {
for (i = 0; i < ap_daemons_limit; ++i) {
for (i = 0; i < ap_daemons_limit; ++i) {
for (i = 0; i < ap_daemons_limit; ++i) {
if (!is_graceful) {
is_graceful = 0;
ap_extended_status = 0;
INIT_SIGLIST();
return err;
return NULL;
return err;
return NULL;
return err;
if (ap_daemons_min_free <= 0) {
return NULL;
return err;
return NULL;
return err;
return NULL;
return err;
return NULL;
const char *fname;
return err;
return NULL;
const char *value)
{ NULL }