mpmt_beos.c revision 407cde44becba3694e7c3d81ac99b5d86f4b03a9
a530dde7009b0a808300c420def741354a4d13d2Martin Kühl/* ====================================================================
a530dde7009b0a808300c420def741354a4d13d2Martin Kühl * Copyright (c) 1995-1999 The Apache Group. All rights reserved.
a530dde7009b0a808300c420def741354a4d13d2Martin Kühl *
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 * are met:
a530dde7009b0a808300c420def741354a4d13d2Martin Kühl *
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 *
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.
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco *
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 *
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 *
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.
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco *
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 *
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 * ====================================================================
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 *
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
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 */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco#define CORE_PRIVATE
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco#include "apr_portable.h"
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco#include "httpd.h"
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco#include "http_main.h"
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco#include "http_log.h"
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco#include "http_config.h" /* for read_config */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco#include "http_core.h" /* for get_remote_host */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco#include "http_connection.h"
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco#include "ap_mpm.h"
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco#include "beosd.h"
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco#include "iol_socket.h"
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco#include "ap_listen.h"
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco#include "scoreboard.h"
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco#include "acceptlock.h"
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco#include "mutex.h"
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco#include "poll.h"
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
7474965b2e6323002c96c0b39a59843cde201870Adrián Riesco/*
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * Actual definitions of config globals
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescoint ap_threads_per_child=0; /* Worker threads per child */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescoint ap_max_requests_per_child=0;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescostatic char *ap_pid_fname=NULL;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescostatic char *ap_scoreboard_fname=NULL;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescostatic int ap_daemons_to_start=0;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescostatic int min_spare_threads=0;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescostatic int max_spare_threads=0;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescostatic int ap_daemons_limit=0;
7474965b2e6323002c96c0b39a59843cde201870Adrián Riescostatic time_t ap_restart_time=0;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián RiescoAPI_VAR_EXPORT int ap_extended_status = 0;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescostatic int workers_may_exit = 0;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescostatic int requests_this_child;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescostatic int num_listenfds = 0;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescostatic struct pollfd *listenfds;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco/* The structure used to pass unique initialization info to each thread */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescotypedef struct {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco int pid;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco thread_id tid;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco int sd;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_context_t *tpool; /* "pthread" would be confusing */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco} proc_info;
7474965b2e6323002c96c0b39a59843cde201870Adrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco#define SERVER_DEAD 0
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco#define SERVER_DYING 1
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco#define SERVER_ALIVE 2
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescostatic struct {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco pid_t pid;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco unsigned char status;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco} child_table[HARD_SERVER_LIMIT];
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco#if 0
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco#define SAFE_ACCEPT(stmt) do {if (ap_listeners->next != NULL) {stmt;}} while (0)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco#else
7474965b2e6323002c96c0b39a59843cde201870Adrián Riesco#define SAFE_ACCEPT(stmt) do {stmt;} while (0)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco#endif
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco/*
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 */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescoint max_daemons_limit = -1;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescostatic char ap_coredump_dir[MAX_STRING_LEN];
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescoport_id port_of_death;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco/* *Non*-shared http_main globals... */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescostatic server_rec *server_conf;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
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 Riesco */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescostatic int one_process = 0;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco#ifdef DEBUG_SIGSTOP
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riescoint raise_sigstop_flags;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco#endif
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco#ifdef HAS_OTHER_CHILD
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;
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riescostruct other_child_rec {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco other_child_rec *next;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco int pid;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco void (*maintenance) (int, void *, ap_wait_t);
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco void *data;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco int write_fd;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco};
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescostatic other_child_rec *other_children;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco#endif
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco
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 Riesco
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 */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescostatic int worker_thread_count;
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riescostatic be_mutex_t worker_thread_count_mutex;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
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 Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián RiescoAPI_EXPORT(const server_rec *) ap_get_server_conf(void)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco{
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco return (server_conf);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco}
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián RiescoAPI_EXPORT(int) ap_get_max_daemons(void)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco{
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco return max_daemons_limit;
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco}
7fc57d0f02d0fec1192376ccebe2be0224cb9a55Adrián Riesco
7fc57d0f02d0fec1192376ccebe2be0224cb9a55Adrián Riesco/* a clean exit from a child with proper cleanup
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco static void clean_child_exit(int code) __attribute__ ((noreturn)); */
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riescovoid clean_child_exit(int code)
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco{
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco if (pchild) {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_destroy_pool(pchild);
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco }
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco exit(code);
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco}
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco/*****************************************************************
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco * dealing with other children
3f8cdebaede9921402318d525b57a9af8f9279d3Adrián Riesco */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco#ifdef HAS_OTHER_CHILD
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián RiescoAPI_EXPORT(void) ap_register_other_child(int pid,
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco void (*maintenance) (int reason, void *, ap_wait_t status),
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco void *data, int write_fd)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco{
fe5611d78ea0648e8719cb004a6a26e9a033429aAdrián Riesco other_child_rec *ocr;
fe5611d78ea0648e8719cb004a6a26e9a033429aAdrián Riesco
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco ocr = ap_palloc(pconf, sizeof(*ocr));
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco ocr->pid = pid;
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco ocr->maintenance = maintenance;
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco ocr->data = data;
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco ocr->write_fd = write_fd;
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco ocr->next = other_children;
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco other_children = ocr;
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco}
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco
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 Riesco */
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián RiescoAPI_EXPORT(void) ap_unregister_other_child(void *data)
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco{
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco other_child_rec **pocr, *nocr;
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco for (pocr = &other_children; *pocr; pocr = &(*pocr)->next) {
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco if ((*pocr)->data == data) {
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco nocr = (*pocr)->next;
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco (*(*pocr)->maintenance) (OC_REASON_UNREGISTER, (*pocr)->data, -1);
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco *pocr = nocr;
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco /* XXX: um, well we've just wasted some space in pconf ? */
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco return;
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco }
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco }
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco}
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco
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)
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco{
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco return;
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco#if 0
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco fd_set writable_fds;
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco int fd_max;
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco other_child_rec *ocr, *nocr;
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco struct timeval tv;
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco int rc;
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco if (other_children == NULL)
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco return;
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco fd_max = 0;
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco FD_ZERO(&writable_fds);
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco do {
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco for (ocr = other_children; ocr; ocr = ocr->next) {
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco if (ocr->write_fd == -1)
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco continue;
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco FD_SET(ocr->write_fd, &writable_fds);
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco if (ocr->write_fd > fd_max) {
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco fd_max = ocr->write_fd;
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco }
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco }
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco if (fd_max == 0)
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco return;
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco tv.tv_sec = 0;
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco tv.tv_usec = 0;
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco rc = ap_select(fd_max + 1, NULL, &writable_fds, NULL, &tv);
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco } while (rc == -1 && errno == EINTR);
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco if (rc == -1) {
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",
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco "could not probe writable fds", server_conf);
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco return;
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco }
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco if (rc == 0)
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco return;
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco for (ocr = other_children; ocr; ocr = nocr) {
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco nocr = ocr->next;
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco if (ocr->write_fd == -1)
fe5611d78ea0648e8719cb004a6a26e9a033429aAdrián Riesco continue;
fe5611d78ea0648e8719cb004a6a26e9a033429aAdrián Riesco if (FD_ISSET(ocr->write_fd, &writable_fds))
fe5611d78ea0648e8719cb004a6a26e9a033429aAdrián Riesco continue;
fe5611d78ea0648e8719cb004a6a26e9a033429aAdrián Riesco (*ocr->maintenance) (OC_REASON_UNWRITABLE, ocr->data, -1);
fe5611d78ea0648e8719cb004a6a26e9a033429aAdrián Riesco }
fe5611d78ea0648e8719cb004a6a26e9a033429aAdrián Riesco#endif
fe5611d78ea0648e8719cb004a6a26e9a033429aAdrián Riesco}
fe5611d78ea0648e8719cb004a6a26e9a033429aAdrián Riesco
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)
fe5611d78ea0648e8719cb004a6a26e9a033429aAdrián Riesco{
fe5611d78ea0648e8719cb004a6a26e9a033429aAdrián Riesco other_child_rec *ocr, *nocr;
fe5611d78ea0648e8719cb004a6a26e9a033429aAdrián Riesco
fe5611d78ea0648e8719cb004a6a26e9a033429aAdrián Riesco for (ocr = other_children; ocr; ocr = nocr) {
fe5611d78ea0648e8719cb004a6a26e9a033429aAdrián Riesco nocr = ocr->next;
fe5611d78ea0648e8719cb004a6a26e9a033429aAdrián Riesco if (ocr->pid != pid)
fe5611d78ea0648e8719cb004a6a26e9a033429aAdrián Riesco continue;
fe5611d78ea0648e8719cb004a6a26e9a033429aAdrián Riesco ocr->pid = -1;
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco (*ocr->maintenance) (OC_REASON_DEATH, ocr->data, status);
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco return 0;
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco }
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco return -1;
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco}
7fc57d0f02d0fec1192376ccebe2be0224cb9a55Adrián Riesco#endif
7fc57d0f02d0fec1192376ccebe2be0224cb9a55Adrián Riesco
7fc57d0f02d0fec1192376ccebe2be0224cb9a55Adrián Riescostatic void reclaim_child_processes(int terminate)
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco{
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco int i, status;
7fc57d0f02d0fec1192376ccebe2be0224cb9a55Adrián Riesco long int waittime = 1024 * 16; /* in usecs */
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco struct timeval tv;
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco int waitret, tries;
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco int not_dead_yet;
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco#ifdef HAS_OTHER_CHILD
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco other_child_rec *ocr, *nocr;
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco#endif
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco
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.
7fc57d0f02d0fec1192376ccebe2be0224cb9a55Adrián Riesco */
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco tv.tv_sec = waittime / 1000000;
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco tv.tv_usec = waittime % 1000000;
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco waittime = waittime * 4;
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco ap_select(0, NULL, NULL, NULL, &tv);
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco /* now see who is done */
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco not_dead_yet = 0;
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco for (i = 0; i < max_daemons_limit; ++i) {
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco int pid;
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco if (child_table[i].status == SERVER_DEAD)
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco continue;
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco pid = child_table[i].pid;
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco waitret = waitpid(pid, &status, WNOHANG);
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco if (waitret == pid || waitret == -1) {
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco child_table[i].status = SERVER_DEAD;
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco continue;
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco }
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco ++not_dead_yet;
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco switch (tries) {
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco case 1: /* 16ms */
7fc57d0f02d0fec1192376ccebe2be0224cb9a55Adrián Riesco case 2: /* 82ms */
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco break;
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco case 3: /* 344ms */
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco case 4: /* 16ms */
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco case 5: /* 82ms */
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco case 6: /* 344ms */
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco case 7: /* 1.4sec */
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco /* ok, now it's being annoying */
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING,
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco errno, server_conf,
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco "child process %d still did not exit, sending a SIGTERM",
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco pid);
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco kill(pid, SIGTERM);
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco break;
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco case 8: /* 6 sec */
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",
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco pid);
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco kill(pid, SIGKILL);
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco break;
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco case 9: /* 14 sec */
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.
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco */
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, "
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco "attempting to continue anyway", pid);
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco break;
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco }
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco }
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco#ifdef HAS_OTHER_CHILD
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco for (ocr = other_children; ocr; ocr = nocr) {
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco nocr = ocr->next;
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco if (ocr->pid == -1)
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco continue;
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco waitret = waitpid(ocr->pid, &status, WNOHANG);
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco if (waitret == ocr->pid) {
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco ocr->pid = -1;
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco (*ocr->maintenance) (OC_REASON_DEATH, ocr->data, status);
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco }
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco else if (waitret == 0) {
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco (*ocr->maintenance) (OC_REASON_RESTART, ocr->data, -1);
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco ++not_dead_yet;
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco }
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco else if (waitret == -1) {
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco /* uh what the heck? they didn't call unregister? */
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco ocr->pid = -1;
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco (*ocr->maintenance) (OC_REASON_LOST, ocr->data, -1);
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco }
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco }
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco#endif
7fc57d0f02d0fec1192376ccebe2be0224cb9a55Adrián Riesco if (!not_dead_yet) {
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco /* nothing left to wait for */
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco break;
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco }
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco }
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco}
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco/* Finally, this routine is used by the caretaker process to wait for
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco * a while...
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco */
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco/* number of calls to wait_or_timeout between writable probes */
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco#ifndef INTERVAL_OF_WRITABLE_PROBES
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco#define INTERVAL_OF_WRITABLE_PROBES 10
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco#endif
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riescostatic int wait_or_timeout_counter;
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riescostatic int wait_or_timeout(ap_wait_t *status)
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco{
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco struct timeval tv;
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco int ret;
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco ++wait_or_timeout_counter;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (wait_or_timeout_counter == INTERVAL_OF_WRITABLE_PROBES) {
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco wait_or_timeout_counter = 0;
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco#ifdef HAS_OTHER_CHILD
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco probe_writable_fds();
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco#endif
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco }
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ret = waitpid(-1, status, WNOHANG);
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco if (ret == -1 && errno == EINTR) {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco return -1;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco }
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco if (ret > 0) {
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco return ret;
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco }
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco tv.tv_sec = SCOREBOARD_MAINTENANCE_INTERVAL / 1000000;
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco tv.tv_usec = SCOREBOARD_MAINTENANCE_INTERVAL % 1000000;
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco ap_select(0, NULL, NULL, NULL, &tv);
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco return -1;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco}
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco/* handle all varieties of core dumping signals */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescostatic void sig_coredump(int sig)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco{
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco chdir(ap_coredump_dir);
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco signal(sig, SIG_DFL);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco kill(my_pid, sig);
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}
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
7474965b2e6323002c96c0b39a59843cde201870Adrián Riescostatic void just_die(int sig)
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco{
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco clean_child_exit(0);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco}
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco/*****************************************************************
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * Connection structures and accounting...
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
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;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco/*
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 *
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 */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescovoid ap_start_shutdown(void)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco{
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco if (shutdown_pending == 1) {
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.
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco return;
6b2e3d60f2e2c230c9637bf0701d7024d289764dAdrián Riesco }
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco shutdown_pending = 1;
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco}
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco/* do a graceful restart if graceful == 1 */
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riescovoid ap_start_restart(int graceful)
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco{
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (restart_pending == 1) {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* Probably not an error - don't bother reporting it */
7474965b2e6323002c96c0b39a59843cde201870Adrián Riesco return;
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco }
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco restart_pending = 1;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco is_graceful = graceful;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco}
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescostatic void sig_term(int sig)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco{
7474965b2e6323002c96c0b39a59843cde201870Adrián Riesco ap_start_shutdown();
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco}
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescostatic void restart(int sig)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco{
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_start_restart(sig == SIGWINCH);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco}
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescostatic void set_signals(void)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco{
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco struct sigaction sa;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco sigemptyset(&sa.sa_mask);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco sa.sa_flags = 0;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (!one_process) {
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco sa.sa_handler = sig_coredump;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (sigaction(SIGSEGV, &sa, NULL) < 0)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGSEGV)");
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (sigaction(SIGBUS, &sa, NULL) < 0)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGBUS)");
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (sigaction(SIGABRT, &sa, NULL) < 0)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGABRT)");
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (sigaction(SIGILL, &sa, NULL) < 0)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGILL)");
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco sa.sa_flags = 0;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco }
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco sa.sa_handler = sig_term;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (sigaction(SIGTERM, &sa, NULL) < 0)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGTERM)");
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (sigaction(SIGINT, &sa, NULL) < 0)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGINT)");
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco sa.sa_handler = SIG_IGN;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (sigaction(SIGPIPE, &sa, NULL) < 0)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGPIPE)");
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* we want to ignore HUPs and WINCH while we're busy processing one */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco sigaddset(&sa.sa_mask, SIGHUP);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco sigaddset(&sa.sa_mask, SIGWINCH);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco sa.sa_handler = restart;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (sigaction(SIGHUP, &sa, NULL) < 0)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGHUP)");
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (sigaction(SIGWINCH, &sa, NULL) < 0)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGWINCH)");
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco}
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescostatic void process_child_status(int pid, ap_wait_t status)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco{
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* Child died... if it died due to a fatal error,
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * we should simply bail out.
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if ((WIFEXITED(status)) &&
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco WEXITSTATUS(status) == APEXIT_CHILDFATAL) {
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!",
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco pid);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco exit(APEXIT_CHILDFATAL);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco }
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (WIFSIGNALED(status)) {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco switch (WTERMSIG(status)) {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco case SIGTERM:
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco case SIGHUP:
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco case SIGUSR1:
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco case SIGKILL:
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco break;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco default:
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco#ifdef SYS_SIGLIST
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco#ifdef WCOREDUMP
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco if (WCOREDUMP(status)) {
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE,
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco errno, server_conf,
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco "child pid %d exit signal %s (%d), "
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco "possible coredump in %s",
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco pid, (WTERMSIG(status) >= NumSIG) ? "" :
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco SYS_SIGLIST[WTERMSIG(status)], WTERMSIG(status),
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco ap_coredump_dir);
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco }
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco else {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco#endif
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE,
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco errno, server_conf,
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco "child pid %d exit signal %s (%d)", pid,
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco SYS_SIGLIST[WTERMSIG(status)], WTERMSIG(status));
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco#ifdef WCOREDUMP
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco }
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco#endif
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco#else
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE,
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco errno, server_conf,
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco "child pid %d exit signal %d",
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco pid, WTERMSIG(status));
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco#endif
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco }
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco }
3b1e33dd8d2de8301d7a31860dd1819bd3752718Adrián Riesco}
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescostatic int setup_listeners(server_rec *s)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco{
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_listen_rec *lr;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco int num_listeners = 0;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (ap_listen_open(s->process, s->port)) {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco return 0;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco }
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco for (lr = ap_listeners; lr; lr = lr->next) {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco num_listeners++;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco }
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco return num_listeners;
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco}
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco/*****************************************************************
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco * Here follows a long bunch of generic server bookkeeping stuff...
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco */
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco#define sock_disable_nagle(s) /* NOOP */
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescoint ap_graceful_stop_signalled(void)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco{
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* XXX - Does this really work? - Manoj */
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco return is_graceful;
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco}
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco/*****************************************************************
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco * Child process main loop.
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco */
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco
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{
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco BUFF *conn_io;
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco conn_rec *current_conn;
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco ap_iol *iol;
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco long conn_id = my_child_num * HARD_THREAD_LIMIT + my_thread_num;
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco int csd;
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco iol = beos_attach_socket(sock);
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco if (iol == NULL) {
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco if (errno == EBADF) {
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 "larger FD_SETSIZE", csd, FD_SETSIZE);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco }
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco else {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_log_error(APLOG_MARK, APLOG_WARNING, errno, NULL,
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco "error attaching to socket");
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco }
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_close_socket(sock);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco return;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco }
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco conn_io = ap_bcreate(p, B_RDWR);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_bpush_iol(conn_io, iol);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco current_conn = ap_new_apr_connection(p, server_conf, conn_io, sock,
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco conn_id);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_process_connection(current_conn);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco}
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescostatic int32 worker_thread(void * dummy)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco{
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco proc_info * ti = dummy;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco int process_slot = ti->pid;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco int thread_slot = ti->tid;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_context_t *tpool = ti->tpool;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco struct sockaddr sa_client;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_socket_t *csd = NULL;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_context_t *ptrans; /* Pool for per-transaction stuff */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_socket_t *sd = NULL;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco int srv;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco int curr_pollfd, last_pollfd = 0;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco int thesock;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco sigset_t sig_mask;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco free(ti);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* block the signals for this thread */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco sigfillset(&sig_mask);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco sigprocmask(SIG_BLOCK, &sig_mask, NULL);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_create_context(&ptrans, tpool);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco be_mutex_lock(&worker_thread_count_mutex);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco worker_thread_count++;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco be_mutex_unlock(&worker_thread_count_mutex);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* TODO: Switch to a system where threads reuse the results from earlier
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco poll calls - manoj */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco while (!workers_may_exit) {
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco workers_may_exit |= (ap_max_requests_per_child != 0) && (requests_this_child <= 0);
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco if (workers_may_exit) break;
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco SAFE_ACCEPT(intra_mutex_on(0));
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco if (workers_may_exit) {
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco SAFE_ACCEPT(intra_mutex_off(0));
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco break;
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco }
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco SAFE_ACCEPT(accept_mutex_on(0));
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco while (!workers_may_exit) {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco srv = poll(listenfds, num_listenfds + 1, -1);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (srv < 0) {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (errno == EINTR) {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco continue;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco }
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
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 *)
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco ap_get_server_conf(), "poll: (listen)");
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco workers_may_exit = 1;
0f77efdcc159eee5682aabf2b9a3c178c467b466Adrián Riesco }
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (workers_may_exit) break;
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (num_listenfds == 1) {
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco sd = ap_listeners->sd;
7474965b2e6323002c96c0b39a59843cde201870Adrián Riesco goto got_fd;
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco }
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco else {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* find a listener */
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco curr_pollfd = last_pollfd;
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco do {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco curr_pollfd++;
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco if (curr_pollfd > num_listenfds) {
7474965b2e6323002c96c0b39a59843cde201870Adrián Riesco curr_pollfd = 1;
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco }
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco /* XXX: Should we check for POLLERR? */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (listenfds[curr_pollfd].revents & POLLIN) {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco last_pollfd = curr_pollfd;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_put_os_sock(&sd, &listenfds[curr_pollfd].fd, tpool);
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco goto got_fd;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco }
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco } while (curr_pollfd != last_pollfd);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco }
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco }
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco got_fd:
7474965b2e6323002c96c0b39a59843cde201870Adrián Riesco if (!workers_may_exit) {
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco ap_accept(&csd, sd, ptrans);
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco SAFE_ACCEPT(accept_mutex_off(0));
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco SAFE_ACCEPT(intra_mutex_off(0));
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco process_socket(ptrans, csd, process_slot,
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco thread_slot);
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco requests_this_child--;
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco }
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco else {
7474965b2e6323002c96c0b39a59843cde201870Adrián Riesco SAFE_ACCEPT(accept_mutex_off(0));
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco SAFE_ACCEPT(intra_mutex_off(0));
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco break;
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco }
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_clear_pool(ptrans);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco }
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_destroy_pool(tpool);
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco be_mutex_lock(&worker_thread_count_mutex);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco worker_thread_count--;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (worker_thread_count == 0) {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* All the threads have exited, now finish the shutdown process
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * by signalling the sigwait thread */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco kill(my_pid, SIGTERM);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco }
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco be_mutex_unlock(&worker_thread_count_mutex);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco return (0);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco}
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescostatic int32 child_main(void * data)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco{
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco int child_num_arg = (int) data;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco sigset_t sig_mask;
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco thread_id thread;
7474965b2e6323002c96c0b39a59843cde201870Adrián Riesco int i;
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco int my_child_num = child_num_arg;
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco proc_info *my_info = NULL;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_listen_rec *lr;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco struct sigaction sa;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco int32 msg;
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco char buf;
7474965b2e6323002c96c0b39a59843cde201870Adrián Riesco
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco my_pid = getpid();
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco ap_create_context(&pchild, pconf);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco /*stuff to do before we switch id's, so we have permissions.*/
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco SAFE_ACCEPT(intra_mutex_init(pchild, 1));
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco SAFE_ACCEPT(accept_mutex_child_init(pchild));
1ed0071009c6fcf215aff70aaa1bf73be5324494Adrián Riesco
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco if (beosd_setup_child()) {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco clean_child_exit(APEXIT_CHILDFATAL);
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco }
1ed0071009c6fcf215aff70aaa1bf73be5324494Adrián Riesco
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco ap_child_init_hook(pchild, server_conf);
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco /*done with init critical section */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* All threads should mask signals out, accoring to sigwait(2) man page */
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco sigfillset(&sig_mask);
1ed0071009c6fcf215aff70aaa1bf73be5324494Adrián Riesco sigprocmask(SIG_BLOCK, &sig_mask, NULL);
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco requests_this_child = ap_max_requests_per_child;
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco
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 ap_get_os_sock(&listenfds[i].fd , lr->sd);
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco listenfds[i].events = POLLIN; /* should we add POLLPRI ?*/
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco listenfds[i].revents = 0;
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco }
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco /* Setup worker threads */
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco worker_thread_count = 0;
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco be_mutex_init(&worker_thread_count_mutex, NULL);
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco for (i=0; i < ap_threads_per_child; i++) {
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco my_info = (proc_info *)malloc(sizeof(proc_info));
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco if (my_info == NULL) {
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco ap_log_error(APLOG_MARK, APLOG_ALERT, errno, server_conf,
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco "malloc: out of memory");
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco clean_child_exit(APEXIT_CHILDFATAL);
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco }
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco my_info->pid = my_child_num;
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco my_info->tid = i;
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco my_info->sd = 0;
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco ap_create_context(&my_info->tpool, pchild);
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco /* We are creating threads right now */
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco if ((thread = spawn_thread(worker_thread, "httpd_worker_thread",
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco B_NORMAL_PRIORITY, my_info)) < B_NO_ERROR) {
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 sleep(10);
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco clean_child_exit(APEXIT_CHILDFATAL);
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco }
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco resume_thread(thread);
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco
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.
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco */
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco }
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco sigemptyset(&sa.sa_mask);
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco sa.sa_flags = 0;
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco sa.sa_handler = just_die;
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco sigaction(SIGTERM, &sa, NULL);
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco sigaction(SIGINT, &sa, NULL);
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco /* this blocks until it gets a message... */
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco read_port(port_of_death, &msg, &buf, 1);
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco return (0);
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco}
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riescostatic int make_child(server_rec *s, int slot, time_t now)
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco{
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco thread_id tid;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco if (slot + 1 > max_daemons_limit) {
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco max_daemons_limit = slot + 1;
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco }
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco if (one_process) {
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco set_signals();
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco child_table[slot].pid = getpid();
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco child_table[slot].status = SERVER_ALIVE;
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco //child_main(slot);
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco }
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco tid = spawn_thread(child_main, "httpd_child", B_NORMAL_PRIORITY,
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco (void*)slot);
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco if (tid < B_NO_ERROR) {
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco ap_log_error(APLOG_MARK, APLOG_ERR, errno, s,
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. */
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco sleep(10);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco return -1;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco }
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco resume_thread(tid);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco child_table[slot].pid = getpid();
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco child_table[slot].status = SERVER_ALIVE;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco return 0;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco}
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco/* start up a bunch of children */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescostatic void startup_children(int number_to_start)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco{
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco int i;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco for (i = 0; number_to_start && i < ap_daemons_limit; ++i) {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (child_table[i].status != SERVER_DEAD) {
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco continue;
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco }
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco if (make_child(server_conf, i, 0) < 0) {
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco break;
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco }
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco --number_to_start;
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco }
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco}
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco/*
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.
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco */
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riescostatic int spawn_rate = 1;
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco#ifndef MAX_SPAWN_RATE
7fc57d0f02d0fec1192376ccebe2be0224cb9a55Adrián Riesco#define MAX_SPAWN_RATE (32)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco#endif
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescostatic int hold_off_on_exponential_spawning;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescostatic void perform_idle_server_maintenance(void)
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco{
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco int i, j;
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco int idle_thread_count;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco time_t now = 0;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco int free_length;
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco int free_slots[MAX_SPAWN_RATE];
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco int last_non_dead;
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco int total_non_dead;
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco /* initialize the free_list */
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco free_length = 0;
d72e314a1952b4418fb1c98b17dbab0d16bba585Adrián Riesco
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco ap_check_signals();
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco for (i = 0; i < ap_daemons_limit; ++i) {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (child_table[i].status == SERVER_DEAD) {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (free_length < spawn_rate) {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco free_slots[free_length] = i;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ++free_length;
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco }
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco }
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco else {
27aad79faa0eec8d0e7dda32bca710db95bd2d0aAdrián Riesco last_non_dead = i;
7fc57d0f02d0fec1192376ccebe2be0224cb9a55Adrián Riesco }
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco if (i >= max_daemons_limit && free_length >= spawn_rate) {
7fc57d0f02d0fec1192376ccebe2be0224cb9a55Adrián Riesco break;
7fc57d0f02d0fec1192376ccebe2be0224cb9a55Adrián Riesco }
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco }
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco max_daemons_limit = last_non_dead + 1;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (free_length > 0) {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco for (i = 0; i < free_length; ++i) {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco make_child(server_conf, free_slots[i], now);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco }
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
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (hold_off_on_exponential_spawning) {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco --hold_off_on_exponential_spawning;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco } else if (spawn_rate < MAX_SPAWN_RATE) {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco spawn_rate *= 2;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco }
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco } else {
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco spawn_rate = 1;
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco }
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco}
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riescostatic void server_main_loop(int remaining_children_to_start)
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco{
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco int child_slot;
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco ap_wait_t status;
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco int pid;
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco int i;
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco while (!restart_pending && !shutdown_pending) {
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco pid = wait_or_timeout(&status);
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco if (pid >= 0) {
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco process_child_status(pid, status);
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco /* non-fatal death... note that it's gone in the scoreboard. */
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco child_slot = -1;
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco for (i = 0; i < max_daemons_limit; ++i) {
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco if (child_table[i].pid == pid) {
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco int j;
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco child_slot = 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 }
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco break;
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco }
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco }
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco if (child_slot >= 0) {
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco child_table[child_slot].status = SERVER_DEAD;
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco
9bc11d5fe23b8f0c3b61b03d7453f7a29c74666dAdrián Riesco if (remaining_children_to_start
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco && child_slot < ap_daemons_limit) {
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco /* we're still doing a 1-for-1 replacement of dead
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco * children with new children
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco */
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco make_child(server_conf, child_slot, time(NULL));
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco --remaining_children_to_start;
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco }
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco#ifdef HAS_OTHER_CHILD
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco }
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco else if (reap_other_child(pid, status) == 0) {
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco /* handled */
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco#endif
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco }
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco else if (is_graceful) {
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 * child.
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco */
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, errno, server_conf,
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco "long lost child came home! (pid %d)", pid);
172f4dfb4b858440fab545bac00d3ec4abd0cbe4Adrián Riesco }
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 */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco continue;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco }
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco else if (remaining_children_to_start) {
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 */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco startup_children(remaining_children_to_start);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco remaining_children_to_start = 0;
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 Riesco */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco continue;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco }
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco perform_idle_server_maintenance();
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco }
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco}
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riescoint ap_mpm_run(ap_context_t *_pconf, ap_context_t *plog, server_rec *s)
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco{
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco int remaining_children_to_start;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco pconf = _pconf;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco server_conf = s;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco port_of_death = create_port(1, "httpd_port_of_death");
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
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 return 1;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco }
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_log_pid(pconf, ap_pid_fname);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco SAFE_ACCEPT(accept_mutex_init(pconf, 1));
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (!is_graceful) {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco reinit_scoreboard(pconf);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco }
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco set_signals();
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
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 */
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 }
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (!is_graceful) {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco startup_children(remaining_children_to_start);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco remaining_children_to_start = 0;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco }
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco else {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* give the system some time to recover before kicking into
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * exponential mode */
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco hold_off_on_exponential_spawning = 10;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco }
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
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_get_server_version());
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, errno, server_conf,
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco "Server built: %s", ap_get_server_built());
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco restart_pending = shutdown_pending = 0;
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco server_main_loop(remaining_children_to_start);
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco if (shutdown_pending) {
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco /* Time to gracefully shut down:
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco * Kill child processes, tell them to call child_exit, etc...
5318901bb69bf247e0f341312c800ba4ea87e46bAdrián Riesco */
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco if (ap_killpg(getpgrp(), SIGTERM) < 0) {
aea9000fc94442cbfc92596f4264473c0fce51e4Adrián Riesco ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf,
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco "killpg SIGTERM");
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco }
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco reclaim_child_processes(1); /* Start with SIGTERM */
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco /* cleanup pid file on normal shutdown */
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco {
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco const char *pidfile = NULL;
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco pidfile = ap_server_root_relative (pconf, ap_pid_fname);
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco if ( pidfile != NULL && unlink(pidfile) == 0)
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO,
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco errno, server_conf,
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco "removed PID file %s (pid=%ld)",
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco pidfile, (long)getpid());
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco }
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, errno, server_conf,
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco "caught SIGTERM, shutting down");
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco
fecce42517d20490f893c4a9dee29b000e1653eaAdrián Riesco return 1;
7474965b2e6323002c96c0b39a59843cde201870Adrián Riesco }
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco /* we've been told to restart */
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco signal(SIGHUP, SIG_IGN);
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco if (one_process) {
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco /* not worth thinking about */
c1cf2f634a37116ff90e99ca710179a23115cbfbAdrián Riesco return 1;
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco }
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco if (is_graceful) {
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco int i, j;
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco char char_of_death = '!';
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco
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
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco /* give the children the signal to die */
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco for (i = 0; i < ap_daemons_limit;) {
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco if(child_table[i].status != SERVER_DEAD) {
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco if (write_port(port_of_death, 99, &char_of_death, 1) != B_OK) {
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco if (errno == EINTR) continue;
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf,
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco "write port_of_death");
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco }
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco }
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco i++;
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco }
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco
223be434693e8c97e2522ac19155a284b3536035Adrián Riesco }
b3a8ae62887130fd41b91bf2ea1fd66360bd3c29Adrián Riesco else {
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 */
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco if (ap_killpg(getpgrp(), SIGTERM) < 0) {
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf,
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco "killpg SIGTERM");
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco }
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");
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco }
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco if (!is_graceful) {
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco ap_restart_time = time(NULL);
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco }
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco delete_port(port_of_death);
b9840e4ee6fda6e42fa4ee9f337482ccc4839a39Adrián Riesco return 0;
7474965b2e6323002c96c0b39a59843cde201870Adrián Riesco}
7474965b2e6323002c96c0b39a59843cde201870Adrián Riesco
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;
one_process = !!getenv("ONE_PROCESS");
/* sigh, want this only the second time around */
if (restart_num++ == 1) {
is_graceful = 0;
if (!one_process) {
beosd_detach();
}
my_pid = getpid();
}
beosd_pre_config();
ap_listen_pre_config();
ap_daemons_to_start = DEFAULT_START_DAEMON;
min_spare_threads = DEFAULT_MIN_FREE_DAEMON * DEFAULT_THREADS_PER_CHILD;
max_spare_threads = DEFAULT_MAX_FREE_DAEMON * DEFAULT_THREADS_PER_CHILD;
ap_daemons_limit = HARD_SERVER_LIMIT;
ap_threads_per_child = DEFAULT_THREADS_PER_CHILD;
ap_pid_fname = DEFAULT_PIDLOG;
ap_scoreboard_fname = DEFAULT_SCOREBOARD;
ap_max_requests_per_child = DEFAULT_MAX_REQUESTS_PER_CHILD;
ap_mpmt_beos_set_maintain_connection_status(1);
ap_cpystrn(ap_coredump_dir, ap_server_root, sizeof(ap_coredump_dir));
}
static void mpmt_beos_hooks(void)
{
ap_hook_pre_config(mpmt_beos_pre_config,NULL,NULL,HOOK_MIDDLE);
INIT_SIGLIST()
one_process = 0;
}
static const char *set_pidfile(cmd_parms *cmd, void *dummy, char *arg)
{
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
if (err != NULL) {
return err;
}
if (cmd->server->is_virtual) {
return "PidFile directive not allowed in <VirtualHost>";
}
ap_pid_fname = arg;
return NULL;
}
static const char *set_scoreboard(cmd_parms *cmd, void *dummy, char *arg)
{
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
if (err != NULL) {
return err;
}
ap_scoreboard_fname = arg;
return NULL;
}
static const char *set_daemons_to_start(cmd_parms *cmd, void *dummy, char *arg)
{
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
if (err != NULL) {
return err;
}
ap_daemons_to_start = atoi(arg);
return NULL;
}
static const char *set_min_spare_threads(cmd_parms *cmd, void *dummy, char *arg)
{
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
if (err != NULL) {
return err;
}
min_spare_threads = atoi(arg);
if (min_spare_threads <= 0) {
ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
"WARNING: detected MinSpareThreads set to non-positive.");
ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
"Resetting to 1 to avoid almost certain Apache failure.");
ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
"Please read the documentation.");
min_spare_threads = 1;
}
return NULL;
}
static const char *set_max_spare_threads(cmd_parms *cmd, void *dummy, char *arg)
{
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
if (err != NULL) {
return err;
}
max_spare_threads = atoi(arg);
return NULL;
}
static const char *set_server_limit (cmd_parms *cmd, void *dummy, char *arg)
{
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
if (err != NULL) {
return err;
}
ap_daemons_limit = atoi(arg);
if (ap_daemons_limit > HARD_SERVER_LIMIT) {
ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
"WARNING: MaxClients of %d exceeds compile time limit "
"of %d servers,", ap_daemons_limit, HARD_SERVER_LIMIT);
ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
" lowering MaxClients to %d. To increase, please "
"see the", HARD_SERVER_LIMIT);
ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
" HARD_SERVER_LIMIT define in src/include/httpd.h.");
ap_daemons_limit = HARD_SERVER_LIMIT;
}
else if (ap_daemons_limit < 1) {
ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
"WARNING: Require MaxClients > 0, setting to 1");
ap_daemons_limit = 1;
}
return NULL;
}
static const char *set_threads_per_child (cmd_parms *cmd, void *dummy, char *arg)
{
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
if (err != NULL) {
return err;
}
ap_threads_per_child = atoi(arg);
if (ap_threads_per_child > HARD_THREAD_LIMIT) {
ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
"WARNING: ThreadsPerChild of %d exceeds compile time"
"limit of %d threads,\n", ap_threads_per_child,
HARD_THREAD_LIMIT);
ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
" lowering ThreadsPerChild to %d. To increase, please"
"see the", HARD_THREAD_LIMIT);
ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
" HARD_THREAD_LIMIT define in src/include/httpd.h.");
}
else if (ap_threads_per_child < 1) {
ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
"WARNING: Require ThreadsPerChild > 0, setting to 1");
ap_threads_per_child = 1;
}
return NULL;
}
static const char *set_max_requests(cmd_parms *cmd, void *dummy, char *arg)
{
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
if (err != NULL) {
return err;
}
ap_max_requests_per_child = atoi(arg);
return NULL;
}
static const char *set_maintain_connection_status(cmd_parms *cmd,
core_dir_config *d, int arg)
{
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
if (err != NULL) {
return err;
}
ap_mpmt_beos_set_maintain_connection_status(arg != 0);
return NULL;
}
static const char *set_coredumpdir (cmd_parms *cmd, void *dummy, char *arg)
{
struct stat finfo;
const char *fname;
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
if (err != NULL) {
return err;
}
fname = ap_server_root_relative(cmd->pool, arg);
if ((stat(fname, &finfo) == -1) || !S_ISDIR(finfo.st_mode)) {
return ap_pstrcat(cmd->pool, "CoreDumpDirectory ", fname,
" does not exist or is not a directory", NULL);
}
ap_cpystrn(ap_coredump_dir, fname, sizeof(ap_coredump_dir));
return NULL;
}
struct ap_thread_mutex {
be_mutex_t mutex;
};
API_EXPORT(ap_thread_mutex *) ap_thread_mutex_new(void)
{
ap_thread_mutex *mtx;
mtx = malloc(sizeof(ap_thread_mutex));
be_mutex_init(&(mtx->mutex), NULL);
return mtx;
}
API_EXPORT(void) ap_thread_mutex_lock(ap_thread_mutex *mtx)
{
/* Ignoring error conditions here. :( */
be_mutex_lock(&(mtx->mutex));
}
API_EXPORT(void) ap_thread_mutex_unlock(ap_thread_mutex *mtx)
{
/* Here too. */
be_mutex_unlock(&(mtx->mutex));
}
API_EXPORT(void) ap_thread_mutex_destroy(ap_thread_mutex *mtx)
{
/* Here too. */
be_mutex_destroy(&(mtx->mutex));
free(mtx);
}
static const command_rec mpmt_beos_cmds[] = {
UNIX_DAEMON_COMMANDS
LISTEN_COMMANDS
{ "PidFile", set_pidfile, NULL, RSRC_CONF, TAKE1,
"A file for logging the server process ID"},
{ "ScoreBoardFile", set_scoreboard, NULL, RSRC_CONF, TAKE1,
"A file for Apache to maintain runtime process management information"},
{ "StartServers", set_daemons_to_start, NULL, RSRC_CONF, TAKE1,
"Number of child processes launched at server startup" },
{ "MinSpareThreads", set_min_spare_threads, NULL, RSRC_CONF, TAKE1,
"Minimum number of idle children, to handle request spikes" },
{ "MaxSpareThreads", set_max_spare_threads, NULL, RSRC_CONF, TAKE1,
"Maximum number of idle children" },
{ "MaxClients", set_server_limit, NULL, RSRC_CONF, TAKE1,
"Maximum number of children alive at the same time" },
{ "ThreadsPerChild", set_threads_per_child, NULL, RSRC_CONF, TAKE1,
"Number of threads each child creates" },
{ "MaxRequestsPerChild", set_max_requests, NULL, RSRC_CONF, TAKE1,
"Maximum number of requests a particular child serves before dying." },
{ "ConnectionStatus", set_maintain_connection_status, NULL, RSRC_CONF, FLAG,
"Whether or not to maintain status information on current connections"},
{ "CoreDumpDirectory", set_coredumpdir, NULL, RSRC_CONF, TAKE1,
"The location of the directory Apache changes to before dumping core" },
{ NULL }
};
module MODULE_VAR_EXPORT mpm_mpmt_beos_module = {
STANDARD20_MODULE_STUFF,
NULL, /* create per-directory config structure */
NULL, /* merge per-directory config structures */
NULL, /* create per-server config structure */
NULL, /* merge per-server config structures */
mpmt_beos_cmds, /* command ap_table_t */
NULL, /* handlers */
mpmt_beos_hooks /* register_hooks */
};