event.c revision ddd5a8aaf25fba9e158e554c072a1fa57eaef07a
d5082de325fb6351c6bd34d28df0b43ec5a8ac90erikabele/* Licensed to the Apache Software Foundation (ASF) under one or more
d5082de325fb6351c6bd34d28df0b43ec5a8ac90erikabele * contributor license agreements. See the NOTICE file distributed with
d5082de325fb6351c6bd34d28df0b43ec5a8ac90erikabele * this work for additional information regarding copyright ownership.
47bbfaa3a2ea0afb775a3aa3e7dbf8a71ea1b966rbowen * The ASF licenses this file to You under the Apache License, Version 2.0
47bbfaa3a2ea0afb775a3aa3e7dbf8a71ea1b966rbowen * (the "License"); you may not use this file except in compliance with
47bbfaa3a2ea0afb775a3aa3e7dbf8a71ea1b966rbowen * the License. You may obtain a copy of the License at
5a58787efeb02a1c3f06569d019ad81fd2efa06end * Unless required by applicable law or agreed to in writing, software
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen * distributed under the License is distributed on an "AS IS" BASIS,
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen * See the License for the specific language governing permissions and
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen * limitations under the License.
3f08db06526d6901aa08c110b5bc7dde6bc39905nd * This MPM tries to fix the 'keep alive problem' in HTTP.
5a58787efeb02a1c3f06569d019ad81fd2efa06end * After a client completes the first request, the client can keep the
5a58787efeb02a1c3f06569d019ad81fd2efa06end * connection open to send more requests with the same socket. This can save
8a77625288bc7112717de423742309213a7d453erbowen * significant overhead in creating TCP connections. However, the major
3b3b7fc78d1f5bfc2769903375050048ff41ff26nd * disadvantage is that Apache traditionally keeps an entire child
a0e183666b44ebb43fdfeffe78d36c6134a59d4dyoshiki * process/thread waiting for data from the client. To solve this problem,
980bee71ed017c72bfdd9861445f9495855508ccgryzor * this MPM has a dedicated thread for handling both the Listening sockets,
7f5b59ccc63c0c0e3e678a168f09ee6a2f51f9d0nd * and all sockets that are in a Keep Alive status.
f086b4b402fa9a2fefc7dda85de2a3cc1cd0a654rjung * The MPM assumes the underlying apr_pollset implementation is somewhat
3b3b7fc78d1f5bfc2769903375050048ff41ff26nd * threadsafe. This currently is only compatible with KQueue and EPoll. This
3b3b7fc78d1f5bfc2769903375050048ff41ff26nd * enables the MPM to avoid extra high level locking or having to wake up the
47bbfaa3a2ea0afb775a3aa3e7dbf8a71ea1b966rbowen * listener thread when a keep-alive socket needs to be sent to it.
5a58787efeb02a1c3f06569d019ad81fd2efa06end * This MPM does not perform well on older platforms that do not have very good
5a58787efeb02a1c3f06569d019ad81fd2efa06end * threading, like Linux with a 2.4 kernel, but this does not matter, since we
5a58787efeb02a1c3f06569d019ad81fd2efa06end * require EPoll or KQueue.
5a58787efeb02a1c3f06569d019ad81fd2efa06end * For FreeBSD, use 5.3. It is possible to run this MPM on FreeBSD 5.2.1, if
5a58787efeb02a1c3f06569d019ad81fd2efa06end * you use libkse (see `man libmap.conf`).
5a58787efeb02a1c3f06569d019ad81fd2efa06end * For NetBSD, use at least 2.0.
30471a4650391f57975f60bbb6e4a90be7b284bfhumbedooh * For Linux, you should use a 2.6 kernel, and make sure your glibc has epoll
5a58787efeb02a1c3f06569d019ad81fd2efa06end * support compiled in.
c10e24e52c0f454df46a44e3ccc8ccb56abd9d2aslive#error The Event MPM requires APR threads, but they are unavailable.
6f227ca67f7a591c2b1dbfd0f7ac31cc341061a5nd/* Limit on the total --- clients will be locked out if more servers than
5a58787efeb02a1c3f06569d019ad81fd2efa06end * this are needed. It is intended solely to keep the server from crashing
5a58787efeb02a1c3f06569d019ad81fd2efa06end * when things get out of hand.
47bbfaa3a2ea0afb775a3aa3e7dbf8a71ea1b966rbowen * We keep a hard maximum number of servers, for two reasons --- first off,
bcd392b291251e23c63d0cc4d11c9121e9627c24rbowen * in case something goes seriously wrong, we want to stop the fork bomb
47bbfaa3a2ea0afb775a3aa3e7dbf8a71ea1b966rbowen * short of actually crashing the machine we're running on by filling some
bde4540877ce9bac98aec1d196a307b39c5c9775rbowen * kernel table. Secondly, it keeps the size of the scoreboard file small
1bf55339918c7e8ebf57ab686ff459c3f2651fcagryzor * enough that we can read the whole thing without worrying too much about
bde4540877ce9bac98aec1d196a307b39c5c9775rbowen * the overhead.
47bbfaa3a2ea0afb775a3aa3e7dbf8a71ea1b966rbowen/* Admin can't tune ServerLimit beyond MAX_SERVER_LIMIT. We want
47bbfaa3a2ea0afb775a3aa3e7dbf8a71ea1b966rbowen * some sort of compile-time limit to help catch typos.
47bbfaa3a2ea0afb775a3aa3e7dbf8a71ea1b966rbowen/* Limit on the threads per process. Clients will be locked out if more than
47bbfaa3a2ea0afb775a3aa3e7dbf8a71ea1b966rbowen * this are needed.
47bbfaa3a2ea0afb775a3aa3e7dbf8a71ea1b966rbowen * We keep this for one reason it keeps the size of the scoreboard file small
47bbfaa3a2ea0afb775a3aa3e7dbf8a71ea1b966rbowen * enough that we can read the whole thing without worrying too much about
47bbfaa3a2ea0afb775a3aa3e7dbf8a71ea1b966rbowen * the overhead.
47bbfaa3a2ea0afb775a3aa3e7dbf8a71ea1b966rbowen/* Admin can't tune ThreadLimit beyond MAX_THREAD_LIMIT. We want
47bbfaa3a2ea0afb775a3aa3e7dbf8a71ea1b966rbowen * some sort of compile-time limit to help catch typos.
47bbfaa3a2ea0afb775a3aa3e7dbf8a71ea1b966rbowen#define MPM_CHILD_PID(i) (ap_scoreboard_image->parent[i].pid)
d5082de325fb6351c6bd34d28df0b43ec5a8ac90erikabele * Actual definitions of config globals
47bbfaa3a2ea0afb775a3aa3e7dbf8a71ea1b966rbowen#define WORKER_FACTOR_SCALE 16 /* scale factor to allow fractional values */
6f227ca67f7a591c2b1dbfd0f7ac31cc341061a5ndstatic unsigned int worker_factor = DEFAULT_WORKER_FACTOR * WORKER_FACTOR_SCALE;
6f227ca67f7a591c2b1dbfd0f7ac31cc341061a5ndstatic int threads_per_child = 0; /* Worker threads per child */
bde4540877ce9bac98aec1d196a307b39c5c9775rbowenstatic int min_spare_threads = 0;
bde4540877ce9bac98aec1d196a307b39c5c9775rbowenstatic int max_spare_threads = 0;
bde4540877ce9bac98aec1d196a307b39c5c9775rbowenstatic int ap_daemons_limit = 0;
bde4540877ce9bac98aec1d196a307b39c5c9775rbowenstatic int max_workers = 0;
bde4540877ce9bac98aec1d196a307b39c5c9775rbowenstatic int server_limit = 0;
bde4540877ce9bac98aec1d196a307b39c5c9775rbowenstatic int thread_limit = 0;
bde4540877ce9bac98aec1d196a307b39c5c9775rbowenstatic int had_healthy_child = 0;
bde4540877ce9bac98aec1d196a307b39c5c9775rbowenstatic int dying = 0;
bde4540877ce9bac98aec1d196a307b39c5c9775rbowenstatic int workers_may_exit = 0;
47bbfaa3a2ea0afb775a3aa3e7dbf8a71ea1b966rbowenstatic int listener_may_exit = 0;
47bbfaa3a2ea0afb775a3aa3e7dbf8a71ea1b966rbowenstatic int num_listensocks = 0;
47bbfaa3a2ea0afb775a3aa3e7dbf8a71ea1b966rbowenstatic apr_int32_t conns_this_child; /* MaxConnectionsPerChild, only access
47bbfaa3a2ea0afb775a3aa3e7dbf8a71ea1b966rbowen in listener thread */
47bbfaa3a2ea0afb775a3aa3e7dbf8a71ea1b966rbowenstatic apr_uint32_t connection_count = 0; /* Number of open connections */
47bbfaa3a2ea0afb775a3aa3e7dbf8a71ea1b966rbowenstatic apr_uint32_t lingering_count = 0; /* Number of connections in lingering close */
6f227ca67f7a591c2b1dbfd0f7ac31cc341061a5ndstatic apr_uint32_t suspended_count = 0; /* Number of suspended connections */
6f227ca67f7a591c2b1dbfd0f7ac31cc341061a5ndstatic apr_uint32_t clogged_count = 0; /* Number of threads processing ssl conns */
6f227ca67f7a591c2b1dbfd0f7ac31cc341061a5ndstatic int resource_shortage = 0;
47bbfaa3a2ea0afb775a3aa3e7dbf8a71ea1b966rbowen /** APR_RING of expiration timeouts */
d5082de325fb6351c6bd34d28df0b43ec5a8ac90erikabele /** the expiration time of the next keepalive timeout */
e487d6c09669296f94a5190cc34586a98e624a00nd /** connection record this struct refers to */
d5082de325fb6351c6bd34d28df0b43ec5a8ac90erikabele /** memory pool to allocate from */
15292da5451dea4ad10c12d35d9addc88be302c5humbedooh /** bucket allocator */
15292da5451dea4ad10c12d35d9addc88be302c5humbedooh /** poll file descriptor information */
e487d6c09669296f94a5190cc34586a98e624a00nd /** public parts of the connection state */
6f227ca67f7a591c2b1dbfd0f7ac31cc341061a5nd const char *tag;
15292da5451dea4ad10c12d35d9addc88be302c5humbedooh * Several timeout queues that use different timeouts, so that we always can
15292da5451dea4ad10c12d35d9addc88be302c5humbedooh * simply append to the end.
5a58787efeb02a1c3f06569d019ad81fd2efa06end * write_completion_q uses TimeOut
5a58787efeb02a1c3f06569d019ad81fd2efa06end * keepalive_q uses KeepAliveTimeOut
5a58787efeb02a1c3f06569d019ad81fd2efa06end * linger_q uses MAX_SECS_TO_LINGER
47bbfaa3a2ea0afb775a3aa3e7dbf8a71ea1b966rbowen * short_linger_q uses SECONDS_TO_LINGER
47bbfaa3a2ea0afb775a3aa3e7dbf8a71ea1b966rbowenstatic struct timeout_queue write_completion_q, keepalive_q, linger_q,
47bbfaa3a2ea0afb775a3aa3e7dbf8a71ea1b966rbowen * Macros for accessing struct timeout_queue.
47bbfaa3a2ea0afb775a3aa3e7dbf8a71ea1b966rbowen * For TO_QUEUE_APPEND and TO_QUEUE_REMOVE, timeout_mutex must be held.
47bbfaa3a2ea0afb775a3aa3e7dbf8a71ea1b966rbowen APR_RING_INSERT_TAIL(&(q).head, el, event_conn_state_t, timeout_list); \
47bbfaa3a2ea0afb775a3aa3e7dbf8a71ea1b966rbowen } while (0)
47bbfaa3a2ea0afb775a3aa3e7dbf8a71ea1b966rbowen } while (0)
47bbfaa3a2ea0afb775a3aa3e7dbf8a71ea1b966rbowen APR_RING_INIT(&(q).head, event_conn_state_t, timeout_list); \
47bbfaa3a2ea0afb775a3aa3e7dbf8a71ea1b966rbowen (q).tag = #q; \
47bbfaa3a2ea0afb775a3aa3e7dbf8a71ea1b966rbowen } while (0)
15292da5451dea4ad10c12d35d9addc88be302c5humbedooh#define TO_QUEUE_ELEM_INIT(el) APR_RING_ELEM_INIT(el, timeout_list)
47bbfaa3a2ea0afb775a3aa3e7dbf8a71ea1b966rbowen * The pollset for sockets that are in any of the timeout queues. Currently
47bbfaa3a2ea0afb775a3aa3e7dbf8a71ea1b966rbowen * we use the timeout_mutex to make sure that connections are added/removed
47bbfaa3a2ea0afb775a3aa3e7dbf8a71ea1b966rbowen * atomically to/from both event_pollset and a timeout queue. Otherwise
47bbfaa3a2ea0afb775a3aa3e7dbf8a71ea1b966rbowen * some confusion can happen under high load if timeout queues and pollset
2a80f5f5b2b28a9b603fc41d3e2b37128f5f1e00slive * get out of sync.
2a80f5f5b2b28a9b603fc41d3e2b37128f5f1e00slive * XXX: It should be possible to make the lock unnecessary in many or even all
2a80f5f5b2b28a9b603fc41d3e2b37128f5f1e00slive * XXX: cases.
bcd392b291251e23c63d0cc4d11c9121e9627c24rbowentypedef struct {
419d55842022e9e257941bfe226549661fb2c6c7humbedooh/* The structure used to pass unique initialization info to each thread */
419d55842022e9e257941bfe226549661fb2c6c7humbedoohtypedef struct
2a80f5f5b2b28a9b603fc41d3e2b37128f5f1e00slive/* Structure used to pass information to the thread responsible for
bcd392b291251e23c63d0cc4d11c9121e9627c24rbowen * creating the rest of the threads.
2a80f5f5b2b28a9b603fc41d3e2b37128f5f1e00slivetypedef struct
47bbfaa3a2ea0afb775a3aa3e7dbf8a71ea1b966rbowentypedef enum
47bbfaa3a2ea0afb775a3aa3e7dbf8a71ea1b966rbowentypedef struct
15292da5451dea4ad10c12d35d9addc88be302c5humbedooh/* data retained by event across load/unload of the module
15292da5451dea4ad10c12d35d9addc88be302c5humbedooh * allocated on first call to pre-config hook; located on
15292da5451dea4ad10c12d35d9addc88be302c5humbedooh * subsequent calls to pre-config hook
15292da5451dea4ad10c12d35d9addc88be302c5humbedoohtypedef struct event_retained_data {
47bbfaa3a2ea0afb775a3aa3e7dbf8a71ea1b966rbowen int volatile is_graceful; /* set from signal handler */
5a58787efeb02a1c3f06569d019ad81fd2efa06end * The max child slot ever assigned, preserved across restarts. Necessary
5a58787efeb02a1c3f06569d019ad81fd2efa06end * to deal with MaxRequestWorkers changes across AP_SIG_GRACEFUL restarts.
6f227ca67f7a591c2b1dbfd0f7ac31cc341061a5nd * We use this value to optimize routines that have to scan the entire
47bbfaa3a2ea0afb775a3aa3e7dbf8a71ea1b966rbowen * scoreboard.
47bbfaa3a2ea0afb775a3aa3e7dbf8a71ea1b966rbowen * idle_spawn_rate is the number of children that will be spawned on the
47bbfaa3a2ea0afb775a3aa3e7dbf8a71ea1b966rbowen * next maintenance cycle if there aren't enough idle servers. It is
419d55842022e9e257941bfe226549661fb2c6c7humbedooh * doubled up to MAX_SPAWN_RATE, and reset only when a cycle goes by
15292da5451dea4ad10c12d35d9addc88be302c5humbedooh * without the need to spawn.
47bbfaa3a2ea0afb775a3aa3e7dbf8a71ea1b966rbowen#define ID_FROM_CHILD_THREAD(c, t) ((c * thread_limit) + t)
5a58787efeb02a1c3f06569d019ad81fd2efa06end/* The event MPM respects a couple of runtime flags that can aid
47bbfaa3a2ea0afb775a3aa3e7dbf8a71ea1b966rbowen * in debugging. Setting the -DNO_DETACH flag will prevent the root process
47bbfaa3a2ea0afb775a3aa3e7dbf8a71ea1b966rbowen * from detaching from its controlling terminal. Additionally, setting
47bbfaa3a2ea0afb775a3aa3e7dbf8a71ea1b966rbowen * the -DONE_PROCESS flag (which implies -DNO_DETACH) will get you the
47bbfaa3a2ea0afb775a3aa3e7dbf8a71ea1b966rbowen * child_main loop running in the process which originally started up.
47bbfaa3a2ea0afb775a3aa3e7dbf8a71ea1b966rbowen * This gives you a pretty nice debugging environment. (You'll get a SIGHUP
419d55842022e9e257941bfe226549661fb2c6c7humbedooh * early in standalone_main; just continue through. This is the server
15292da5451dea4ad10c12d35d9addc88be302c5humbedooh * trying to kill off any child processes which it might have lying
15292da5451dea4ad10c12d35d9addc88be302c5humbedooh * around --- Apache doesn't keep track of their pids, it just sends
419d55842022e9e257941bfe226549661fb2c6c7humbedooh * SIGHUP to the process group, ignoring it in the root process.
419d55842022e9e257941bfe226549661fb2c6c7humbedooh * Continue through and you'll be fine.).
47bbfaa3a2ea0afb775a3aa3e7dbf8a71ea1b966rbowenstatic int one_process = 0;
419d55842022e9e257941bfe226549661fb2c6c7humbedoohstatic apr_pool_t *pconf; /* Pool for config stuff */
419d55842022e9e257941bfe226549661fb2c6c7humbedoohstatic apr_pool_t *pchild; /* Pool for httpd child stuff */
6f227ca67f7a591c2b1dbfd0f7ac31cc341061a5ndstatic pid_t ap_my_pid; /* Linux getpid() doesn't work except in main
6f227ca67f7a591c2b1dbfd0f7ac31cc341061a5nd thread. Use this instead */
47bbfaa3a2ea0afb775a3aa3e7dbf8a71ea1b966rbowen/* The LISTENER_SIGNAL signal will be sent from the main thread to the
47bbfaa3a2ea0afb775a3aa3e7dbf8a71ea1b966rbowen * listener thread to wake it up for graceful termination (what a child
5a58787efeb02a1c3f06569d019ad81fd2efa06end * process from an old generation does when the admin does "apachectl
5a58787efeb02a1c3f06569d019ad81fd2efa06end * graceful"). This signal will be blocked in all threads of a child
5a58787efeb02a1c3f06569d019ad81fd2efa06end * process except for the listener thread.
47bbfaa3a2ea0afb775a3aa3e7dbf8a71ea1b966rbowen/* An array of socket descriptors in use by each thread used to
47bbfaa3a2ea0afb775a3aa3e7dbf8a71ea1b966rbowen * perform a non-graceful (forced) shutdown of the server.
47bbfaa3a2ea0afb775a3aa3e7dbf8a71ea1b966rbowen for (i = 0; i < num_listensocks; i++) {
47bbfaa3a2ea0afb775a3aa3e7dbf8a71ea1b966rbowen apr_pollset_remove(event_pollset, &listener_pollfd[i]);
8a77625288bc7112717de423742309213a7d453erbowen ap_scoreboard_image->parent[process_slot].not_accepting = 1;
1baec6e12c9c698202c8cd880b8013431f7542c9rbowen ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(00457)
1baec6e12c9c698202c8cd880b8013431f7542c9rbowen "Accepting new connections again: "
1baec6e12c9c698202c8cd880b8013431f7542c9rbowen "%u active conns (%u lingering/%u clogged/%u suspended), "
1baec6e12c9c698202c8cd880b8013431f7542c9rbowen "%u idle workers",
1baec6e12c9c698202c8cd880b8013431f7542c9rbowen for (i = 0; i < num_listensocks; i++)
1baec6e12c9c698202c8cd880b8013431f7542c9rbowen * XXX: This is not yet optimal. If many workers suddenly become available,
1baec6e12c9c698202c8cd880b8013431f7542c9rbowen * XXX: the parent may kill some processes off too soon.
1baec6e12c9c698202c8cd880b8013431f7542c9rbowen ap_scoreboard_image->parent[process_slot].not_accepting = 0;
47bbfaa3a2ea0afb775a3aa3e7dbf8a71ea1b966rbowenstatic void close_worker_sockets(void)
a0e183666b44ebb43fdfeffe78d36c6134a59d4dyoshiki for (i = 0; i < threads_per_child; i++) {
30471a4650391f57975f60bbb6e4a90be7b284bfhumbedoohstatic void wakeup_listener(void)
0d0ba3a410038e179b695446bb149cce6264e0abnd /* XXX there is an obscure path that this doesn't handle perfectly:
0d0ba3a410038e179b695446bb149cce6264e0abnd * right after listener thread is created but before
0d0ba3a410038e179b695446bb149cce6264e0abnd * listener_os_thread is set, the first worker thread hits an
0d0ba3a410038e179b695446bb149cce6264e0abnd * error and starts graceful termination
0d0ba3a410038e179b695446bb149cce6264e0abnd /* unblock the listener if it's waiting for a worker */
5effc8b39fae5cd169d17f342bfc265705840014rbowen * we should just be able to "kill(ap_my_pid, LISTENER_SIGNAL)" on all
d229f940abfb2490dee17979e9a5ff31b7012eb5rbowen * platforms and wake up the listener thread since it is the only thread
0d0ba3a410038e179b695446bb149cce6264e0abnd * with SIGHUP unblocked, but that doesn't work on Linux
#define ST_INIT 0
switch (query_code) {
case AP_MPMQ_MAX_DAEMON_USED:
case AP_MPMQ_IS_THREADED:
case AP_MPMQ_IS_FORKED:
case AP_MPMQ_IS_ASYNC:
case AP_MPMQ_HAS_SERF:
case AP_MPMQ_MAX_THREADS:
*result = 0;
*result = 0;
case AP_MPMQ_MAX_DAEMONS:
case AP_MPMQ_MPM_STATE:
case AP_MPMQ_GENERATION:
return OK;
static const char *event_get_name(void)
if (pchild) {
if (one_process) {
clean_child_exit(0);
static int child_fatal;
static int volatile shutdown_pending;
static int volatile restart_pending;
case CONN_STATE_LINGER_NORMAL:
case CONN_STATE_LINGER_SHORT:
case CONN_STATE_SUSPENDED:
return APR_SUCCESS;
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
struct timeout_queue *q;
#ifdef AP_DEBUG
q = &short_linger_q;
q = &linger_q;
if (c->aborted
AP_DEBUG_ASSERT(0);
int my_thread_num)
conn_rec *c;
int rc;
apr_pool_clear(p);
cs->c = c;
cs->p = p;
c = cs->c;
if (!c->aborted) {
* fall thru to either wait for readability/timeout or
else if (c->data_in_output_filters) {
else if (c->data_in_input_filters) {
goto read_request;
apr_time_now();
static void check_infinite_requests(void)
if (ap_max_requests_per_child) {
if (!*closed) {
for (i = 0; i < threads_per_child; ++i) {
#if defined(SIGPROCMASK_SETS_THREAD_MASK)
#if HAVE_SERF
void *serf_baton)
void *serf_baton)
#if HAVE_SERF
#if HAVE_SERF
s_socket_remove, p);
return APR_SUCCESS;
return rc;
if (*have_idle_worker_p) {
if (blocking)
void *baton)
int inserted = 0;
if (!inserted) {
return APR_SUCCESS;
struct timeout_queue *q;
int count = 0;
if (!q->count) {
count++;
if (!count)
while (count) {
count--;
int have_idle_worker = 0;
return NULL;
int workers_were_busy = 0;
if (listener_may_exit) {
if (conns_this_child <= 0)
#if HAVE_SERF
if (listener_may_exit) {
while (num) {
blocking = 0;
if (!have_idle_worker) {
have_idle_worker = 0;
case CONN_STATE_LINGER_NORMAL:
case CONN_STATE_LINGER_SHORT:
ap_assert(0);
if (workers_were_busy) {
if (!listeners_disabled)
if (!listeners_disabled)
else if (listeners_disabled) {
listeners_disabled = 0;
if (!listeners_disabled) {
return NULL;
have_idle_worker = 0;
#if HAVE_SERF
out_pfd++;
num--;
listeners_disabled = 0;
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;
pchild);
for (i = 0; i < sizeof(good_methods) / sizeof(void*); i++) {
good_methods[i]);
* sizeof(apr_socket_t *));
for (i = 0; i < threads_per_child; i++) {
int status =
++loops;
return NULL;
if (listener) {
int iter;
iter = 0;
++iter;
for (i = 0; i < threads_per_child; i++) {
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
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;
int child_threads_active = 0;
for (j = 0; j < threads_per_child; j++) {
if (any_dead_threads
if (all_dead_threads) {
++free_length;
if (!any_dying_threads) {
last_non_dead = i;
if (had_healthy_child) {
"or Min/MaxSpareThreads), "
for (i = 0; i < free_length; ++i) {
int child_slot;
if (child_slot < 0
if (child_slot >= 0) {
for (i = 0; i < threads_per_child; i++)
else if (remaining_children_to_start
status) == 0) {
else if (remaining_children_to_start) {
return DONE;
set_signals();
if (!child_fatal) {
return DONE;
} else if (shutdown_pending) {
int active_children;
int index;
if (!child_fatal) {
if (ap_graceful_shutdown_timeout) {
shutdown_pending = 0;
active_children = 0;
return DONE;
if (one_process) {
return DONE;
/* wake up the children...time to die. But we'll have more soon */
return OK;
int startup = 0;
int level_flags = 0;
pconf = p;
return DONE;
if (!one_process) {
return DONE;
return OK;
if (debug) {
no_detach = 0;
if (!retained) {
return HTTP_INTERNAL_SERVER_ERROR;
return HTTP_INTERNAL_SERVER_ERROR;
had_healthy_child = 0;
ap_extended_status = 0;
return OK;
int startup = 0;
if (startup) {
if (startup) {
if (startup) {
if (startup) {
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;
const char *arg)
return err;
return NULL;
const char *arg)
double val;
char *endptr;
return err;
if (*endptr)
if (worker_factor == 0)
return NULL;
{NULL}