mpmt_beos.c revision 407cde44becba3694e7c3d81ac99b5d86f4b03a9
a530dde7009b0a808300c420def741354a4d13d2Martin Kühl/* ====================================================================
a530dde7009b0a808300c420def741354a4d13d2Martin Kühl * Copyright (c) 1995-1999 The Apache Group. All rights reserved.
a530dde7009b0a808300c420def741354a4d13d2Martin Kühl * Redistribution and use in source and binary forms, with or without
a530dde7009b0a808300c420def741354a4d13d2Martin Kühl * modification, are permitted provided that the following conditions
a530dde7009b0a808300c420def741354a4d13d2Martin Kühl * 1. Redistributions of source code must retain the above copyright
a530dde7009b0a808300c420def741354a4d13d2Martin Kühl * notice, this list of conditions and the following disclaimer.
a530dde7009b0a808300c420def741354a4d13d2Martin Kühl * 2. Redistributions in binary form must reproduce the above copyright
a530dde7009b0a808300c420def741354a4d13d2Martin Kühl * notice, this list of conditions and the following disclaimer in
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco * the documentation and/or other materials provided with the
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco * distribution.
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * 3. All advertising materials mentioning features or use of this
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * software must display the following acknowledgment:
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco * "This product includes software developed by the Apache Group
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco * for use in the Apache HTTP server project (http://www.apache.org/)."
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco * 4. The names "Apache Server" and "Apache Group" must not be used to
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco * endorse or promote products derived from this software without
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco * prior written permission. For written permission, please contact
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * apache@apache.org.
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * 5. Products derived from this software may not be called "Apache"
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco * nor may "Apache" appear in their names without prior written
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco * permission of the Apache Group.
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * 6. Redistributions of any form whatsoever must retain the following
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * acknowledgment:
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco * "This product includes software developed by the Apache Group
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco * for use in the Apache HTTP server project (http://www.apache.org/)."
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco * OF THE POSSIBILITY OF SUCH DAMAGE.
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco * ====================================================================
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * This software consists of voluntary contributions made by many
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco * individuals on behalf of the Apache Group and was originally based
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco * on public domain software written at the National Center for
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * Supercomputing Applications, University of Illinois, Urbana-Champaign.
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * For more information on the Apache Group and the Apache HTTP server
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * project, please see <http://www.apache.org/>.
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco/* This module is effectivly mpmt_pthread much modified to
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * allow it work on BeOS. It's stable and works OK.
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco#include "http_core.h" /* for get_remote_host */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * Actual definitions of config globals
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescoint ap_threads_per_child=0; /* Worker threads per child */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco/* The structure used to pass unique initialization info to each thread */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescotypedef struct {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_context_t *tpool; /* "pthread" would be confusing */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescostatic struct {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco unsigned char status;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco#define SAFE_ACCEPT(stmt) do {if (ap_listeners->next != NULL) {stmt;}} while (0)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * The max child slot ever assigned, preserved across restarts. Necessary
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * to deal with MaxClients changes across SIGWINCH restarts. We use this
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * value to optimize routines that have to scan the entire scoreboard.
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco/* *Non*-shared http_main globals... */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco/* one_process --- debugging mode variable; can be set from the command line
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * with the -X flag. If set, this gets you the child_main loop running
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * in the process which originally started up (no detach, no make_child),
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * which is a pretty nice debugging environment. (You'll get a SIGHUP
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * early in standalone_main; just continue through. This is the server
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * trying to kill off any child processes which it might have lying
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * around --- Apache doesn't keep track of their pids, it just sends
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * SIGHUP to the process group, ignoring it in the root process.
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * Continue through and you'll be fine.).
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescostatic int one_process = 0;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco/* used to maintain list of children which aren't part of the scoreboard */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescotypedef struct other_child_rec other_child_rec;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescostatic ap_context_t *pconf; /* Pool for config stuff */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescostatic ap_context_t *pchild; /* Pool for httpd child stuff */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescostatic int my_pid; /* Linux getpid() doesn't work except in main thread. Use
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco this instead */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco/* Keep track of the number of worker threads currently active */
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco/* Global, alas, so http_core can talk to us */
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riescoenum server_token_type ap_server_tokens = SrvTk_FULL;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián RiescoAPI_EXPORT(const server_rec *) ap_get_server_conf(void)
7fc57d0f02d0fec1192376ccebe2be0224cb9a55Adrián Riesco/* a clean exit from a child with proper cleanup
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco static void clean_child_exit(int code) __attribute__ ((noreturn)); */
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco/*****************************************************************
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco * dealing with other children
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián RiescoAPI_EXPORT(void) ap_register_other_child(int pid,
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco void (*maintenance) (int reason, void *, ap_wait_t status),
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco/* note that since this can be called by a maintenance function while we're
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco * scanning the other_children list, all scanners should protect themself
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco * by loading ocr->next before calling any maintenance function.
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián RiescoAPI_EXPORT(void) ap_unregister_other_child(void *data)
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco for (pocr = &other_children; *pocr; pocr = &(*pocr)->next) {
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco (*(*pocr)->maintenance) (OC_REASON_UNREGISTER, (*pocr)->data, -1);
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco /* XXX: um, well we've just wasted some space in pconf ? */
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco/* test to ensure that the write_fds are all still writable, otherwise
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco * invoke the maintenance functions as appropriate */
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riescostatic void probe_writable_fds(void)
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco for (ocr = other_children; ocr; ocr = ocr->next) {
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco rc = ap_select(fd_max + 1, NULL, &writable_fds, NULL, &tv);
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco /* XXX: uhh this could be really bad, we could have a bad file
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco * descriptor due to a bug in one of the maintenance routines */
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco ap_log_unixerr("probe_writable_fds", "select",
fe5611d78ea0648e8719cb004a6a26e9a033429aAdrián Riesco (*ocr->maintenance) (OC_REASON_UNWRITABLE, ocr->data, -1);
fe5611d78ea0648e8719cb004a6a26e9a033429aAdrián Riesco/* possibly reap an other_child, return 0 if yes, -1 if not */
fe5611d78ea0648e8719cb004a6a26e9a033429aAdrián Riescostatic int reap_other_child(int pid, ap_wait_t status)
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco (*ocr->maintenance) (OC_REASON_DEATH, ocr->data, status);
7fc57d0f02d0fec1192376ccebe2be0224cb9a55Adrián Riescostatic void reclaim_child_processes(int terminate)
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco for (tries = terminate ? 4 : 1; tries <= 9; ++tries) {
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco /* don't want to hold up progress any more than
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco * necessary, but we need to allow children a few moments to exit.
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco * Set delay with an exponential backoff.
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco /* now see who is done */
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco for (i = 0; i < max_daemons_limit; ++i) {
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco /* ok, now it's being annoying */
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING,
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco "child process %d still did not exit, sending a SIGTERM",
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco /* die child scum */
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, errno, server_conf,
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco "child process %d still did not exit, sending a SIGKILL",
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco /* gave it our best shot, but alas... If this really
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco * is a child we are trying to kill and it really hasn't
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco * exited, we will likely fail to bind to the port
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco * after the restart.
7fc57d0f02d0fec1192376ccebe2be0224cb9a55Adrián Riesco ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, errno, server_conf,
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco "could not make child process %d exit, "
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco waitret = waitpid(ocr->pid, &status, WNOHANG);
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco (*ocr->maintenance) (OC_REASON_DEATH, ocr->data, status);
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco else if (waitret == 0) {
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco (*ocr->maintenance) (OC_REASON_RESTART, ocr->data, -1);
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco /* uh what the heck? they didn't call unregister? */
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco (*ocr->maintenance) (OC_REASON_LOST, ocr->data, -1);
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco /* nothing left to wait for */
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco/* Finally, this routine is used by the caretaker process to wait for
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco/* number of calls to wait_or_timeout between writable probes */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (wait_or_timeout_counter == INTERVAL_OF_WRITABLE_PROBES) {
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco tv.tv_sec = SCOREBOARD_MAINTENANCE_INTERVAL / 1000000;
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco tv.tv_usec = SCOREBOARD_MAINTENANCE_INTERVAL % 1000000;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco/* handle all varieties of core dumping signals */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* At this point we've got sig blocked, because we're still inside
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco * the signal handler. When we leave the signal handler it will
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco * be unblocked, and we'll take the signal... and coredump or whatever
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco * is appropriate for this particular Unix. In addition the parent
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * will see the real signal we received -- whereas if we called
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * abort() here, the parent would only see SIGABRT.
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco/*****************************************************************
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * Connection structures and accounting...
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco/* volatile just in case */
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riescostatic int volatile shutdown_pending;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescostatic int volatile restart_pending;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescostatic int volatile is_graceful;
7474965b2e6323002c96c0b39a59843cde201870Adrián Riesco * ap_start_shutdown() and ap_start_restart(), below, are a first stab at
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco * functions to initiate shutdown or restart without relying on signals.
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco * Previously this was initiated in sig_term() and restart() signal handlers,
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco * but we want to be able to start a shutdown/restart from other sources --
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco * e.g. on Win32, from the service manager. Now the service manager can
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * call ap_start_shutdown() or ap_start_restart() as appropiate. Note that
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco * these functions can also be called by the child processes, since global
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco * variables are no longer used to pass on the required action to the parent.
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * These should only be called from the parent process itself, since the
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * parent process will use the shutdown_pending and restart_pending variables
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * to determine whether to shutdown or restart. The child process should
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * call signal_parent() directly to tell the parent to die -- this will
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * cause neither of those variable to be set, which the parent will
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * assume means something serious is wrong (which it will be, for the
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * child to force an exit) and so do an exit anyway.
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* Um, is this _probably_ not an error, if the user has
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * tried to do a shutdown twice quickly, so we won't
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * worry about reporting it.
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco/* do a graceful restart if graceful == 1 */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* Probably not an error - don't bother reporting it */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescostatic void set_signals(void)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGSEGV)");
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGBUS)");
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGABRT)");
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGILL)");
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGTERM)");
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGINT)");
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGPIPE)");
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* we want to ignore HUPs and WINCH while we're busy processing one */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGHUP)");
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGWINCH)");
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescostatic void process_child_status(int pid, ap_wait_t status)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* Child died... if it died due to a fatal error,
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * we should simply bail out.
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_log_error(APLOG_MARK, APLOG_ALERT|APLOG_NOERRNO, errno, server_conf,
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco "Child %d returned a Fatal error... \n"
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco "Apache is exiting!",
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE,
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco "child pid %d exit signal %s (%d), "
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco "possible coredump in %s",
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco SYS_SIGLIST[WTERMSIG(status)], WTERMSIG(status),
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE,
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco SYS_SIGLIST[WTERMSIG(status)], WTERMSIG(status));
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE,
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco "child pid %d exit signal %d",
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco/*****************************************************************
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco * Here follows a long bunch of generic server bookkeeping stuff...
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* XXX - Does this really work? - Manoj */
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco/*****************************************************************
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco * Child process main loop.
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riescostatic void process_socket(ap_context_t *p, ap_socket_t *sock, int my_child_num, int my_thread_num)
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco long conn_id = my_child_num * HARD_THREAD_LIMIT + my_thread_num;
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, errno, NULL,
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco "filedescriptor (%u) larger than FD_SETSIZE (%u) "
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco "found, you probably need to rebuild Apache with a "
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_log_error(APLOG_MARK, APLOG_WARNING, errno, NULL,
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco "error attaching to socket");
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco current_conn = ap_new_apr_connection(p, server_conf, conn_io, sock,
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_context_t *ptrans; /* Pool for per-transaction stuff */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* block the signals for this thread */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* TODO: Switch to a system where threads reuse the results from earlier
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco poll calls - manoj */
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco workers_may_exit |= (ap_max_requests_per_child != 0) && (requests_this_child <= 0);
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco /* poll() will only return errors in catastrophic
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco * circumstances. Let's try exiting gracefully, for now. */
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco ap_log_error(APLOG_MARK, APLOG_ERR,errno, (const server_rec *)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* find a listener */
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco /* XXX: Should we check for POLLERR? */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (listenfds[curr_pollfd].revents & POLLIN) {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_put_os_sock(&sd, &listenfds[curr_pollfd].fd, tpool);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* All the threads have exited, now finish the shutdown process
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * by signalling the sigwait thread */
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco /*stuff to do before we switch id's, so we have permissions.*/
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco /*done with init critical section */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* All threads should mask signals out, accoring to sigwait(2) man page */
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco requests_this_child = ap_max_requests_per_child;
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco /* Set up the pollfd array */
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco listenfds = ap_palloc(pchild, sizeof(struct pollfd) * (num_listenfds));
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco for (lr = ap_listeners, i = 0; i < num_listenfds; lr = lr->next, ++i) {
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco listenfds[i].events = POLLIN; /* should we add POLLPRI ?*/
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco /* Setup worker threads */
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco be_mutex_init(&worker_thread_count_mutex, NULL);
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco for (i=0; i < ap_threads_per_child; i++) {
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco my_info = (proc_info *)malloc(sizeof(proc_info));
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco ap_log_error(APLOG_MARK, APLOG_ALERT, errno, server_conf,
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco "malloc: out of memory");
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco /* We are creating threads right now */
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco if ((thread = spawn_thread(worker_thread, "httpd_worker_thread",
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco ap_log_error(APLOG_MARK, APLOG_ALERT, errno, server_conf,
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco "spawn_thread: unable to create worker thread");
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco /* In case system resources are maxxed out, we don't want
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco Apache running away with the CPU trying to fork over and
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco over and over again if we exit. */
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco /* We let each thread update it's own scoreboard entry. This is done
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco * because it let's us deal with tid better.
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco /* this blocks until it gets a message... */
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riescostatic int make_child(server_rec *s, int slot, time_t now)
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco //child_main(slot);
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco tid = spawn_thread(child_main, "httpd_child", B_NORMAL_PRIORITY,
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco "spawn_thread: Unable to fork new process");
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco /* In case system resources are maxxed out, we don't want
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco Apache running away with the CPU trying to fork over and
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco over and over again. */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco/* start up a bunch of children */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescostatic void startup_children(int number_to_start)
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco for (i = 0; number_to_start && i < ap_daemons_limit; ++i) {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * spawn_rate is the number of children that will be spawned on the
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco * next maintenance cycle if there aren't enough idle servers. It is
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * doubled up to MAX_SPAWN_RATE, and reset only when a cycle goes by
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * without the need to spawn.
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescostatic void perform_idle_server_maintenance(void)
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco /* initialize the free_list */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco for (i = 0; i < ap_daemons_limit; ++i) {
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco if (i >= max_daemons_limit && free_length >= spawn_rate) {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco for (i = 0; i < free_length; ++i) {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* the next time around we want to spawn twice as many if this
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * wasn't good enough, but not if we've just done a graceful
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riescostatic void server_main_loop(int remaining_children_to_start)
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco while (!restart_pending && !shutdown_pending) {
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco /* non-fatal death... note that it's gone in the scoreboard. */
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco for (i = 0; i < max_daemons_limit; ++i) {
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco for (j = 0; j < HARD_THREAD_LIMIT; j++) {
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco ap_mpmt_beos_force_reset_connection_status(i * HARD_THREAD_LIMIT + j);
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco /* we're still doing a 1-for-1 replacement of dead
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco * children with new children
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco make_child(server_conf, child_slot, time(NULL));
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco else if (reap_other_child(pid, status) == 0) {
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco /* handled */
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco /* Great, we've probably just lost a slot in the
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco * scoreboard. Somehow we don't know about this
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, errno, server_conf,
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco /* Don't perform idle maintenance when a child dies,
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * only do it when there's a timeout. Remember only a
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * finite number of children can die, and it's pretty
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * pathological for a lot to die suddenly.
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* we hit a 1 second timeout in which none of the previous
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * generation of children needed to be reaped... so assume
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * they're all done, and pick up the slack if any is left.
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco startup_children(remaining_children_to_start);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* In any event we really shouldn't do the code below because
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * few of the servers we just started are in the IDLE state
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * yet, so we'd mistakenly create an extra server.
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescoint ap_mpm_run(ap_context_t *_pconf, ap_context_t *plog, server_rec *s)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco port_of_death = create_port(1, "httpd_port_of_death");
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if ((num_listenfds = setup_listeners(server_conf)) < 1) {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* XXX: hey, what's the right way for the mpm to indicate a fatal error? */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ALERT, errno, s,
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco "no listening sockets available, shutting down");
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* Don't thrash... */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (max_spare_threads < min_spare_threads + ap_threads_per_child)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco max_spare_threads = min_spare_threads + ap_threads_per_child;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* If we're doing a graceful_restart then we're going to see a lot
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * of children exiting immediately when we get into the main loop
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * below (because we just sent them SIGWINCH). This happens pretty
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * rapidly... and for each one that exits we'll start a new one until
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * we reach at least daemons_min_free. But we may be permitted to
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * start more than that, so we'll just keep track of how many we're
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * supposed to start up without the 1 second penalty between each fork.
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco remaining_children_to_start = ap_daemons_to_start;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (remaining_children_to_start > ap_daemons_limit) {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco remaining_children_to_start = ap_daemons_limit;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco startup_children(remaining_children_to_start);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* give the system some time to recover before kicking into
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * exponential mode */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, errno, server_conf,
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco "%s configured -- resuming normal operations",
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, errno, server_conf,
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco server_main_loop(remaining_children_to_start);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* Time to gracefully shut down:
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * Kill child processes, tell them to call child_exit, etc...
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf,
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco "killpg SIGTERM");
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco reclaim_child_processes(1); /* Start with SIGTERM */
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco /* cleanup pid file on normal shutdown */
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco pidfile = ap_server_root_relative (pconf, ap_pid_fname);
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO,
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco "removed PID file %s (pid=%ld)",
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, errno, server_conf,
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco "caught SIGTERM, shutting down");
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco /* we've been told to restart */
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco /* not worth thinking about */
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, errno, server_conf,
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco "SIGWINCH received. Doing graceful restart");
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco /* give the children the signal to die */
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco for (i = 0; i < ap_daemons_limit;) {
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco if (write_port(port_of_death, 99, &char_of_death, 1) != B_OK) {
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf,
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco "write port_of_death");
b3a8ae62887130fd41b91bf2ea1fd66360bd3c29Adrián Riesco /* Kill 'em all. Since the child acts the same on the parents SIGTERM
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco * and a SIGHUP, we may as well use the same signal, because some user
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco * pthreads are stealing signals from us left and right.
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf,
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco "killpg SIGTERM");
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco reclaim_child_processes(1); /* Start with SIGTERM */
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, errno, server_conf,
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco "SIGHUP received. Attempting to restart");
7474965b2e6323002c96c0b39a59843cde201870Adrián Riescostatic void mpmt_beos_pre_config(ap_context_t *pconf, ap_context_t *plog, ap_context_t *ptemp)
static int restart_num = 0;
is_graceful = 0;
if (!one_process) {
beosd_detach();
static void mpmt_beos_hooks(void)
one_process = 0;
return err;
return NULL;
return err;
return NULL;
return err;
return NULL;
return err;
if (min_spare_threads <= 0) {
return NULL;
return err;
return NULL;
return err;
return NULL;
return err;
return NULL;
return err;
return NULL;
return err;
return NULL;
const char *fname;
return err;
return NULL;
struct ap_thread_mutex {
return mtx;
{ NULL }