mpmt_pthread.c revision b31025f6f2c0392dc76eecca7f27faad0b902be0
e609c337f729875bc20e01096c7e610f45356f54nilgun/* ====================================================================
e609c337f729875bc20e01096c7e610f45356f54nilgun * The Apache Software License, Version 1.1
e609c337f729875bc20e01096c7e610f45356f54nilgun * Copyright (c) 2000 The Apache Software Foundation. All rights
e609c337f729875bc20e01096c7e610f45356f54nilgun * reserved.
e609c337f729875bc20e01096c7e610f45356f54nilgun * Redistribution and use in source and binary forms, with or without
e609c337f729875bc20e01096c7e610f45356f54nilgun * modification, are permitted provided that the following conditions
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen * 1. Redistributions of source code must retain the above copyright
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen * notice, this list of conditions and the following disclaimer.
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen * 2. Redistributions in binary form must reproduce the above copyright
e609c337f729875bc20e01096c7e610f45356f54nilgun * notice, this list of conditions and the following disclaimer in
e609c337f729875bc20e01096c7e610f45356f54nilgun * the documentation and/or other materials provided with the
d229f940abfb2490dee17979e9a5ff31b7012eb5rbowen * distribution.
e609c337f729875bc20e01096c7e610f45356f54nilgun * 3. The end-user documentation included with the redistribution,
e609c337f729875bc20e01096c7e610f45356f54nilgun * if any, must include the following acknowledgment:
e609c337f729875bc20e01096c7e610f45356f54nilgun * "This product includes software developed by the
3f08db06526d6901aa08c110b5bc7dde6bc39905nd * Apache Software Foundation (http://www.apache.org/)."
e609c337f729875bc20e01096c7e610f45356f54nilgun * Alternately, this acknowledgment may appear in the software itself,
e609c337f729875bc20e01096c7e610f45356f54nilgun * if and wherever such third-party acknowledgments normally appear.
f086b4b402fa9a2fefc7dda85de2a3cc1cd0a654rjung * 4. The names "Apache" and "Apache Software Foundation" must
e609c337f729875bc20e01096c7e610f45356f54nilgun * not be used to endorse or promote products derived from this
e8897b2f72c5fc3bf4a5da96745a320a8b2acae7rbowen * software without prior written permission. For written
e609c337f729875bc20e01096c7e610f45356f54nilgun * permission, please contact apache@apache.org.
e609c337f729875bc20e01096c7e610f45356f54nilgun * 5. Products derived from this software may not be called "Apache",
e609c337f729875bc20e01096c7e610f45356f54nilgun * nor may "Apache" appear in their name, without prior written
e609c337f729875bc20e01096c7e610f45356f54nilgun * permission of the Apache Software Foundation.
e609c337f729875bc20e01096c7e610f45356f54nilgun * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
e609c337f729875bc20e01096c7e610f45356f54nilgun * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
e609c337f729875bc20e01096c7e610f45356f54nilgun * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
e609c337f729875bc20e01096c7e610f45356f54nilgun * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
b9bf3918f6eaf7747bcbfbd02792bcbe4a052784nilgun * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
e609c337f729875bc20e01096c7e610f45356f54nilgun * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
30471a4650391f57975f60bbb6e4a90be7b284bfhumbedooh * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
e609c337f729875bc20e01096c7e610f45356f54nilgun * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
e609c337f729875bc20e01096c7e610f45356f54nilgun * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
e609c337f729875bc20e01096c7e610f45356f54nilgun * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
e609c337f729875bc20e01096c7e610f45356f54nilgun * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
e609c337f729875bc20e01096c7e610f45356f54nilgun * SUCH DAMAGE.
e609c337f729875bc20e01096c7e610f45356f54nilgun * ====================================================================
e609c337f729875bc20e01096c7e610f45356f54nilgun * This software consists of voluntary contributions made by many
e609c337f729875bc20e01096c7e610f45356f54nilgun * individuals on behalf of the Apache Software Foundation. For more
e609c337f729875bc20e01096c7e610f45356f54nilgun * information on the Apache Software Foundation, please see
e609c337f729875bc20e01096c7e610f45356f54nilgun * Portions of this software are based upon public domain software
e609c337f729875bc20e01096c7e610f45356f54nilgun * originally written at the National Center for Supercomputing Applications,
e609c337f729875bc20e01096c7e610f45356f54nilgun * University of Illinois, Urbana-Champaign.
e609c337f729875bc20e01096c7e610f45356f54nilgun * Actual definitions of config globals
b9bf3918f6eaf7747bcbfbd02792bcbe4a052784nilgunint ap_threads_per_child=0; /* Worker threads per child */
e609c337f729875bc20e01096c7e610f45356f54nilgunstatic int workers_may_exit = 0;
e609c337f729875bc20e01096c7e610f45356f54nilgunstatic int num_listensocks = 0;
e609c337f729875bc20e01096c7e610f45356f54nilgun/* The structure used to pass unique initialization info to each thread */
e609c337f729875bc20e01096c7e610f45356f54nilguntypedef struct {
e609c337f729875bc20e01096c7e610f45356f54nilgun apr_pool_t *tpool; /* "pthread" would be confusing */
e609c337f729875bc20e01096c7e610f45356f54nilgun * The max child slot ever assigned, preserved across restarts. Necessary
e609c337f729875bc20e01096c7e610f45356f54nilgun * to deal with MaxClients changes across SIGWINCH restarts. We use this
e609c337f729875bc20e01096c7e610f45356f54nilgun * value to optimize routines that have to scan the entire scoreboard.
e609c337f729875bc20e01096c7e610f45356f54nilgun/* *Non*-shared http_main globals... */
e609c337f729875bc20e01096c7e610f45356f54nilgun/* one_process --- debugging mode variable; can be set from the command line
e609c337f729875bc20e01096c7e610f45356f54nilgun * with the -X flag. If set, this gets you the child_main loop running
e609c337f729875bc20e01096c7e610f45356f54nilgun * in the process which originally started up (no detach, no make_child),
e609c337f729875bc20e01096c7e610f45356f54nilgun * which is a pretty nice debugging environment. (You'll get a SIGHUP
e609c337f729875bc20e01096c7e610f45356f54nilgun * early in standalone_main; just continue through. This is the server
e609c337f729875bc20e01096c7e610f45356f54nilgun * trying to kill off any child processes which it might have lying
e609c337f729875bc20e01096c7e610f45356f54nilgun * around --- Apache doesn't keep track of their pids, it just sends
e609c337f729875bc20e01096c7e610f45356f54nilgun * SIGHUP to the process group, ignoring it in the root process.
e609c337f729875bc20e01096c7e610f45356f54nilgun * Continue through and you'll be fine.).
e609c337f729875bc20e01096c7e610f45356f54nilgunstatic int one_process = 0;
e609c337f729875bc20e01096c7e610f45356f54nilgunstatic apr_pool_t *pchild; /* Pool for httpd child stuff */
e609c337f729875bc20e01096c7e610f45356f54nilgununsigned int ap_my_pid; /* Linux getpid() doesn't work except in main
e609c337f729875bc20e01096c7e610f45356f54nilgun thread. Use this instead */
e609c337f729875bc20e01096c7e610f45356f54nilgun/* Keep track of the number of worker threads currently active */
e609c337f729875bc20e01096c7e610f45356f54nilgun/* Locks for accept serialization */
e609c337f729875bc20e01096c7e610f45356f54nilgunstatic const char *lock_fname;
e609c337f729875bc20e01096c7e610f45356f54nilgun/* a clean exit from a child with proper cleanup */
e609c337f729875bc20e01096c7e610f45356f54nilgunstatic void clean_child_exit(int code) __attribute__ ((noreturn));
e609c337f729875bc20e01096c7e610f45356f54nilgun/* handle all varieties of core dumping signals */
91f378b5a10f2d83820902ed10ba7967a3920c18nilgun /* At this point we've got sig blocked, because we're still inside
e609c337f729875bc20e01096c7e610f45356f54nilgun * the signal handler. When we leave the signal handler it will
e609c337f729875bc20e01096c7e610f45356f54nilgun * be unblocked, and we'll take the signal... and coredump or whatever
e609c337f729875bc20e01096c7e610f45356f54nilgun * is appropriate for this particular Unix. In addition the parent
e609c337f729875bc20e01096c7e610f45356f54nilgun * will see the real signal we received -- whereas if we called
e609c337f729875bc20e01096c7e610f45356f54nilgun * abort() here, the parent would only see SIGABRT.
e609c337f729875bc20e01096c7e610f45356f54nilgun/*****************************************************************
e609c337f729875bc20e01096c7e610f45356f54nilgun * Connection structures and accounting...
e609c337f729875bc20e01096c7e610f45356f54nilgun/* volatile just in case */
e609c337f729875bc20e01096c7e610f45356f54nilgunstatic int volatile shutdown_pending;
e609c337f729875bc20e01096c7e610f45356f54nilgunstatic int volatile restart_pending;
e609c337f729875bc20e01096c7e610f45356f54nilgunstatic int volatile is_graceful;
e609c337f729875bc20e01096c7e610f45356f54nilgun * ap_start_shutdown() and ap_start_restart(), below, are a first stab at
e609c337f729875bc20e01096c7e610f45356f54nilgun * functions to initiate shutdown or restart without relying on signals.
e609c337f729875bc20e01096c7e610f45356f54nilgun * Previously this was initiated in sig_term() and restart() signal handlers,
e609c337f729875bc20e01096c7e610f45356f54nilgun * but we want to be able to start a shutdown/restart from other sources --
e609c337f729875bc20e01096c7e610f45356f54nilgun * e.g. on Win32, from the service manager. Now the service manager can
e609c337f729875bc20e01096c7e610f45356f54nilgun * call ap_start_shutdown() or ap_start_restart() as appropiate. Note that
e609c337f729875bc20e01096c7e610f45356f54nilgun * these functions can also be called by the child processes, since global
e609c337f729875bc20e01096c7e610f45356f54nilgun * variables are no longer used to pass on the required action to the parent.
e609c337f729875bc20e01096c7e610f45356f54nilgun * These should only be called from the parent process itself, since the
e609c337f729875bc20e01096c7e610f45356f54nilgun * parent process will use the shutdown_pending and restart_pending variables
e609c337f729875bc20e01096c7e610f45356f54nilgun * to determine whether to shutdown or restart. The child process should
e609c337f729875bc20e01096c7e610f45356f54nilgun * call signal_parent() directly to tell the parent to die -- this will
e609c337f729875bc20e01096c7e610f45356f54nilgun * cause neither of those variable to be set, which the parent will
e609c337f729875bc20e01096c7e610f45356f54nilgun * assume means something serious is wrong (which it will be, for the
e609c337f729875bc20e01096c7e610f45356f54nilgun * child to force an exit) and so do an exit anyway.
b9bf3918f6eaf7747bcbfbd02792bcbe4a052784nilgunstatic void ap_start_shutdown(void)
b9bf3918f6eaf7747bcbfbd02792bcbe4a052784nilgun /* Um, is this _probably_ not an error, if the user has
b9bf3918f6eaf7747bcbfbd02792bcbe4a052784nilgun * tried to do a shutdown twice quickly, so we won't
b9bf3918f6eaf7747bcbfbd02792bcbe4a052784nilgun * worry about reporting it.
b9bf3918f6eaf7747bcbfbd02792bcbe4a052784nilgun/* do a graceful restart if graceful == 1 */
b9bf3918f6eaf7747bcbfbd02792bcbe4a052784nilgun /* Probably not an error - don't bother reporting it */
b9bf3918f6eaf7747bcbfbd02792bcbe4a052784nilgun apr_kill_cleanup(pconf, NULL, ap_cleanup_shared_mem);
b9bf3918f6eaf7747bcbfbd02792bcbe4a052784nilgunstatic void set_signals(void)
b9bf3918f6eaf7747bcbfbd02792bcbe4a052784nilgun ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGSEGV)");
b9bf3918f6eaf7747bcbfbd02792bcbe4a052784nilgun ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGBUS)");
b9bf3918f6eaf7747bcbfbd02792bcbe4a052784nilgun ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGABORT)");
b9bf3918f6eaf7747bcbfbd02792bcbe4a052784nilgun ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGABRT)");
b9bf3918f6eaf7747bcbfbd02792bcbe4a052784nilgun ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGILL)");
b9bf3918f6eaf7747bcbfbd02792bcbe4a052784nilgun ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGTERM)");
b9bf3918f6eaf7747bcbfbd02792bcbe4a052784nilgun ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGINT)");
e609c337f729875bc20e01096c7e610f45356f54nilgun ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGXCPU)");
e609c337f729875bc20e01096c7e610f45356f54nilgun ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGXFSZ)");
e609c337f729875bc20e01096c7e610f45356f54nilgun ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGPIPE)");
e609c337f729875bc20e01096c7e610f45356f54nilgun /* we want to ignore HUPs and WINCH while we're busy processing one */
727872d18412fc021f03969b8641810d8896820bhumbedooh ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGHUP)");
727872d18412fc021f03969b8641810d8896820bhumbedooh ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGWINCH)");
0d0ba3a410038e179b695446bb149cce6264e0abnd#endif /* SIGBUS */
727872d18412fc021f03969b8641810d8896820bhumbedooh#endif /* SIGABORT */
0d0ba3a410038e179b695446bb149cce6264e0abnd#endif /* SIGABRT */
0d0ba3a410038e179b695446bb149cce6264e0abnd#endif /* SIGILL */
d229f940abfb2490dee17979e9a5ff31b7012eb5rbowen#endif /* SIGXCPU */
7fec19672a491661b2fe4b29f685bc7f4efa64d4nd#endif /* SIGXFSZ */
#ifdef SIGHUP
#ifdef SIGWINCH
#ifdef SIGPIPE
int ap_graceful_stop_signalled(void)
return is_graceful;
int csd;
static void check_pipe_of_death(void)
if (!workers_may_exit) {
char pipe_read_char;
for(n=0 ; n <= num_listensocks ; ++n)
if (workers_may_exit) break;
!= APR_SUCCESS) {
while (!workers_may_exit) {
if (workers_may_exit) break;
goto got_fd;
curr_pollfd++;
goto got_fd;
if (!workers_may_exit) {
!= APR_SUCCESS) {
!= APR_SUCCESS) {
if (worker_thread_count == 0) {
return NULL;
int signal_received;
pchild));
if (unixd_setup_child()) {
#ifdef SIGPROCMASK_SETS_THREAD_MASK
#ifdef PTHREAD_SETS_ERRNO
worker_thread_count = 0;
for (i=0; i < ap_threads_per_child; i++) {
#ifndef NO_THREADS
#ifdef PTHREAD_SETS_ERRNO
switch (signal_received) {
case SIGTERM:
case SIGINT:
int pid;
if (one_process) {
set_signals();
if (!pid) {
#ifdef AIX_BIND_PROCESSOR
#ifndef MAX_SPAWN_RATE
static int hold_off_on_exponential_spawning;
static void perform_idle_server_maintenance(void)
int idle_thread_count;
int free_length;
int last_non_dead;
int total_non_dead;
free_length = 0;
idle_thread_count = 0;
total_non_dead = 0;
for (i = 0; i < ap_daemons_limit; ++i) {
int any_dying_threads = 0;
int idle_thread_addition = 0;
for (j = 0; j < ap_threads_per_child; j++) {
++free_length;
if (!all_dead_threads) {
last_non_dead = i;
if (!any_dying_threads) {
if (free_length == 0) {
static int reported = 0;
if (!reported) {
"or Min/MaxSpareThreads), "
for (i = 0; i < free_length; ++i) {
int child_slot;
if (child_slot >= 0) {
for (i = 0; i < ap_threads_per_child; i++)
else if (is_graceful) {
else if (remaining_children_to_start) {
ap_server_conf = s;
ap_server_conf = s;
if (!is_graceful) {
set_signals();
if (!is_graceful) {
if (shutdown_pending) {
if (one_process) {
if (is_graceful) {
for (i = 0; i < ap_daemons_limit;) {
for (i = 0; i < ap_daemons_limit; ++i) {
for (j = 0; j < ap_threads_per_child; j++) {
if (!is_graceful) {
static int restart_num = 0;
int no_detach = 0;
is_graceful = 0;
apr_detach();
ap_extended_status = 0;
one_process = 0;
return err;
return NULL;
const char *arg)
return err;
return NULL;
return err;
return NULL;
const char *arg)
return err;
return NULL;
const char *arg)
return err;
if (min_spare_threads <= 0) {
return NULL;
const char *arg)
return err;
return NULL;
const char *arg)
return err;
ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, "WARNING: Require MaxClients > 0, setting to 1");
return NULL;
const char *arg)
return err;
return NULL;
const char *arg)
return err;
return NULL;
const char *arg)
const char *fname;
return err;
return NULL;
{ NULL }