worker.c revision d19d0f582dde461e2048a0ade811effb5f6e1524
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd/* Copyright 2001-2005 The Apache Software Foundation or its licensors, as
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * applicable.
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * Licensed under the Apache License, Version 2.0 (the "License");
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * you may not use this file except in compliance with the License.
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * You may obtain a copy of the License at
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * Unless required by applicable law or agreed to in writing, software
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * distributed under the License is distributed on an "AS IS" BASIS,
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * See the License for the specific language governing permissions and
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * limitations under the License.
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd/* The purpose of this MPM is to fix the design flaws in the threaded
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * model. Because of the way that pthreads and mutex locks interact,
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * it is basically impossible to cleanly gracefully shutdown a child
4b5981e276e93df97c34e4da05ca5cf8bbd937dand * process if multiple threads are all blocked in accept. This model
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * fixes those problems.
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd#error The Worker MPM requires APR threads, but they are unavailable.
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd/* Limit on the total --- clients will be locked out if more servers than
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * this are needed. It is intended solely to keep the server from crashing
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * when things get out of hand.
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * We keep a hard maximum number of servers, for two reasons --- first off,
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * in case something goes seriously wrong, we want to stop the fork bomb
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * short of actually crashing the machine we're running on by filling some
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * kernel table. Secondly, it keeps the size of the scoreboard file small
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * enough that we can read the whole thing without worrying too much about
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * the overhead.
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd/* Admin can't tune ServerLimit beyond MAX_SERVER_LIMIT. We want
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * some sort of compile-time limit to help catch typos.
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd/* Limit on the threads per process. Clients will be locked out if more than
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * this * server_limit are needed.
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * We keep this for one reason it keeps the size of the scoreboard file small
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * enough that we can read the whole thing without worrying too much about
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * the overhead.
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd/* Admin can't tune ThreadLimit beyond MAX_THREAD_LIMIT. We want
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * some sort of compile-time limit to help catch typos.
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * Actual definitions of config globals
6116c12fdd3ed06d388fe6572e50a22e9320dfa5ndint ap_threads_per_child = 0; /* Worker threads per child */
6116c12fdd3ed06d388fe6572e50a22e9320dfa5ndstatic int ap_daemons_to_start = 0;
6116c12fdd3ed06d388fe6572e50a22e9320dfa5ndstatic int min_spare_threads = 0;
6116c12fdd3ed06d388fe6572e50a22e9320dfa5ndstatic int max_spare_threads = 0;
6116c12fdd3ed06d388fe6572e50a22e9320dfa5ndstatic int ap_daemons_limit = 0;
6116c12fdd3ed06d388fe6572e50a22e9320dfa5ndstatic int dying = 0;
6116c12fdd3ed06d388fe6572e50a22e9320dfa5ndstatic int workers_may_exit = 0;
6116c12fdd3ed06d388fe6572e50a22e9320dfa5ndstatic int start_thread_may_exit = 0;
6116c12fdd3ed06d388fe6572e50a22e9320dfa5ndstatic int listener_may_exit = 0;
6116c12fdd3ed06d388fe6572e50a22e9320dfa5ndstatic int num_listensocks = 0;
6116c12fdd3ed06d388fe6572e50a22e9320dfa5ndstatic int resource_shortage = 0;
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd/* The structure used to pass unique initialization info to each thread */
6116c12fdd3ed06d388fe6572e50a22e9320dfa5ndtypedef struct {
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd/* Structure used to pass information to the thread responsible for
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * creating the rest of the threads.
71fccc298df6a1540d408151a26aa22beed55d0bndtypedef struct {
71fccc298df6a1540d408151a26aa22beed55d0bnd#define ID_FROM_CHILD_THREAD(c, t) ((c * thread_limit) + t)
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * The max child slot ever assigned, preserved across restarts. Necessary
b3c7a2279fa7a45f5807d9a404760b9b3760df50nd * to deal with MaxClients changes across AP_SIG_GRACEFUL restarts. We
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * use this value to optimize routines that have to scan the entire
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * scoreboard.
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd/* *Non*-shared http_main globals... */
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd/* The worker MPM respects a couple of runtime flags that can aid
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * in debugging. Setting the -DNO_DETACH flag will prevent the root process
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * from detaching from its controlling terminal. Additionally, setting
623eebe956d9c2d6d073ed3eae855b56030b40e9noodl * the -DONE_PROCESS flag (which implies -DNO_DETACH) will get you the
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * child_main loop running in the process which originally started up.
ffb88a4885747797937e30a5ac8b1606da3cb4adnd * This gives you a pretty nice debugging environment. (You'll get a SIGHUP
909ce17e2bd0faef7b1c294f2307f009793fd493nd * early in standalone_main; just continue through. This is the server
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * trying to kill off any child processes which it might have lying
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * around --- Apache doesn't keep track of their pids, it just sends
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * SIGHUP to the process group, ignoring it in the root process.
42af92a661a06b3cebc88d585aad75064a309d51nd * Continue through and you'll be fine.).
6116c12fdd3ed06d388fe6572e50a22e9320dfa5ndstatic int one_process = 0;
6116c12fdd3ed06d388fe6572e50a22e9320dfa5ndstatic apr_pool_t *pchild; /* Pool for httpd child stuff */
6116c12fdd3ed06d388fe6572e50a22e9320dfa5ndstatic pid_t ap_my_pid; /* Linux getpid() doesn't work except in main
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd thread. Use this instead */
05ede5110427cb9dc071cc671d5aaba5d3b88c79nd/* Locks for accept serialization */
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd#define SAFE_ACCEPT(stmt) (ap_listeners->next ? (stmt) : APR_SUCCESS)
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd/* The LISTENER_SIGNAL signal will be sent from the main thread to the
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * listener thread to wake it up for graceful termination (what a child
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * process from an old generation does when the admin does "apachectl
03a4ff9ac4c9b8009249010e7c53bb86ff05915and * graceful"). This signal will be blocked in all threads of a child
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * process except for the listener thread.
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd/* An array of socket descriptors in use by each thread used to
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * perform a non-graceful (forced) shutdown of the server. */
d2b809e5d72658bff23819d8b77f20e4939af541ndstatic void close_worker_sockets(void)
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd for (i = 0; i < ap_threads_per_child; i++) {
1d980e5489836e977ba59b419e27b0ec875c4bd3takashistatic void wakeup_listener(void)
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd /* XXX there is an obscure path that this doesn't handle perfectly:
f772e8f448c223e5ea306f1bf92d97d968f972d5jim * right after listener thread is created but before
f772e8f448c223e5ea306f1bf92d97d968f972d5jim * listener_os_thread is set, the first worker thread hits an
f772e8f448c223e5ea306f1bf92d97d968f972d5jim * error and starts graceful termination
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * we should just be able to "kill(ap_my_pid, LISTENER_SIGNAL)" on all
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd * platforms and wake up the listener thread since it is the only thread
898711b68797304101de0882fa576c8908acfae6nd * with SIGHUP unblocked, but that doesn't work on Linux
71fccc298df6a1540d408151a26aa22beed55d0bnd /* in case we weren't called from the listener thread, wake up the
71fccc298df6a1540d408151a26aa22beed55d0bnd * listener thread
6116c12fdd3ed06d388fe6572e50a22e9320dfa5nd /* for ungraceful termination, let the workers exit now;
ad74a0524a06bfe11b7de9e3b4ce7233ab3bd3f7nd * for graceful termination, the listener thread will notify the
ad74a0524a06bfe11b7de9e3b4ce7233ab3bd3f7nd * workers to exit once it has stopped accepting new connections
6eed902e5b4d3e016e220bfbf8769a87c4cb242enoodl close_worker_sockets(); /* forcefully kill all current connections */
switch(query_code){
case AP_MPMQ_MAX_DAEMON_USED:
return APR_SUCCESS;
case AP_MPMQ_IS_THREADED:
return APR_SUCCESS;
case AP_MPMQ_IS_FORKED:
return APR_SUCCESS;
return APR_SUCCESS;
return APR_SUCCESS;
case AP_MPMQ_MAX_THREADS:
return APR_SUCCESS;
*result = 0;
return APR_SUCCESS;
return APR_SUCCESS;
*result = 0;
return APR_SUCCESS;
return APR_SUCCESS;
return APR_SUCCESS;
case AP_MPMQ_MAX_DAEMONS:
return APR_SUCCESS;
case AP_MPMQ_MPM_STATE:
return APR_SUCCESS;
return APR_ENOTIMPL;
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 ap_start_shutdown(void)
static void set_signals(void)
#ifndef NO_USE_SIGACTION
if (!one_process) {
#ifndef NO_USE_SIGACTION
#ifdef SIGINT
#ifdef SIGXCPU
#ifdef SIGXFSZ
#ifdef SIGPIPE
if (!one_process) {
#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)
int have_idle_worker = 0;
int last_poll_idx = 0;
if (requests_this_child <= 0) {
if (listener_may_exit) break;
if (!have_idle_worker) {
!= 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;
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++) {
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;
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
status) == 0) {
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;
#ifdef AP_MPM_WANT_SET_MAX_MEM_FREE
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;
"Maximum number of worker threads per child process for this run of Apache - Upper limit for ThreadsPerChild"),
{ NULL }