worker.c revision 622b198579318636577fd77c3fb899058c592dfd
359deb60c25147e91a69c227ace686654ea7f484Lennart Poettering/* ====================================================================
359deb60c25147e91a69c227ace686654ea7f484Lennart Poettering * The Apache Software License, Version 1.1
359deb60c25147e91a69c227ace686654ea7f484Lennart Poettering * Copyright (c) 2000-2002 The Apache Software Foundation. All rights
359deb60c25147e91a69c227ace686654ea7f484Lennart Poettering * Redistribution and use in source and binary forms, with or without
359deb60c25147e91a69c227ace686654ea7f484Lennart Poettering * modification, are permitted provided that the following conditions
359deb60c25147e91a69c227ace686654ea7f484Lennart Poettering * 1. Redistributions of source code must retain the above copyright
359deb60c25147e91a69c227ace686654ea7f484Lennart Poettering * notice, this list of conditions and the following disclaimer.
359deb60c25147e91a69c227ace686654ea7f484Lennart Poettering * 2. Redistributions in binary form must reproduce the above copyright
359deb60c25147e91a69c227ace686654ea7f484Lennart Poettering * notice, this list of conditions and the following disclaimer in
359deb60c25147e91a69c227ace686654ea7f484Lennart Poettering * the documentation and/or other materials provided with the
359deb60c25147e91a69c227ace686654ea7f484Lennart Poettering * distribution.
359deb60c25147e91a69c227ace686654ea7f484Lennart Poettering * 3. The end-user documentation included with the redistribution,
359deb60c25147e91a69c227ace686654ea7f484Lennart Poettering * if any, must include the following acknowledgment:
359deb60c25147e91a69c227ace686654ea7f484Lennart Poettering * "This product includes software developed by the
359deb60c25147e91a69c227ace686654ea7f484Lennart Poettering * Apache Software Foundation (http://www.apache.org/)."
359deb60c25147e91a69c227ace686654ea7f484Lennart Poettering * Alternately, this acknowledgment may appear in the software itself,
21ac6ff143cc8bebfbd1818af28e8c6f82cd5265Zbigniew Jędrzejewski-Szmek * if and wherever such third-party acknowledgments normally appear.
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * 4. The names "Apache" and "Apache Software Foundation" must
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * not be used to endorse or promote products derived from this
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * software without prior written permission. For written
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * permission, please contact apache@apache.org.
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * 5. Products derived from this software may not be called "Apache",
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * nor may "Apache" appear in their name, without prior written
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * permission of the Apache Software Foundation.
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * ====================================================================
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * This software consists of voluntary contributions made by many
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * individuals on behalf of the Apache Software Foundation. For more
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * information on the Apache Software Foundation, please see
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * Portions of this software are based upon public domain software
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * originally written at the National Center for Supercomputing Applications,
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * University of Illinois, Urbana-Champaign.
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek/* The purpose of this MPM is to fix the design flaws in the threaded
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * model. Because of the way that pthreads and mutex locks interact,
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * it is basically impossible to cleanly gracefully shutdown a child
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * process if multiple threads are all blocked in accept. This model
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * fixes those problems.
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek#include <sys/processor.h> /* for bindprocessor() */
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek#error The Worker MPM requires APR threads, but they are unavailable.
213cf5b1f27a077f1cf61a185d0bb7468c3d5380Lennart Poettering#include "http_config.h" /* for read_config */
213cf5b1f27a077f1cf61a185d0bb7468c3d5380Lennart Poettering#include "http_core.h" /* for get_remote_host */
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek#include <limits.h> /* for INT_MAX */
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek/* Limit on the total --- clients will be locked out if more servers than
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * this are needed. It is intended solely to keep the server from crashing
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * when things get out of hand.
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * We keep a hard maximum number of servers, for two reasons --- first off,
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * in case something goes seriously wrong, we want to stop the fork bomb
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * short of actually crashing the machine we're running on by filling some
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * kernel table. Secondly, it keeps the size of the scoreboard file small
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * enough that we can read the whole thing without worrying too much about
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek/* Admin can't tune ServerLimit beyond MAX_SERVER_LIMIT. We want
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * some sort of compile-time limit to help catch typos.
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek/* Limit on the threads per process. Clients will be locked out if more than
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * this * server_limit are needed.
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * We keep this for one reason it keeps the size of the scoreboard file small
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * enough that we can read the whole thing without worrying too much about
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek/* Admin can't tune ThreadLimit beyond MAX_THREAD_LIMIT. We want
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * some sort of compile-time limit to help catch typos.
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * Actual definitions of config globals
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekint ap_threads_per_child = 0; /* Worker threads per child */
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekstatic int ap_daemons_to_start = 0;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekstatic int min_spare_threads = 0;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekstatic int max_spare_threads = 0;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekstatic int server_limit = DEFAULT_SERVER_LIMIT;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekstatic int thread_limit = DEFAULT_THREAD_LIMIT;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekstatic int changed_limit_at_restart;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekstatic int start_thread_may_exit = 0;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekstatic int listener_may_exit = 0;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekstatic int resource_shortage = 0;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekstatic fd_queue_info_t *worker_queue_info;
2ca2a91cf1deba83825692f1ce06116d2aed2379Lennart Poettering/* The structure used to pass unique initialization info to each thread */
2ca2a91cf1deba83825692f1ce06116d2aed2379Lennart Poetteringtypedef struct {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek/* Structure used to pass information to the thread responsible for
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * creating the rest of the threads.
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek#define ID_FROM_CHILD_THREAD(c, t) ((c * thread_limit) + t)
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * The max child slot ever assigned, preserved across restarts. Necessary
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * to deal with MaxClients changes across AP_SIG_GRACEFUL restarts. We
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * use this value to optimize routines that have to scan the entire
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek/* *Non*-shared http_main globals... */
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek/* The worker MPM respects a couple of runtime flags that can aid
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * in debugging. Setting the -DNO_DETACH flag will prevent the root process
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * from detaching from its controlling terminal. Additionally, setting
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * the -DONE_PROCESS flag (which implies -DNO_DETACH) will get you the
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * child_main loop running in the process which originally started up.
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * This gives you a pretty nice debugging environment. (You'll get a SIGHUP
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * early in standalone_main; just continue through. This is the server
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * trying to kill off any child processes which it might have lying
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * around --- Apache doesn't keep track of their pids, it just sends
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * SIGHUP to the process group, ignoring it in the root process.
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * Continue through and you'll be fine.).
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekstatic apr_pool_t *pconf; /* Pool for config stuff */
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekstatic apr_pool_t *pchild; /* Pool for httpd child stuff */
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekstatic pid_t ap_my_pid; /* Linux getpid() doesn't work except in main
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek thread. Use this instead */
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekstatic apr_os_thread_t *listener_os_thread;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek/* Locks for accept serialization */
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekstatic apr_proc_mutex_t *accept_mutex;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek#ifdef SINGLE_LISTEN_UNSERIALIZED_ACCEPT
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek#define SAFE_ACCEPT(stmt) (ap_listeners->next ? (stmt) : APR_SUCCESS)
6ecb6cec66739d733e95302031998f517261380cZbigniew Jędrzejewski-Szmek/* The LISTENER_SIGNAL signal will be sent from the main thread to the
6ecb6cec66739d733e95302031998f517261380cZbigniew Jędrzejewski-Szmek * listener thread to wake it up for graceful termination (what a child
6ecb6cec66739d733e95302031998f517261380cZbigniew Jędrzejewski-Szmek * process from an old generation does when the admin does "apachectl
6ecb6cec66739d733e95302031998f517261380cZbigniew Jędrzejewski-Szmek * graceful"). This signal will be blocked in all threads of a child
6ecb6cec66739d733e95302031998f517261380cZbigniew Jędrzejewski-Szmek * process except for the listener thread.
6ecb6cec66739d733e95302031998f517261380cZbigniew Jędrzejewski-Szmek/* An array of socket descriptors in use by each thread used to
6ecb6cec66739d733e95302031998f517261380cZbigniew Jędrzejewski-Szmek * perform a non-graceful (forced) shutdown of the server. */
6ecb6cec66739d733e95302031998f517261380cZbigniew Jędrzejewski-Szmekstatic apr_socket_t **worker_sockets;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekstatic void close_worker_sockets(void)
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek for (i = 0; i < ap_threads_per_child; i++) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek apr_socket_close(worker_sockets[i]);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekstatic void wakeup_listener(void)
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek /* XXX there is an obscure path that this doesn't handle perfectly:
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * right after listener thread is created but before
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * listener_os_thread is set, the first worker thread hits an
6ecb6cec66739d733e95302031998f517261380cZbigniew Jędrzejewski-Szmek * error and starts graceful termination
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * we should just be able to "kill(ap_my_pid, LISTENER_SIGNAL)" on all
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * platforms and wake up the listener thread since it is the only thread
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * with SIGHUP unblocked, but that doesn't work on Linux
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek pthread_kill(*listener_os_thread, LISTENER_SIGNAL);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek kill(ap_my_pid, LISTENER_SIGNAL);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekstatic int terminate_mode = ST_INIT;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekstatic void signal_threads(int mode)
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek /* in case we weren't called from the listener thread, wake up the
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * listener thread
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek /* for ungraceful termination, let the workers exit now;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * for graceful termination, the listener thread will notify the
816f25e86ab690da6e408bc8d5b03dae9cc1b219Lennart Poettering * workers to exit once it has stopped accepting new connections
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek ap_queue_interrupt_all(worker_queue);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek ap_queue_info_term(worker_queue_info);
142c4ecaa9840714d49b40b1de407748b52f21d7Zbigniew Jędrzejewski-Szmek close_worker_sockets(); /* forcefully kill all current connections */
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-SzmekAP_DECLARE(apr_status_t) ap_mpm_query(int query_code, int *result)
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek case AP_MPMQ_HARD_LIMIT_DAEMONS:
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek case AP_MPMQ_HARD_LIMIT_THREADS:
142c4ecaa9840714d49b40b1de407748b52f21d7Zbigniew Jędrzejewski-Szmek case AP_MPMQ_MAX_REQUESTS_DAEMON:
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek *result = ap_max_requests_per_child;
142c4ecaa9840714d49b40b1de407748b52f21d7Zbigniew Jędrzejewski-Szmek/* a clean exit from a child with proper cleanup */
142c4ecaa9840714d49b40b1de407748b52f21d7Zbigniew Jędrzejewski-Szmekstatic void clean_child_exit(int code) __attribute__ ((noreturn));
142c4ecaa9840714d49b40b1de407748b52f21d7Zbigniew Jędrzejewski-Szmekstatic void clean_child_exit(int code)
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek/* handle all varieties of core dumping signals */
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekstatic void sig_coredump(int sig)
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek apr_filepath_set(ap_coredump_dir, pconf);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE,
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek "seg fault or similar nasty error detected "
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek "in the parent process");
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek /* XXX we can probably add some rudimentary cleanup code here,
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * like getting rid of the pid file. If any additional bad stuff
359deb60c25147e91a69c227ace686654ea7f484Lennart Poettering * happens, we are protected from recursive errors taking down the
359deb60c25147e91a69c227ace686654ea7f484Lennart Poettering * system since this function is no longer the signal handler GLA
clean_child_exit(0);
static int volatile shutdown_pending;
static int volatile restart_pending;
static int volatile is_graceful;
static volatile int child_fatal;
static void ap_start_shutdown(void)
static void set_signals(void)
#ifndef NO_USE_SIGACTION
if (!one_process) {
#if defined(SA_ONESHOT)
#ifdef SIGBUS
#ifdef SIGABORT
#ifdef SIGABRT
#ifdef SIGILL
#ifdef SIGINT
#ifdef SIGXCPU
#ifdef SIGXFSZ
#ifdef SIGPIPE
if (!one_process) {
#ifdef SIGBUS
#ifdef SIGABORT
#ifdef SIGABRT
#ifdef SIGILL
#ifdef SIGXCPU
#ifdef SIGXFSZ
#ifdef SIGHUP
#ifdef AP_SIG_GRACEFUL
#ifdef SIGPIPE
int ap_graceful_stop_signalled(void)
return listener_may_exit;
int csd;
if (current_conn) {
static void check_infinite_requests(void)
if (ap_max_requests_per_child) {
#if defined(SIGPROCMASK_SETS_THREAD_MASK)
if (requests_this_child <= 0) {
if (listener_may_exit) break;
!= APR_SUCCESS) {
if (listener_may_exit) {
while (!listener_may_exit) {
if (listener_may_exit) break;
goto got_fd;
if (!listener_may_exit) {
!= APR_SUCCESS) {
if (listener_may_exit) {
if (rv) {
!= APR_SUCCESS) {
return NULL;
/* XXX For ungraceful termination/restart, we definitely don't want to
while (!workers_may_exit) {
if (workers_may_exit) {
goto worker_pop;
else if (!workers_may_exit) {
return NULL;
switch (signum) {
case SIGTERM:
case SIGINT:
int threads_created = 0;
int listener_started = 0;
int loops;
int prev_threads_created;
* sizeof(apr_socket_t *));
for (i = 0; i < ap_threads_per_child; i++) {
++loops;
return NULL;
if (listener) {
int iter;
iter = 0;
#ifdef HAVE_PTHREAD_KILL
++iter;
for (i = 0; i < ap_threads_per_child; i++) {
pchild));
if (unixd_setup_child()) {
if (ap_max_requests_per_child) {
if (one_process) {
switch(terminate_mode) {
case ST_GRACEFUL:
case ST_UNGRACEFUL:
int pid;
if (one_process) {
set_signals();
if (!pid) {
#ifdef HAVE_BINDPROCESSOR
clean_child_exit(0);
#ifndef MAX_SPAWN_RATE
static int hold_off_on_exponential_spawning;
static void perform_idle_server_maintenance(void)
int idle_thread_count;
int free_length;
int totally_free_length = 0;
int last_non_dead;
int total_non_dead;
free_length = 0;
idle_thread_count = 0;
total_non_dead = 0;
for (i = 0; i < ap_daemons_limit; ++i) {
int any_dying_threads = 0;
int any_dead_threads = 0;
for (j = 0; j < ap_threads_per_child; j++) {
if (all_dead_threads) {
++free_length;
if (!any_dying_threads) {
last_non_dead = i;
if (free_length == 0) {
static int reported = 0;
if (!reported) {
"or Min/MaxSpareThreads), "
for (i = 0; i < free_length; ++i) {
int child_slot;
if (child_slot >= 0) {
for (i = 0; i < ap_threads_per_child; i++)
else if (remaining_children_to_start
else if (is_graceful) {
else if (remaining_children_to_start) {
if (changed_limit_at_restart) {
if (!is_graceful) {
set_signals();
if (!is_graceful) {
if (shutdown_pending) {
if (!child_fatal) {
if (one_process) {
if (is_graceful) {
/* wake up the children...time to die. But we'll have more soon */
pconf = p;
ap_server_conf = s;
return DONE;
if (!one_process) {
return DONE;
return OK;
static int restart_num = 0;
if (!max_clients) {
else if (!max_clients
if (debug) {
no_detach = 0;
is_graceful = 0;
return HTTP_INTERNAL_SERVER_ERROR;
ap_extended_status = 0;
return OK;
one_process = 0;
const char *arg)
return err;
return NULL;
const char *arg)
return err;
if (min_spare_threads <= 0) {
return NULL;
const char *arg)
return err;
return NULL;
const char *arg)
int max_clients;
return err;
return NULL;
const char *arg)
return err;
return NULL;
int tmp_server_limit;
return err;
if (first_server_limit &&
return NULL;
return NULL;
int tmp_thread_limit;
return err;
if (first_thread_limit &&
return NULL;
return NULL;
{ NULL }