worker.c revision 4bd465052c4a0c8d41e573ee7a90c312d980355f
8a77240a809197c92c0736c431b4b88947a7bac1Christian Maeder/* Licensed to the Apache Software Foundation (ASF) under one or more
8a77240a809197c92c0736c431b4b88947a7bac1Christian Maeder * contributor license agreements. See the NOTICE file distributed with
8a77240a809197c92c0736c431b4b88947a7bac1Christian Maeder * this work for additional information regarding copyright ownership.
adea2e45fa61f1097aadc490a0aeaf4831b729ccChristian Maeder * The ASF licenses this file to You under the Apache License, Version 2.0
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski * (the "License"); you may not use this file except in compliance with
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * the License. You may obtain a copy of the License at
98890889ffb2e8f6f722b00e265a211f13b5a861Corneliu-Claudiu Prodescu * http://www.apache.org/licenses/LICENSE-2.0
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski * Unless required by applicable law or agreed to in writing, software
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski * distributed under the License is distributed on an "AS IS" BASIS,
f3a94a197960e548ecd6520bb768cb0d547457bbChristian Maeder * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * See the License for the specific language governing permissions and
0095c7efbddd0ffeed6aaf8ec015346be161d819Till Mossakowski * limitations under the License.
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski/* The purpose of this MPM is to fix the design flaws in the threaded
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * model. Because of the way that pthreads and mutex locks interact,
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * it is basically impossible to cleanly gracefully shutdown a child
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * process if multiple threads are all blocked in accept. This model
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski * fixes those problems.
556f473448dfcceee22afaa89ed7a364489cdbbbChristian Maeder#include <sys/processor.h> /* for bindprocessor() */
556f473448dfcceee22afaa89ed7a364489cdbbbChristian Maeder#error The Worker MPM requires APR threads, but they are unavailable.
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski#include "http_config.h" /* for read_config */
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski#include "http_core.h" /* for get_remote_host */
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski/* Limit on the total --- clients will be locked out if more servers than
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski * this are needed. It is intended solely to keep the server from crashing
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski * when things get out of hand.
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski * We keep a hard maximum number of servers, for two reasons --- first off,
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski * in case something goes seriously wrong, we want to stop the fork bomb
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * short of actually crashing the machine we're running on by filling some
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski * kernel table. Secondly, it keeps the size of the scoreboard file small
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski * enough that we can read the whole thing without worrying too much about
556f473448dfcceee22afaa89ed7a364489cdbbbChristian Maeder * the overhead.
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder/* Admin can't tune ServerLimit beyond MAX_SERVER_LIMIT. We want
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski * some sort of compile-time limit to help catch typos.
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski/* Limit on the threads per process. Clients will be locked out if more than
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski * this * server_limit are needed.
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski * We keep this for one reason it keeps the size of the scoreboard file small
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski * enough that we can read the whole thing without worrying too much about
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski * the overhead.
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski/* Admin can't tune ThreadLimit beyond MAX_THREAD_LIMIT. We want
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski * some sort of compile-time limit to help catch typos.
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski * Actual definitions of config globals
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowskiint ap_threads_per_child = 0; /* Worker threads per child */
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowskistatic int dying = 0;
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder/* The structure used to pass unique initialization info to each thread */
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maedertypedef struct {
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder/* Structure used to pass information to the thread responsible for
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * creating the rest of the threads.
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maedertypedef struct {
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder#define ID_FROM_CHILD_THREAD(c, t) ((c * thread_limit) + t)
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * The max child slot ever assigned, preserved across restarts. Necessary
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * to deal with MaxClients changes across AP_SIG_GRACEFUL restarts. We
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * use this value to optimize routines that have to scan the entire
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * scoreboard.
556f473448dfcceee22afaa89ed7a364489cdbbbChristian Maeder/* *Non*-shared http_main globals... */
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder/* The worker MPM respects a couple of runtime flags that can aid
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * in debugging. Setting the -DNO_DETACH flag will prevent the root process
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * from detaching from its controlling terminal. Additionally, setting
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * the -DONE_PROCESS flag (which implies -DNO_DETACH) will get you the
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * child_main loop running in the process which originally started up.
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * This gives you a pretty nice debugging environment. (You'll get a SIGHUP
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * early in standalone_main; just continue through. This is the server
556f473448dfcceee22afaa89ed7a364489cdbbbChristian Maeder * trying to kill off any child processes which it might have lying
4d7d53fec6b551333c79da6ae3b8ca2af0a741abChristian Maeder * around --- Apache doesn't keep track of their pids, it just sends
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * SIGHUP to the process group, ignoring it in the root process.
c911a0ec80ca4a178399c68f1e28be4e2bf42fceChristian Maeder * Continue through and you'll be fine.).
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maederstatic apr_pool_t *pconf; /* Pool for config stuff */
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maederstatic apr_pool_t *pchild; /* Pool for httpd child stuff */
cd6e5706893519bfcf24539afa252fcbed5097ddKlaus Luettichstatic pid_t ap_my_pid; /* Linux getpid() doesn't work except in main
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder thread. Use this instead */
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder/* Locks for accept serialization */
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder#define SAFE_ACCEPT(stmt) (ap_listeners->next ? (stmt) : APR_SUCCESS)
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder/* The LISTENER_SIGNAL signal will be sent from the main thread to the
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * listener thread to wake it up for graceful termination (what a child
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * process from an old generation does when the admin does "apachectl
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * graceful"). This signal will be blocked in all threads of a child
e8eb2b9d68adc3024eb1aa9899b902ed5a3fb460Christian Maeder * process except for the listener thread.
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder/* The WORKER_SIGNAL signal will be sent from the main thread to the
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * worker threads during an ungraceful restart or shutdown.
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * This ensures that on systems (i.e., Linux) where closing the worker
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * socket doesn't awake the worker thread when it is polling on the socket
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * (especially in apr_wait_for_io_or_timeout() when handling
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * Keep-Alive connections), close_worker_sockets() and join_workers()
cd6e5706893519bfcf24539afa252fcbed5097ddKlaus Luettich * still function in timely manner and allow ungraceful shutdowns to
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * proceed to completion. Otherwise join_workers() doesn't return
e7d2b3903c7b44db432538b0d720c21062c24823Christian Maeder * before the main process decides the child process is non-responsive
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * and sends a SIGKILL.
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder/* An array of socket descriptors in use by each thread used to
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * perform a non-graceful (forced) shutdown of the server. */
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder for (i = 0; i < ap_threads_per_child; i++) {
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maederstatic void wakeup_listener(void)
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder /* XXX there is an obscure path that this doesn't handle perfectly:
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * right after listener thread is created but before
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * listener_os_thread is set, the first worker thread hits an
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * error and starts graceful termination
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * we should just be able to "kill(ap_my_pid, LISTENER_SIGNAL)" on all
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * platforms and wake up the listener thread since it is the only thread
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * with SIGHUP unblocked, but that doesn't work on Linux
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder pthread_kill(*listener_os_thread, LISTENER_SIGNAL);
c911a0ec80ca4a178399c68f1e28be4e2bf42fceChristian Maeder /* in case we weren't called from the listener thread, wake up the
c911a0ec80ca4a178399c68f1e28be4e2bf42fceChristian Maeder * listener thread
4ef5e33657aae95850b7e6941f67ac1fb73cd13fChristian Maeder /* for ungraceful termination, let the workers exit now;
4ef5e33657aae95850b7e6941f67ac1fb73cd13fChristian Maeder * for graceful termination, the listener thread will notify the
4ef5e33657aae95850b7e6941f67ac1fb73cd13fChristian Maeder * workers to exit once it has stopped accepting new connections
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder close_worker_sockets(); /* forcefully kill all current connections */
09b431a868c79a92ae7c9bd141565f43f9034144Christian MaederAP_DECLARE(apr_status_t) ap_mpm_query(int query_code, int *result)
if (pchild) {
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 set_signals(void)
#ifndef NO_USE_SIGACTION
if (!one_process) {
#ifndef NO_USE_SIGACTION
#ifdef AP_SIG_GRACEFUL_STOP
#ifdef SIGINT
#ifdef SIGXCPU
#ifdef SIGXFSZ
#ifdef SIGPIPE
if (!one_process) {
#ifdef SIGXCPU
#ifdef SIGXFSZ
#ifdef SIGHUP
#ifdef AP_SIG_GRACEFUL
#ifdef AP_SIG_GRACEFUL_STOP
#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)
int have_idle_worker = 0;
int last_poll_idx = 0;
if (requests_this_child <= 0) {
if (listener_may_exit) break;
if (!have_idle_worker) {
&ptrans);
!= APR_SUCCESS) {
if (listener_may_exit) {
while (!listener_may_exit) {
if (listener_may_exit) break;
last_poll_idx = 0;
if (!listener_may_exit) {
!= APR_SUCCESS) {
if (listener_may_exit) {
if (rv) {
have_idle_worker = 0;
!= APR_SUCCESS) {
return NULL;
/* XXX For ungraceful termination/restart, we definitely don't want to
int is_idle = 0;
#ifdef HAVE_PTHREAD_KILL
while (!workers_may_exit) {
if (!is_idle) {
if (workers_may_exit) {
goto worker_pop;
else if (!workers_may_exit) {
is_idle = 0;
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++) {
#ifdef HAVE_PTHREAD_KILL
pchild));
if (unixd_setup_child()) {
if (ap_max_requests_per_child) {
if (ap_thread_stacksize != 0) {
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;
int active_thread_count = 0;
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 (sick_child_detected) {
if (active_thread_count > 0) {
sick_child_detected = 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
status) == 0) {
else if (is_graceful) {
else if (remaining_children_to_start) {
if (!is_graceful) {
set_signals();
if (!is_graceful) {
if (!child_fatal) {
} else if (shutdown_pending) {
int active_children;
int index;
if (!child_fatal) {
if (ap_graceful_shutdown_timeout) {
shutdown_pending = 0;
active_children = 0;
if (one_process) {
if (is_graceful) {
/* wake up the children...time to die. But we'll have more soon */
static int restart_num = 0;
int startup = 0;
int level_flags = 0;
pconf = p;
ap_server_conf = s;
if (restart_num++ == 0) {
return DONE;
if (!one_process) {
return DONE;
return OK;
static int restart_num = 0;
if (debug) {
no_detach = 0;
is_graceful = 0;
return HTTP_INTERNAL_SERVER_ERROR;
ap_extended_status = 0;
#ifdef AP_MPM_WANT_SET_MAX_MEM_FREE
return OK;
static int restart_num = 0;
int startup = 0;
if (restart_num++ == 0) {
if (startup) {
if (startup) {
if (!first_server_limit) {
if (startup) {
if (startup) {
if (!first_thread_limit) {
if (startup) {
if (startup) {
if (startup) {
if (startup) {
if (startup) {
if (ap_daemons_to_start < 0) {
if (startup) {
if (startup) {
return OK;
one_process = 0;
const char *arg)
return err;
return NULL;
const char *arg)
return err;
return NULL;
const char *arg)
return err;
return NULL;
const char *arg)
return err;
return NULL;
const char *arg)
return err;
return NULL;
return err;
return NULL;
return err;
return NULL;
"Maximum number of worker threads per child process for this run of Apache - Upper limit for ThreadsPerChild"),
{ NULL }