1
/* Licensed to the Apache Software Foundation (ASF) under one or more
2
* contributor license agreements. See the NOTICE file distributed with
3
* this work for additional information regarding copyright ownership.
4
* The ASF licenses this file to You under the Apache License, Version 2.0
5
* (the "License"); you may not use this file except in compliance with
6
* the License. You may obtain a copy of the License at
8
* http://www.apache.org/licenses/LICENSE-2.0
10
* Unless required by applicable law or agreed to in writing, software
11
* distributed under the License is distributed on an "AS IS" BASIS,
12
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
* See the License for the specific language governing permissions and
14
* limitations under the License.
18
* This MPM tries to fix the 'keep alive problem' in HTTP.
20
* After a client completes the first request, the client can keep the
21
* connection open to send more requests with the same socket. This can save
22
* signifigant overhead in creating TCP connections. However, the major
23
* disadvantage is that Apache traditionally keeps an entire child
24
* process/thread waiting for data from the client. To solve this problem,
25
* this MPM has a dedicated thread for handling both the Listenting sockets,
26
* and all sockets that are in a Keep Alive status.
28
* The MPM assumes the underlying apr_pollset implmentation is somewhat
29
* threadsafe. This currently is only compatible with KQueue and EPoll. This
30
* enables the MPM to avoid extra high level locking or having to wake up the
31
* listener thread when a keep-alive socket needs to be sent to it.
33
* This MPM not preform well on older platforms that do not have very good
34
* threading, like Linux with a 2.4 kernel, but this does not matter, since we
35
* require EPoll or KQueue.
37
* For FreeBSD, use 5.3. It is possible to run this MPM on FreeBSD 5.2.1, if
38
* you use libkse (see `man libmap.conf`).
40
* For NetBSD, use at least 2.0.
42
* For Linux, you should use a 2.6 kernel, and make sure your glibc has epoll
43
* support compiled in.
48
#include "apr_portable.h"
49
#include "apr_strings.h"
50
#include "apr_file_io.h"
51
#include "apr_thread_proc.h"
52
#include "apr_signal.h"
53
#include "apr_thread_mutex.h"
54
#include "apr_proc_mutex.h"
57
#include "apr_queue.h"
58
#define APR_WANT_STRFUNC
64
#if APR_HAVE_SYS_SOCKET_H
65
#include <sys/socket.h>
67
#if APR_HAVE_SYS_WAIT_H
70
#ifdef HAVE_SYS_PROCESSOR_H
71
#include <sys/processor.h> /* for bindprocessor() */
75
#error The Event MPM requires APR threads, but they are unavailable.
80
#include "ap_config.h"
82
#include "http_main.h"
84
#include "http_config.h" /* for read_config */
85
#include "http_core.h" /* for get_remote_host */
86
#include "http_connection.h"
89
#include "mpm_common.h"
90
#include "ap_listen.h"
91
#include "scoreboard.h"
93
#include "mpm_default.h"
94
#include "http_vhost.h"
97
#include <limits.h> /* for INT_MAX */
99
/* Limit on the total --- clients will be locked out if more servers than
100
* this are needed. It is intended solely to keep the server from crashing
101
* when things get out of hand.
103
* We keep a hard maximum number of servers, for two reasons --- first off,
104
* in case something goes seriously wrong, we want to stop the fork bomb
105
* short of actually crashing the machine we're running on by filling some
106
* kernel table. Secondly, it keeps the size of the scoreboard file small
107
* enough that we can read the whole thing without worrying too much about
110
#ifndef DEFAULT_SERVER_LIMIT
111
#define DEFAULT_SERVER_LIMIT 16
114
/* Admin can't tune ServerLimit beyond MAX_SERVER_LIMIT. We want
115
* some sort of compile-time limit to help catch typos.
117
#ifndef MAX_SERVER_LIMIT
118
#define MAX_SERVER_LIMIT 20000
121
/* Limit on the threads per process. Clients will be locked out if more than
124
* We keep this for one reason it keeps the size of the scoreboard file small
125
* enough that we can read the whole thing without worrying too much about
128
#ifndef DEFAULT_THREAD_LIMIT
129
#define DEFAULT_THREAD_LIMIT 64
132
/* Admin can't tune ThreadLimit beyond MAX_THREAD_LIMIT. We want
133
* some sort of compile-time limit to help catch typos.
135
#ifndef MAX_THREAD_LIMIT
136
#define MAX_THREAD_LIMIT 100000
140
* Actual definitions of config globals
143
int ap_threads_per_child = 0; /* Worker threads per child */
144
static int ap_daemons_to_start = 0;
145
static int min_spare_threads = 0;
146
static int max_spare_threads = 0;
147
static int ap_daemons_limit = 0;
148
static int server_limit = DEFAULT_SERVER_LIMIT;
149
static int first_server_limit = 0;
150
static int thread_limit = DEFAULT_THREAD_LIMIT;
151
static int first_thread_limit = 0;
152
static int changed_limit_at_restart;
153
static int dying = 0;
154
static int workers_may_exit = 0;
155
static int start_thread_may_exit = 0;
156
static int listener_may_exit = 0;
157
static int requests_this_child;
158
static int num_listensocks = 0;
159
static int resource_shortage = 0;
160
static fd_queue_t *worker_queue;
161
static fd_queue_info_t *worker_queue_info;
162
static int mpm_state = AP_MPMQ_STARTING;
163
static int sick_child_detected;
165
apr_thread_mutex_t *timeout_mutex;
166
APR_RING_HEAD(timeout_head_t, conn_state_t);
167
static struct timeout_head_t timeout_head;
169
static apr_pollset_t *event_pollset;
171
/* The structure used to pass unique initialization info to each thread */
179
/* Structure used to pass information to the thread responsible for
180
* creating the rest of the threads.
184
apr_thread_t **threads;
185
apr_thread_t *listener;
187
apr_threadattr_t *threadattr;
199
int status; /*XXX what is this for? 0 and 1 don't make it clear */
201
} listener_poll_type;
203
#define ID_FROM_CHILD_THREAD(c, t) ((c * thread_limit) + t)
206
* The max child slot ever assigned, preserved across restarts. Necessary
207
* to deal with MaxClients changes across AP_SIG_GRACEFUL restarts. We
208
* use this value to optimize routines that have to scan the entire
211
int ap_max_daemons_limit = -1;
213
static ap_pod_t *pod;
215
/* *Non*-shared http_main globals... */
217
server_rec *ap_server_conf;
219
/* The worker MPM respects a couple of runtime flags that can aid
220
* in debugging. Setting the -DNO_DETACH flag will prevent the root process
221
* from detaching from its controlling terminal. Additionally, setting
222
* the -DONE_PROCESS flag (which implies -DNO_DETACH) will get you the
223
* child_main loop running in the process which originally started up.
224
* This gives you a pretty nice debugging environment. (You'll get a SIGHUP
225
* early in standalone_main; just continue through. This is the server
226
* trying to kill off any child processes which it might have lying
227
* around --- Apache doesn't keep track of their pids, it just sends
228
* SIGHUP to the process group, ignoring it in the root process.
229
* Continue through and you'll be fine.).
232
static int one_process = 0;
235
int raise_sigstop_flags;
238
static apr_pool_t *pconf; /* Pool for config stuff */
239
static apr_pool_t *pchild; /* Pool for httpd child stuff */
241
static pid_t ap_my_pid; /* Linux getpid() doesn't work except in main
242
thread. Use this instead */
243
static pid_t parent_pid;
244
static apr_os_thread_t *listener_os_thread;
246
/* The LISTENER_SIGNAL signal will be sent from the main thread to the
247
* listener thread to wake it up for graceful termination (what a child
248
* process from an old generation does when the admin does "apachectl
249
* graceful"). This signal will be blocked in all threads of a child
250
* process except for the listener thread.
252
#define LISTENER_SIGNAL SIGHUP
254
/* An array of socket descriptors in use by each thread used to
255
* perform a non-graceful (forced) shutdown of the server.
257
static apr_socket_t **worker_sockets;
259
static void close_worker_sockets(void)
262
for (i = 0; i < ap_threads_per_child; i++) {
263
if (worker_sockets[i]) {
264
apr_socket_close(worker_sockets[i]);
265
worker_sockets[i] = NULL;
270
static void wakeup_listener(void)
272
listener_may_exit = 1;
273
if (!listener_os_thread) {
274
/* XXX there is an obscure path that this doesn't handle perfectly:
275
* right after listener thread is created but before
276
* listener_os_thread is set, the first worker thread hits an
277
* error and starts graceful termination
282
* we should just be able to "kill(ap_my_pid, LISTENER_SIGNAL)" on all
283
* platforms and wake up the listener thread since it is the only thread
284
* with SIGHUP unblocked, but that doesn't work on Linux
286
#ifdef HAVE_PTHREAD_KILL
287
pthread_kill(*listener_os_thread, LISTENER_SIGNAL);
289
kill(ap_my_pid, LISTENER_SIGNAL);
294
#define ST_GRACEFUL 1
295
#define ST_UNGRACEFUL 2
297
static int terminate_mode = ST_INIT;
299
static void signal_threads(int mode)
301
if (terminate_mode == mode) {
304
terminate_mode = mode;
305
mpm_state = AP_MPMQ_STOPPING;
307
/* in case we weren't called from the listener thread, wake up the
312
/* for ungraceful termination, let the workers exit now;
313
* for graceful termination, the listener thread will notify the
314
* workers to exit once it has stopped accepting new connections
316
if (mode == ST_UNGRACEFUL) {
317
workers_may_exit = 1;
318
ap_queue_interrupt_all(worker_queue);
319
ap_queue_info_term(worker_queue_info);
320
close_worker_sockets(); /* forcefully kill all current connections */
324
AP_DECLARE(apr_status_t) ap_mpm_query(int query_code, int *result)
326
switch (query_code) {
327
case AP_MPMQ_MAX_DAEMON_USED:
328
*result = ap_max_daemons_limit;
330
case AP_MPMQ_IS_THREADED:
331
*result = AP_MPMQ_STATIC;
333
case AP_MPMQ_IS_FORKED:
334
*result = AP_MPMQ_DYNAMIC;
336
case AP_MPMQ_IS_ASYNC:
339
case AP_MPMQ_HARD_LIMIT_DAEMONS:
340
*result = server_limit;
342
case AP_MPMQ_HARD_LIMIT_THREADS:
343
*result = thread_limit;
345
case AP_MPMQ_MAX_THREADS:
346
*result = ap_threads_per_child;
348
case AP_MPMQ_MIN_SPARE_DAEMONS:
351
case AP_MPMQ_MIN_SPARE_THREADS:
352
*result = min_spare_threads;
354
case AP_MPMQ_MAX_SPARE_DAEMONS:
357
case AP_MPMQ_MAX_SPARE_THREADS:
358
*result = max_spare_threads;
360
case AP_MPMQ_MAX_REQUESTS_DAEMON:
361
*result = ap_max_requests_per_child;
363
case AP_MPMQ_MAX_DAEMONS:
364
*result = ap_daemons_limit;
366
case AP_MPMQ_MPM_STATE:
373
/* a clean exit from a child with proper cleanup */
374
static void clean_child_exit(int code) __attribute__ ((noreturn));
375
static void clean_child_exit(int code)
377
mpm_state = AP_MPMQ_STOPPING;
379
apr_pool_destroy(pchild);
384
static void just_die(int sig)
389
/*****************************************************************
390
* Connection structures and accounting...
393
/* volatile just in case */
394
static int volatile shutdown_pending;
395
static int volatile restart_pending;
396
static int volatile is_graceful;
397
static volatile int child_fatal;
398
ap_generation_t volatile ap_my_generation;
401
* ap_start_shutdown() and ap_start_restart(), below, are a first stab at
402
* functions to initiate shutdown or restart without relying on signals.
403
* Previously this was initiated in sig_term() and restart() signal handlers,
404
* but we want to be able to start a shutdown/restart from other sources --
405
* e.g. on Win32, from the service manager. Now the service manager can
406
* call ap_start_shutdown() or ap_start_restart() as appropiate. Note that
407
* these functions can also be called by the child processes, since global
408
* variables are no longer used to pass on the required action to the parent.
410
* These should only be called from the parent process itself, since the
411
* parent process will use the shutdown_pending and restart_pending variables
412
* to determine whether to shutdown or restart. The child process should
413
* call signal_parent() directly to tell the parent to die -- this will
414
* cause neither of those variable to be set, which the parent will
415
* assume means something serious is wrong (which it will be, for the
416
* child to force an exit) and so do an exit anyway.
419
static void ap_start_shutdown(int graceful)
421
mpm_state = AP_MPMQ_STOPPING;
422
if (shutdown_pending == 1) {
423
/* Um, is this _probably_ not an error, if the user has
424
* tried to do a shutdown twice quickly, so we won't
425
* worry about reporting it.
429
shutdown_pending = 1;
430
is_graceful = graceful;
433
/* do a graceful restart if graceful == 1 */
434
static void ap_start_restart(int graceful)
436
mpm_state = AP_MPMQ_STOPPING;
437
if (restart_pending == 1) {
438
/* Probably not an error - don't bother reporting it */
442
is_graceful = graceful;
445
static void sig_term(int sig)
447
ap_start_shutdown(sig == AP_SIG_GRACEFUL_STOP);
450
static void restart(int sig)
452
ap_start_restart(sig == AP_SIG_GRACEFUL);
455
static void set_signals(void)
457
#ifndef NO_USE_SIGACTION
462
ap_fatal_signal_setup(ap_server_conf, pconf);
465
#ifndef NO_USE_SIGACTION
466
sigemptyset(&sa.sa_mask);
469
sa.sa_handler = sig_term;
470
if (sigaction(SIGTERM, &sa, NULL) < 0)
471
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
472
"sigaction(SIGTERM)");
473
#ifdef AP_SIG_GRACEFUL_STOP
474
if (sigaction(AP_SIG_GRACEFUL_STOP, &sa, NULL) < 0)
475
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
476
"sigaction(" AP_SIG_GRACEFUL_STOP_STRING ")");
479
if (sigaction(SIGINT, &sa, NULL) < 0)
480
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
481
"sigaction(SIGINT)");
484
sa.sa_handler = SIG_DFL;
485
if (sigaction(SIGXCPU, &sa, NULL) < 0)
486
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
487
"sigaction(SIGXCPU)");
490
sa.sa_handler = SIG_DFL;
491
if (sigaction(SIGXFSZ, &sa, NULL) < 0)
492
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
493
"sigaction(SIGXFSZ)");
496
sa.sa_handler = SIG_IGN;
497
if (sigaction(SIGPIPE, &sa, NULL) < 0)
498
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
499
"sigaction(SIGPIPE)");
502
/* we want to ignore HUPs and AP_SIG_GRACEFUL while we're busy
504
sigaddset(&sa.sa_mask, SIGHUP);
505
sigaddset(&sa.sa_mask, AP_SIG_GRACEFUL);
506
sa.sa_handler = restart;
507
if (sigaction(SIGHUP, &sa, NULL) < 0)
508
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
509
"sigaction(SIGHUP)");
510
if (sigaction(AP_SIG_GRACEFUL, &sa, NULL) < 0)
511
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
512
"sigaction(" AP_SIG_GRACEFUL_STRING ")");
516
apr_signal(SIGXCPU, SIG_DFL);
519
apr_signal(SIGXFSZ, SIG_DFL);
523
apr_signal(SIGTERM, sig_term);
525
apr_signal(SIGHUP, restart);
527
#ifdef AP_SIG_GRACEFUL
528
apr_signal(AP_SIG_GRACEFUL, restart);
529
#endif /* AP_SIG_GRACEFUL */
530
#ifdef AP_SIG_GRACEFUL_STOP
531
apr_signal(AP_SIG_GRACEFUL_STOP, sig_term);
532
#endif /* AP_SIG_GRACEFUL_STOP */
534
apr_signal(SIGPIPE, SIG_IGN);
540
/*****************************************************************
541
* Here follows a long bunch of generic server bookkeeping stuff...
544
int ap_graceful_stop_signalled(void)
545
/* XXX this is really a bad confusing obsolete name
546
* maybe it should be ap_mpm_process_exiting?
549
/* note: for a graceful termination, listener_may_exit will be set before
550
* workers_may_exit, so check listener_may_exit
552
return listener_may_exit;
555
/*****************************************************************
556
* Child process main loop.
559
static int process_socket(apr_pool_t * p, apr_socket_t * sock,
560
conn_state_t * cs, int my_child_num,
564
listener_poll_type *pt;
565
long conn_id = ID_FROM_CHILD_THREAD(my_child_num, my_thread_num);
568
apr_time_t time_now = 0;
571
ap_create_sb_handle(&sbh, p, my_child_num, my_thread_num);
572
apr_os_sock_get(&csd, sock);
574
time_now = apr_time_now();
576
if (cs == NULL) { /* This is a new connection */
578
cs = apr_pcalloc(p, sizeof(conn_state_t));
580
pt = apr_pcalloc(p, sizeof(*pt));
582
cs->bucket_alloc = apr_bucket_alloc_create(p);
583
c = ap_run_create_connection(p, ap_server_conf, sock,
584
conn_id, sbh, cs->bucket_alloc);
588
cs->pfd.desc_type = APR_POLL_SOCKET;
589
cs->pfd.reqevents = APR_POLLIN;
590
cs->pfd.desc.s = sock;
594
cs->pfd.client_data = pt;
596
ap_update_vhost_given_ip(c);
598
rc = ap_run_pre_connection(c, sock);
599
if (rc != OK && rc != DONE) {
600
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
601
"process_socket: connection aborted");
606
* XXX If the platform does not have a usable way of bundling
607
* accept() with a socket readability check, like Win32,
608
* and there are measurable delays before the
609
* socket is readable due to the first data packet arriving,
610
* it might be better to create the cs on the listener thread
611
* with the state set to CONN_STATE_CHECK_REQUEST_LINE_READABLE
613
* FreeBSD users will want to enable the HTTP accept filter
614
* module in their kernel for the highest performance
615
* When the accept filter is active, sockets are kept in the
616
* kernel until a HTTP request is received.
618
cs->state = CONN_STATE_READ_REQUEST_LINE;
626
if (cs->state == CONN_STATE_READ_REQUEST_LINE) {
628
ap_run_process_connection(c);
630
/* state will be updated upon return
631
* fall thru to either wait for readability/timeout or
636
cs->state = CONN_STATE_LINGER;
640
if (cs->state == CONN_STATE_LINGER) {
641
ap_lingering_close(c);
642
apr_bucket_alloc_destroy(cs->bucket_alloc);
644
ap_push_pool(worker_queue_info, p);
647
else if (cs->state == CONN_STATE_CHECK_REQUEST_LINE_READABLE) {
649
listener_poll_type *pt = (listener_poll_type *) cs->pfd.client_data;
651
/* It greatly simplifies the logic to use a single timeout value here
652
* because the new element can just be added to the end of the list and
653
* it will stay sorted in expiration time sequence. If brand new
654
* sockets are sent to the event thread for a readability check, this
655
* will be a slight behavior change - they use the non-keepalive
656
* timeout today. With a normal client, the socket will be readable in
657
* a few milliseconds anyway.
659
cs->expiration_time = ap_server_conf->keep_alive_timeout + time_now;
660
apr_thread_mutex_lock(timeout_mutex);
661
APR_RING_INSERT_TAIL(&timeout_head, cs, conn_state_t, timeout_list);
664
/* Add work to pollset. These are always read events */
665
rc = apr_pollset_add(event_pollset, &cs->pfd);
667
apr_thread_mutex_unlock(timeout_mutex);
669
if (rc != APR_SUCCESS) {
670
ap_log_error(APLOG_MARK, APLOG_ERR, rc, ap_server_conf,
671
"process_socket: apr_pollset_add failure");
672
AP_DEBUG_ASSERT(rc == APR_SUCCESS);
678
/* requests_this_child has gone to zero or below. See if the admin coded
679
"MaxRequestsPerChild 0", and keep going in that case. Doing it this way
680
simplifies the hot path in worker_thread */
681
static void check_infinite_requests(void)
683
if (ap_max_requests_per_child) {
684
signal_threads(ST_GRACEFUL);
687
/* wow! if you're executing this code, you may have set a record.
688
* either this child process has served over 2 billion requests, or
689
* you're running a threaded 2.0 on a 16 bit machine.
691
* I'll buy pizza and beers at Apachecon for the first person to do
692
* the former without cheating (dorking with INT_MAX, or running with
693
* uncommitted performance patches, for example).
695
* for the latter case, you probably deserve a beer too. Greg Ames
698
requests_this_child = INT_MAX; /* keep going */
702
static void unblock_signal(int sig)
706
sigemptyset(&sig_mask);
707
sigaddset(&sig_mask, sig);
708
#if defined(SIGPROCMASK_SETS_THREAD_MASK)
709
sigprocmask(SIG_UNBLOCK, &sig_mask, NULL);
711
pthread_sigmask(SIG_UNBLOCK, &sig_mask, NULL);
715
static void dummy_signal_handler(int sig)
717
/* XXX If specifying SIG_IGN is guaranteed to unblock a syscall,
718
* then we don't need this goofy function.
722
static apr_status_t push2worker(const apr_pollfd_t * pfd,
723
apr_pollset_t * pollset)
725
listener_poll_type *pt = (listener_poll_type *) pfd->client_data;
726
conn_state_t *cs = (conn_state_t *) pt->baton;
729
if (pt->status == 1) {
735
rc = apr_pollset_remove(pollset, pfd);
738
* Some of the pollset backends, like KQueue or Epoll
739
* automagically remove the FD if the socket is closed,
740
* therefore, we can accept _SUCCESS or _NOTFOUND,
741
* and we still want to keep going
743
if (rc != APR_SUCCESS && rc != APR_NOTFOUND) {
744
cs->state = CONN_STATE_LINGER;
747
rc = ap_queue_push(worker_queue, cs->pfd.desc.s, cs, cs->p);
748
if (rc != APR_SUCCESS) {
749
/* trash the connection; we couldn't queue the connected
752
apr_bucket_alloc_destroy(cs->bucket_alloc);
753
apr_socket_close(cs->pfd.desc.s);
754
ap_log_error(APLOG_MARK, APLOG_CRIT, rc,
755
ap_server_conf, "push2worker: ap_queue_push failed");
756
apr_pool_clear(cs->p);
757
ap_push_pool(worker_queue_info, cs->p);
764
* reserve a worker thread, block if all are currently busy.
765
* this prevents the worker queue from overflowing and lets
766
* other processes accept new connections in the mean time.
768
static int get_worker(int *have_idle_worker_p)
772
if (!*have_idle_worker_p) {
773
rc = ap_queue_info_wait_for_idler(worker_queue_info);
775
if (rc == APR_SUCCESS) {
776
*have_idle_worker_p = 1;
780
if (!APR_STATUS_IS_EOF(rc)) {
781
ap_log_error(APLOG_MARK, APLOG_ERR, rc, ap_server_conf,
782
"ap_queue_info_wait_for_idler failed. "
783
"Attempting to shutdown process gracefully");
784
signal_threads(ST_GRACEFUL);
790
/* already reserved a worker thread - must have hit a
791
* transient error on a previous pass
797
static void *listener_thread(apr_thread_t * thd, void *dummy)
800
proc_info *ti = dummy;
801
int process_slot = ti->pid;
802
apr_pool_t *tpool = apr_thread_pool_get(thd);
804
apr_pool_t *ptrans; /* Pool for per-transaction stuff */
806
int have_idle_worker = 0;
808
const apr_pollfd_t *out_pfd;
810
apr_time_t time_now = 0;
811
apr_interval_time_t timeout_interval;
812
apr_time_t timeout_time;
813
listener_poll_type *pt;
817
/* We set this to force apr_pollset to wakeup if there hasn't been any IO
818
* on any of its sockets. This allows sockets to have been added
819
* when no other keepalive operations where going on.
821
* current value is 1 second
823
timeout_interval = 1000000;
825
/* the following times out events that are really close in the future
826
* to prevent extra poll calls
828
* current value is .1 second
830
#define TIMEOUT_FUDGE_FACTOR 100000
832
/* POLLSET_SCALE_FACTOR * ap_threads_per_child sets the size of
833
* the pollset. I've seen 15 connections per active worker thread
836
* However, with the newer apr_pollset, this is the number of sockets that
837
* we will return to any *one* call to poll(). Therefore, there is no
838
* reason to make it more than ap_threads_per_child.
840
#define POLLSET_SCALE_FACTOR 1
842
rc = apr_thread_mutex_create(&timeout_mutex, APR_THREAD_MUTEX_DEFAULT,
844
if (rc != APR_SUCCESS) {
845
ap_log_error(APLOG_MARK, APLOG_ERR, rc, ap_server_conf,
846
"creation of the timeout mutex failed. Attempting to "
847
"shutdown process gracefully");
848
signal_threads(ST_GRACEFUL);
852
APR_RING_INIT(&timeout_head, conn_state_t, timeout_list);
854
/* Create the main pollset */
855
rc = apr_pollset_create(&event_pollset,
856
ap_threads_per_child * POLLSET_SCALE_FACTOR,
857
tpool, APR_POLLSET_THREADSAFE);
858
if (rc != APR_SUCCESS) {
859
ap_log_error(APLOG_MARK, APLOG_ERR, rc, ap_server_conf,
860
"apr_pollset_create with Thread Safety failed. "
861
"Attempting to shutdown process gracefully");
862
signal_threads(ST_GRACEFUL);
866
for (lr = ap_listeners; lr != NULL; lr = lr->next) {
867
apr_pollfd_t pfd = { 0 };
868
pt = apr_pcalloc(tpool, sizeof(*pt));
869
pfd.desc_type = APR_POLL_SOCKET;
871
pfd.reqevents = APR_POLLIN;
873
pt->type = PT_ACCEPT;
876
pfd.client_data = pt;
878
apr_socket_opt_set(pfd.desc.s, APR_SO_NONBLOCK, 1);
879
apr_pollset_add(event_pollset, &pfd);
882
/* Unblock the signal used to wake this thread up, and set a handler for
885
unblock_signal(LISTENER_SIGNAL);
886
apr_signal(LISTENER_SIGNAL, dummy_signal_handler);
888
while (!listener_may_exit) {
890
if (requests_this_child <= 0) {
891
check_infinite_requests();
894
rc = apr_pollset_poll(event_pollset, timeout_interval, &num,
897
if (rc != APR_SUCCESS) {
898
if (APR_STATUS_IS_EINTR(rc)) {
901
if (!APR_STATUS_IS_TIMEUP(rc)) {
902
ap_log_error(APLOG_MARK, APLOG_ERR, rc, ap_server_conf,
903
"apr_pollset_poll failed. Attempting to "
904
"shutdown process gracefully");
905
signal_threads(ST_GRACEFUL);
909
if (listener_may_exit)
912
while (num && get_worker(&have_idle_worker)) {
913
pt = (listener_poll_type *) out_pfd->client_data;
914
if (pt->type == PT_CSD) {
915
/* one of the sockets is readable */
916
cs = (conn_state_t *) pt->baton;
918
case CONN_STATE_CHECK_REQUEST_LINE_READABLE:
919
cs->state = CONN_STATE_READ_REQUEST_LINE;
922
ap_log_error(APLOG_MARK, APLOG_ERR, rc,
924
"event_loop: unexpected state %d",
929
apr_thread_mutex_lock(timeout_mutex);
930
APR_RING_REMOVE(cs, timeout_list);
931
apr_thread_mutex_unlock(timeout_mutex);
933
rc = push2worker(out_pfd, event_pollset);
934
if (rc != APR_SUCCESS) {
935
ap_log_error(APLOG_MARK, APLOG_CRIT, rc,
936
ap_server_conf, "push2worker failed");
939
have_idle_worker = 0;
943
/* A Listener Socket is ready for an accept() */
944
apr_pool_t *recycled_pool = NULL;
946
lr = (ap_listen_rec *) pt->baton;
948
ap_pop_pool(&recycled_pool, worker_queue_info);
950
if (recycled_pool == NULL) {
951
/* create a new transaction pool for each accepted socket */
952
apr_allocator_t *allocator;
954
apr_allocator_create(&allocator);
955
apr_allocator_max_free_set(allocator,
957
apr_pool_create_ex(&ptrans, pconf, NULL, allocator);
958
apr_allocator_owner_set(allocator, ptrans);
959
if (ptrans == NULL) {
960
ap_log_error(APLOG_MARK, APLOG_CRIT, rc,
962
"Failed to create transaction pool");
963
signal_threads(ST_GRACEFUL);
968
ptrans = recycled_pool;
971
apr_pool_tag(ptrans, "transaction");
973
rc = lr->accept_func(&csd, lr, ptrans);
975
/* later we trash rv and rely on csd to indicate
978
AP_DEBUG_ASSERT(rc == APR_SUCCESS || !csd);
980
if (rc == APR_EGENERAL) {
981
/* E[NM]FILE, ENOMEM, etc */
982
resource_shortage = 1;
983
signal_threads(ST_GRACEFUL);
987
rc = ap_queue_push(worker_queue, csd, NULL, ptrans);
988
if (rc != APR_SUCCESS) {
989
/* trash the connection; we couldn't queue the connected
992
apr_socket_close(csd);
993
ap_log_error(APLOG_MARK, APLOG_CRIT, rc,
995
"ap_queue_push failed");
996
apr_pool_clear(ptrans);
997
ap_push_pool(worker_queue_info, ptrans);
1000
have_idle_worker = 0;
1004
apr_pool_clear(ptrans);
1005
ap_push_pool(worker_queue_info, ptrans);
1007
} /* if:else on pt->type */
1010
} /* while for processing poll */
1012
/* XXX possible optimization: stash the current time for use as
1013
* r->request_time for new requests
1015
time_now = apr_time_now();
1017
/* handle timed out sockets */
1018
apr_thread_mutex_lock(timeout_mutex);
1020
cs = APR_RING_FIRST(&timeout_head);
1021
timeout_time = time_now + TIMEOUT_FUDGE_FACTOR;
1022
while (!APR_RING_EMPTY(&timeout_head, conn_state_t, timeout_list)
1023
&& cs->expiration_time < timeout_time
1024
&& get_worker(&have_idle_worker)) {
1026
cs->state = CONN_STATE_LINGER;
1028
APR_RING_REMOVE(cs, timeout_list);
1030
rc = push2worker(&cs->pfd, event_pollset);
1032
if (rc != APR_SUCCESS) {
1034
/* XXX return NULL looks wrong - not an init failure
1035
* that bypasses all the cleanup outside the main loop
1036
* break seems more like it
1037
* need to evaluate seriousness of push2worker failures
1040
have_idle_worker = 0;
1041
cs = APR_RING_FIRST(&timeout_head);
1043
apr_thread_mutex_unlock(timeout_mutex);
1045
} /* listener main loop */
1047
ap_close_listeners();
1048
ap_queue_term(worker_queue);
1050
ap_scoreboard_image->parent[process_slot].quiescing = 1;
1052
/* wake up the main thread */
1053
kill(ap_my_pid, SIGTERM);
1055
apr_thread_exit(thd, APR_SUCCESS);
1059
/* XXX For ungraceful termination/restart, we definitely don't want to
1060
* wait for active connections to finish but we may want to wait
1061
* for idle workers to get out of the queue code and release mutexes,
1062
* since those mutexes are cleaned up pretty soon and some systems
1063
* may not react favorably (i.e., segfault) if operations are attempted
1064
* on cleaned-up mutexes.
1066
static void *APR_THREAD_FUNC worker_thread(apr_thread_t * thd, void *dummy)
1068
proc_info *ti = dummy;
1069
int process_slot = ti->pid;
1070
int thread_slot = ti->tid;
1071
apr_socket_t *csd = NULL;
1073
apr_pool_t *ptrans; /* Pool for per-transaction stuff */
1079
ap_scoreboard_image->servers[process_slot][thread_slot].pid = ap_my_pid;
1080
ap_scoreboard_image->servers[process_slot][thread_slot].generation = ap_my_generation;
1081
ap_update_child_status_from_indexes(process_slot, thread_slot,
1082
SERVER_STARTING, NULL);
1084
while (!workers_may_exit) {
1086
rv = ap_queue_info_set_idle(worker_queue_info, NULL);
1087
if (rv != APR_SUCCESS) {
1088
ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
1089
"ap_queue_info_set_idle failed. Attempting to "
1090
"shutdown process gracefully.");
1091
signal_threads(ST_GRACEFUL);
1097
ap_update_child_status_from_indexes(process_slot, thread_slot,
1098
SERVER_READY, NULL);
1100
if (workers_may_exit) {
1103
rv = ap_queue_pop(worker_queue, &csd, &cs, &ptrans);
1105
if (rv != APR_SUCCESS) {
1106
/* We get APR_EOF during a graceful shutdown once all the
1107
* connections accepted by this server process have been handled.
1109
if (APR_STATUS_IS_EOF(rv)) {
1112
/* We get APR_EINTR whenever ap_queue_pop() has been interrupted
1113
* from an explicit call to ap_queue_interrupt_all(). This allows
1114
* us to unblock threads stuck in ap_queue_pop() when a shutdown
1117
* If workers_may_exit is set and this is ungraceful termination/
1118
* restart, we are bound to get an error on some systems (e.g.,
1119
* AIX, which sanity-checks mutex operations) since the queue
1120
* may have already been cleaned up. Don't log the "error" if
1121
* workers_may_exit is set.
1123
else if (APR_STATUS_IS_EINTR(rv)) {
1126
/* We got some other error. */
1127
else if (!workers_may_exit) {
1128
ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
1129
"ap_queue_pop failed");
1134
worker_sockets[thread_slot] = csd;
1135
rv = process_socket(ptrans, csd, cs, process_slot, thread_slot);
1137
requests_this_child--;
1139
worker_sockets[thread_slot] = NULL;
1142
ap_update_child_status_from_indexes(process_slot, thread_slot,
1143
(dying) ? SERVER_DEAD :
1145
(request_rec *) NULL);
1147
apr_thread_exit(thd, APR_SUCCESS);
1151
static int check_signal(int signum)
1163
static void create_listener_thread(thread_starter * ts)
1165
int my_child_num = ts->child_num_arg;
1166
apr_threadattr_t *thread_attr = ts->threadattr;
1170
my_info = (proc_info *) malloc(sizeof(proc_info));
1171
my_info->pid = my_child_num;
1172
my_info->tid = -1; /* listener thread doesn't have a thread slot */
1174
rv = apr_thread_create(&ts->listener, thread_attr, listener_thread,
1176
if (rv != APR_SUCCESS) {
1177
ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
1178
"apr_thread_create: unable to create listener thread");
1179
/* let the parent decide how bad this really is */
1180
clean_child_exit(APEXIT_CHILDSICK);
1182
apr_os_thread_get(&listener_os_thread, ts->listener);
1185
/* XXX under some circumstances not understood, children can get stuck
1186
* in start_threads forever trying to take over slots which will
1187
* never be cleaned up; for now there is an APLOG_DEBUG message issued
1188
* every so often when this condition occurs
1190
static void *APR_THREAD_FUNC start_threads(apr_thread_t * thd, void *dummy)
1192
thread_starter *ts = dummy;
1193
apr_thread_t **threads = ts->threads;
1194
apr_threadattr_t *thread_attr = ts->threadattr;
1195
int child_num_arg = ts->child_num_arg;
1196
int my_child_num = child_num_arg;
1200
int threads_created = 0;
1201
int listener_started = 0;
1203
int prev_threads_created;
1205
/* We must create the fd queues before we start up the listener
1206
* and worker threads. */
1207
worker_queue = apr_pcalloc(pchild, sizeof(*worker_queue));
1208
rv = ap_queue_init(worker_queue, ap_threads_per_child, pchild);
1209
if (rv != APR_SUCCESS) {
1210
ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
1211
"ap_queue_init() failed");
1212
clean_child_exit(APEXIT_CHILDFATAL);
1215
rv = ap_queue_info_create(&worker_queue_info, pchild,
1216
ap_threads_per_child);
1217
if (rv != APR_SUCCESS) {
1218
ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
1219
"ap_queue_info_create() failed");
1220
clean_child_exit(APEXIT_CHILDFATAL);
1223
worker_sockets = apr_pcalloc(pchild, ap_threads_per_child
1224
* sizeof(apr_socket_t *));
1226
loops = prev_threads_created = 0;
1228
/* ap_threads_per_child does not include the listener thread */
1229
for (i = 0; i < ap_threads_per_child; i++) {
1231
ap_scoreboard_image->servers[child_num_arg][i].status;
1233
if (status != SERVER_GRACEFUL && status != SERVER_DEAD) {
1237
my_info = (proc_info *) malloc(sizeof(proc_info));
1238
if (my_info == NULL) {
1239
ap_log_error(APLOG_MARK, APLOG_ALERT, errno, ap_server_conf,
1240
"malloc: out of memory");
1241
clean_child_exit(APEXIT_CHILDFATAL);
1243
my_info->pid = my_child_num;
1247
/* We are creating threads right now */
1248
ap_update_child_status_from_indexes(my_child_num, i,
1249
SERVER_STARTING, NULL);
1250
/* We let each thread update its own scoreboard entry. This is
1251
* done because it lets us deal with tid better.
1253
rv = apr_thread_create(&threads[i], thread_attr,
1254
worker_thread, my_info, pchild);
1255
if (rv != APR_SUCCESS) {
1256
ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
1257
"apr_thread_create: unable to create worker thread");
1258
/* let the parent decide how bad this really is */
1259
clean_child_exit(APEXIT_CHILDSICK);
1264
/* Start the listener only when there are workers available */
1265
if (!listener_started && threads_created) {
1266
create_listener_thread(ts);
1267
listener_started = 1;
1271
if (start_thread_may_exit || threads_created == ap_threads_per_child) {
1274
/* wait for previous generation to clean up an entry */
1275
apr_sleep(apr_time_from_sec(1));
1277
if (loops % 120 == 0) { /* every couple of minutes */
1278
if (prev_threads_created == threads_created) {
1279
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
1280
"child %" APR_PID_T_FMT " isn't taking over "
1281
"slots very quickly (%d of %d)",
1282
ap_my_pid, threads_created,
1283
ap_threads_per_child);
1285
prev_threads_created = threads_created;
1289
/* What state should this child_main process be listed as in the
1291
* ap_update_child_status_from_indexes(my_child_num, i, SERVER_STARTING,
1292
* (request_rec *) NULL);
1294
* This state should be listed separately in the scoreboard, in some kind
1295
* of process_status, not mixed in with the worker threads' status.
1296
* "life_status" is almost right, but it's in the worker's structure, and
1297
* the name could be clearer. gla
1299
apr_thread_exit(thd, APR_SUCCESS);
1303
static void join_workers(apr_thread_t * listener, apr_thread_t ** threads)
1306
apr_status_t rv, thread_rv;
1311
/* deal with a rare timing window which affects waking up the
1312
* listener thread... if the signal sent to the listener thread
1313
* is delivered between the time it verifies that the
1314
* listener_may_exit flag is clear and the time it enters a
1315
* blocking syscall, the signal didn't do any good... work around
1316
* that by sleeping briefly and sending it again
1321
#ifdef HAVE_PTHREAD_KILL
1322
pthread_kill(*listener_os_thread, 0)
1327
/* listener not dead yet */
1328
apr_sleep(apr_time_make(0, 500000));
1333
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
1334
"the listener thread didn't exit");
1337
rv = apr_thread_join(&thread_rv, listener);
1338
if (rv != APR_SUCCESS) {
1339
ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
1340
"apr_thread_join: unable to join listener thread");
1345
for (i = 0; i < ap_threads_per_child; i++) {
1346
if (threads[i]) { /* if we ever created this thread */
1347
rv = apr_thread_join(&thread_rv, threads[i]);
1348
if (rv != APR_SUCCESS) {
1349
ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
1350
"apr_thread_join: unable to join worker "
1357
static void join_start_thread(apr_thread_t * start_thread_id)
1359
apr_status_t rv, thread_rv;
1361
start_thread_may_exit = 1; /* tell it to give up in case it is still
1362
* trying to take over slots from a
1363
* previous generation
1365
rv = apr_thread_join(&thread_rv, start_thread_id);
1366
if (rv != APR_SUCCESS) {
1367
ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
1368
"apr_thread_join: unable to join the start " "thread");
1372
static void child_main(int child_num_arg)
1374
apr_thread_t **threads;
1377
apr_threadattr_t *thread_attr;
1378
apr_thread_t *start_thread_id;
1380
mpm_state = AP_MPMQ_STARTING; /* for benefit of any hooks that run as this
1383
ap_my_pid = getpid();
1384
ap_fatal_signal_child_setup(ap_server_conf);
1385
apr_pool_create(&pchild, pconf);
1387
/*stuff to do before we switch id's, so we have permissions. */
1388
ap_reopen_scoreboard(pchild, NULL, 0);
1390
if (unixd_setup_child()) {
1391
clean_child_exit(APEXIT_CHILDFATAL);
1394
ap_run_child_init(pchild, ap_server_conf);
1396
/* done with init critical section */
1398
/* Just use the standard apr_setup_signal_thread to block all signals
1399
* from being received. The child processes no longer use signals for
1400
* any communication with the parent process.
1402
rv = apr_setup_signal_thread();
1403
if (rv != APR_SUCCESS) {
1404
ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
1405
"Couldn't initialize signal thread");
1406
clean_child_exit(APEXIT_CHILDFATAL);
1409
if (ap_max_requests_per_child) {
1410
requests_this_child = ap_max_requests_per_child;
1413
/* coding a value of zero means infinity */
1414
requests_this_child = INT_MAX;
1417
/* Setup worker threads */
1419
/* clear the storage; we may not create all our threads immediately,
1420
* and we want a 0 entry to indicate a thread which was not created
1422
threads = (apr_thread_t **) calloc(1,
1423
sizeof(apr_thread_t *) *
1424
ap_threads_per_child);
1425
if (threads == NULL) {
1426
ap_log_error(APLOG_MARK, APLOG_ALERT, errno, ap_server_conf,
1427
"malloc: out of memory");
1428
clean_child_exit(APEXIT_CHILDFATAL);
1431
ts = (thread_starter *) apr_palloc(pchild, sizeof(*ts));
1433
apr_threadattr_create(&thread_attr, pchild);
1434
/* 0 means PTHREAD_CREATE_JOINABLE */
1435
apr_threadattr_detach_set(thread_attr, 0);
1437
if (ap_thread_stacksize != 0) {
1438
apr_threadattr_stacksize_set(thread_attr, ap_thread_stacksize);
1441
ts->threads = threads;
1442
ts->listener = NULL;
1443
ts->child_num_arg = child_num_arg;
1444
ts->threadattr = thread_attr;
1446
rv = apr_thread_create(&start_thread_id, thread_attr, start_threads,
1448
if (rv != APR_SUCCESS) {
1449
ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
1450
"apr_thread_create: unable to create worker thread");
1451
/* let the parent decide how bad this really is */
1452
clean_child_exit(APEXIT_CHILDSICK);
1455
mpm_state = AP_MPMQ_RUNNING;
1457
/* If we are only running in one_process mode, we will want to
1458
* still handle signals. */
1460
/* Block until we get a terminating signal. */
1461
apr_signal_thread(check_signal);
1462
/* make sure the start thread has finished; signal_threads()
1463
* and join_workers() depend on that
1465
/* XXX join_start_thread() won't be awakened if one of our
1466
* threads encounters a critical error and attempts to
1467
* shutdown this child
1469
join_start_thread(start_thread_id);
1471
/* helps us terminate a little more quickly than the dispatch of the
1472
* signal thread; beats the Pipe of Death and the browsers
1474
signal_threads(ST_UNGRACEFUL);
1476
/* A terminating signal was received. Now join each of the
1477
* workers to clean them up.
1478
* If the worker already exited, then the join frees
1479
* their resources and returns.
1480
* If the worker hasn't exited, then this blocks until
1481
* they have (then cleans up).
1483
join_workers(ts->listener, threads);
1485
else { /* !one_process */
1486
/* remove SIGTERM from the set of blocked signals... if one of
1487
* the other threads in the process needs to take us down
1488
* (e.g., for MaxRequestsPerChild) it will send us SIGTERM
1490
unblock_signal(SIGTERM);
1491
apr_signal(SIGTERM, dummy_signal_handler);
1492
/* Watch for any messages from the parent over the POD */
1494
rv = ap_mpm_pod_check(pod);
1495
if (rv == AP_NORESTART) {
1496
/* see if termination was triggered while we slept */
1497
switch (terminate_mode) {
1506
if (rv == AP_GRACEFUL || rv == AP_RESTART) {
1507
/* make sure the start thread has finished;
1508
* signal_threads() and join_workers depend on that
1510
join_start_thread(start_thread_id);
1511
signal_threads(rv ==
1512
AP_GRACEFUL ? ST_GRACEFUL : ST_UNGRACEFUL);
1517
/* A terminating signal was received. Now join each of the
1518
* workers to clean them up.
1519
* If the worker already exited, then the join frees
1520
* their resources and returns.
1521
* If the worker hasn't exited, then this blocks until
1522
* they have (then cleans up).
1524
join_workers(ts->listener, threads);
1529
clean_child_exit(resource_shortage ? APEXIT_CHILDSICK : 0);
1532
static int make_child(server_rec * s, int slot)
1536
if (slot + 1 > ap_max_daemons_limit) {
1537
ap_max_daemons_limit = slot + 1;
1542
ap_scoreboard_image->parent[slot].pid = getpid();
1546
if ((pid = fork()) == -1) {
1547
ap_log_error(APLOG_MARK, APLOG_ERR, errno, s,
1548
"fork: Unable to fork new process");
1550
/* fork didn't succeed. Fix the scoreboard or else
1551
* it will say SERVER_STARTING forever and ever
1553
ap_update_child_status_from_indexes(slot, 0, SERVER_DEAD, NULL);
1555
/* In case system resources are maxxed out, we don't want
1556
Apache running away with the CPU trying to fork over and
1557
over and over again. */
1558
apr_sleep(apr_time_from_sec(10));
1564
#ifdef HAVE_BINDPROCESSOR
1565
/* By default, AIX binds to a single processor. This bit unbinds
1566
* children which will then bind to another CPU.
1568
int status = bindprocessor(BINDPROCESS, (int) getpid(),
1569
PROCESSOR_CLASS_ANY);
1571
ap_log_error(APLOG_MARK, APLOG_WARNING, errno,
1573
"processor unbind failed %d", status);
1575
RAISE_SIGSTOP(MAKE_CHILD);
1577
apr_signal(SIGTERM, just_die);
1580
clean_child_exit(0);
1583
ap_scoreboard_image->parent[slot].quiescing = 0;
1584
ap_scoreboard_image->parent[slot].pid = pid;
1588
/* start up a bunch of children */
1589
static void startup_children(int number_to_start)
1593
for (i = 0; number_to_start && i < ap_daemons_limit; ++i) {
1594
if (ap_scoreboard_image->parent[i].pid != 0) {
1597
if (make_child(ap_server_conf, i) < 0) {
1606
* idle_spawn_rate is the number of children that will be spawned on the
1607
* next maintenance cycle if there aren't enough idle servers. It is
1608
* doubled up to MAX_SPAWN_RATE, and reset only when a cycle goes by
1609
* without the need to spawn.
1611
static int idle_spawn_rate = 1;
1612
#ifndef MAX_SPAWN_RATE
1613
#define MAX_SPAWN_RATE (32)
1615
static int hold_off_on_exponential_spawning;
1617
static void perform_idle_server_maintenance(void)
1620
int idle_thread_count;
1624
int totally_free_length = 0;
1625
int free_slots[MAX_SPAWN_RATE];
1628
int active_thread_count = 0;
1630
/* initialize the free_list */
1633
idle_thread_count = 0;
1637
for (i = 0; i < ap_daemons_limit; ++i) {
1638
/* Initialization to satisfy the compiler. It doesn't know
1639
* that ap_threads_per_child is always > 0 */
1640
int status = SERVER_DEAD;
1641
int any_dying_threads = 0;
1642
int any_dead_threads = 0;
1643
int all_dead_threads = 1;
1645
if (i >= ap_max_daemons_limit
1646
&& totally_free_length == idle_spawn_rate)
1648
ps = &ap_scoreboard_image->parent[i];
1649
for (j = 0; j < ap_threads_per_child; j++) {
1650
ws = &ap_scoreboard_image->servers[i][j];
1651
status = ws->status;
1653
/* XXX any_dying_threads is probably no longer needed GLA */
1654
any_dying_threads = any_dying_threads ||
1655
(status == SERVER_GRACEFUL);
1656
any_dead_threads = any_dead_threads || (status == SERVER_DEAD);
1657
all_dead_threads = all_dead_threads &&
1658
(status == SERVER_DEAD || status == SERVER_GRACEFUL);
1660
/* We consider a starting server as idle because we started it
1661
* at least a cycle ago, and if it still hasn't finished starting
1662
* then we're just going to swamp things worse by forking more.
1663
* So we hopefully won't need to fork more if we count it.
1664
* This depends on the ordering of SERVER_READY and SERVER_STARTING.
1666
if (ps->pid != 0) { /* XXX just set all_dead_threads in outer
1667
for loop if no pid? not much else matters */
1668
if (status <= SERVER_READY &&
1669
!ps->quiescing && ps->generation == ap_my_generation) {
1670
++idle_thread_count;
1672
if (status >= SERVER_READY && status < SERVER_GRACEFUL) {
1673
++active_thread_count;
1677
if (any_dead_threads
1678
&& totally_free_length < idle_spawn_rate
1679
&& free_length < MAX_SPAWN_RATE
1680
&& (!ps->pid /* no process in the slot */
1681
|| ps->quiescing)) { /* or at least one is going away */
1682
if (all_dead_threads) {
1683
/* great! we prefer these, because the new process can
1684
* start more threads sooner. So prioritize this slot
1685
* by putting it ahead of any slots with active threads.
1687
* first, make room by moving a slot that's potentially still
1688
* in use to the end of the array
1690
free_slots[free_length] = free_slots[totally_free_length];
1691
free_slots[totally_free_length++] = i;
1694
/* slot is still in use - back of the bus
1696
free_slots[free_length] = i;
1700
/* XXX if (!ps->quiescing) is probably more reliable GLA */
1701
if (!any_dying_threads) {
1707
if (sick_child_detected) {
1708
if (active_thread_count > 0) {
1709
/* some child processes appear to be working. don't kill the
1712
sick_child_detected = 0;
1715
/* looks like a basket case. give up.
1717
shutdown_pending = 1;
1719
ap_log_error(APLOG_MARK, APLOG_ALERT, 0,
1721
"No active workers found..."
1722
" Apache is exiting!");
1723
/* the child already logged the failure details */
1728
ap_max_daemons_limit = last_non_dead + 1;
1730
if (idle_thread_count > max_spare_threads) {
1731
/* Kill off one child */
1732
ap_mpm_pod_signal(pod, TRUE);
1733
idle_spawn_rate = 1;
1735
else if (idle_thread_count < min_spare_threads) {
1736
/* terminate the free list */
1737
if (free_length == 0) {
1738
/* only report this condition once */
1739
static int reported = 0;
1742
ap_log_error(APLOG_MARK, APLOG_ERR, 0,
1744
"server reached MaxClients setting, consider"
1745
" raising the MaxClients setting");
1748
idle_spawn_rate = 1;
1751
if (free_length > idle_spawn_rate) {
1752
free_length = idle_spawn_rate;
1754
if (idle_spawn_rate >= 8) {
1755
ap_log_error(APLOG_MARK, APLOG_INFO, 0,
1757
"server seems busy, (you may need "
1758
"to increase StartServers, ThreadsPerChild "
1759
"or Min/MaxSpareThreads), "
1760
"spawning %d children, there are around %d idle "
1761
"threads, and %d total children", free_length,
1762
idle_thread_count, total_non_dead);
1764
for (i = 0; i < free_length; ++i) {
1765
make_child(ap_server_conf, free_slots[i]);
1767
/* the next time around we want to spawn twice as many if this
1768
* wasn't good enough, but not if we've just done a graceful
1770
if (hold_off_on_exponential_spawning) {
1771
--hold_off_on_exponential_spawning;
1773
else if (idle_spawn_rate < MAX_SPAWN_RATE) {
1774
idle_spawn_rate *= 2;
1779
idle_spawn_rate = 1;
1783
static void server_main_loop(int remaining_children_to_start)
1786
apr_exit_why_e exitwhy;
1787
int status, processed_status;
1791
while (!restart_pending && !shutdown_pending) {
1792
ap_wait_or_timeout(&exitwhy, &status, &pid, pconf);
1794
if (pid.pid != -1) {
1795
processed_status = ap_process_child_status(&pid, exitwhy, status);
1796
if (processed_status == APEXIT_CHILDFATAL) {
1797
shutdown_pending = 1;
1801
else if (processed_status == APEXIT_CHILDSICK) {
1802
/* tell perform_idle_server_maintenance to check into this
1803
* on the next timer pop
1805
sick_child_detected = 1;
1807
/* non-fatal death... note that it's gone in the scoreboard. */
1808
child_slot = find_child_by_pid(&pid);
1809
if (child_slot >= 0) {
1810
for (i = 0; i < ap_threads_per_child; i++)
1811
ap_update_child_status_from_indexes(child_slot, i,
1813
(request_rec *) NULL);
1815
ap_scoreboard_image->parent[child_slot].pid = 0;
1816
ap_scoreboard_image->parent[child_slot].quiescing = 0;
1817
if (processed_status == APEXIT_CHILDSICK) {
1818
/* resource shortage, minimize the fork rate */
1819
idle_spawn_rate = 1;
1821
else if (remaining_children_to_start
1822
&& child_slot < ap_daemons_limit) {
1823
/* we're still doing a 1-for-1 replacement of dead
1824
* children with new children
1826
make_child(ap_server_conf, child_slot);
1827
--remaining_children_to_start;
1829
#if APR_HAS_OTHER_CHILD
1831
else if (apr_proc_other_child_alert(&pid, APR_OC_REASON_DEATH,
1836
else if (is_graceful) {
1837
/* Great, we've probably just lost a slot in the
1838
* scoreboard. Somehow we don't know about this child.
1840
ap_log_error(APLOG_MARK, APLOG_WARNING, 0,
1842
"long lost child came home! (pid %ld)",
1845
/* Don't perform idle maintenance when a child dies,
1846
* only do it when there's a timeout. Remember only a
1847
* finite number of children can die, and it's pretty
1848
* pathological for a lot to die suddenly.
1852
else if (remaining_children_to_start) {
1853
/* we hit a 1 second timeout in which none of the previous
1854
* generation of children needed to be reaped... so assume
1855
* they're all done, and pick up the slack if any is left.
1857
startup_children(remaining_children_to_start);
1858
remaining_children_to_start = 0;
1859
/* In any event we really shouldn't do the code below because
1860
* few of the servers we just started are in the IDLE state
1861
* yet, so we'd mistakenly create an extra server.
1866
perform_idle_server_maintenance();
1870
int ap_mpm_run(apr_pool_t * _pconf, apr_pool_t * plog, server_rec * s)
1872
int remaining_children_to_start;
1874
ap_log_pid(pconf, ap_pid_fname);
1876
first_server_limit = server_limit;
1877
first_thread_limit = thread_limit;
1879
if (changed_limit_at_restart) {
1880
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
1881
"WARNING: Attempt to change ServerLimit or ThreadLimit "
1882
"ignored during restart");
1883
changed_limit_at_restart = 0;
1887
if (ap_run_pre_mpm(s->process->pool, SB_SHARED) != OK) {
1888
mpm_state = AP_MPMQ_STOPPING;
1891
/* fix the generation number in the global score; we just got a new,
1892
* cleared scoreboard
1894
ap_scoreboard_image->global->running_generation = ap_my_generation;
1898
/* Don't thrash... */
1899
if (max_spare_threads < min_spare_threads + ap_threads_per_child)
1900
max_spare_threads = min_spare_threads + ap_threads_per_child;
1902
/* If we're doing a graceful_restart then we're going to see a lot
1903
* of children exiting immediately when we get into the main loop
1904
* below (because we just sent them AP_SIG_GRACEFUL). This happens pretty
1905
* rapidly... and for each one that exits we'll start a new one until
1906
* we reach at least daemons_min_free. But we may be permitted to
1907
* start more than that, so we'll just keep track of how many we're
1908
* supposed to start up without the 1 second penalty between each fork.
1910
remaining_children_to_start = ap_daemons_to_start;
1911
if (remaining_children_to_start > ap_daemons_limit) {
1912
remaining_children_to_start = ap_daemons_limit;
1915
startup_children(remaining_children_to_start);
1916
remaining_children_to_start = 0;
1919
/* give the system some time to recover before kicking into
1920
* exponential mode */
1921
hold_off_on_exponential_spawning = 10;
1924
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
1925
"%s configured -- resuming normal operations",
1926
ap_get_server_version());
1927
ap_log_error(APLOG_MARK, APLOG_INFO, 0, ap_server_conf,
1928
"Server built: %s", ap_get_server_built());
1930
restart_pending = shutdown_pending = 0;
1931
mpm_state = AP_MPMQ_RUNNING;
1933
server_main_loop(remaining_children_to_start);
1934
mpm_state = AP_MPMQ_STOPPING;
1936
if (shutdown_pending && !is_graceful) {
1937
/* Time to shut down:
1938
* Kill child processes, tell them to call child_exit, etc...
1940
ap_mpm_pod_killpg(pod, ap_daemons_limit, FALSE);
1941
ap_reclaim_child_processes(1); /* Start with SIGTERM */
1944
/* cleanup pid file on normal shutdown */
1945
const char *pidfile = NULL;
1946
pidfile = ap_server_root_relative(pconf, ap_pid_fname);
1947
if (pidfile != NULL && unlink(pidfile) == 0)
1948
ap_log_error(APLOG_MARK, APLOG_INFO, 0,
1950
"removed PID file %s (pid=%ld)",
1951
pidfile, (long) getpid());
1953
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0,
1954
ap_server_conf, "caught SIGTERM, shutting down");
1957
} else if (shutdown_pending) {
1958
/* Time to gracefully shut down:
1959
* Kill child processes, tell them to call child_exit, etc...
1961
int active_children;
1963
apr_time_t cutoff = 0;
1965
/* Close our listeners, and then ask our children to do same */
1966
ap_close_listeners();
1967
ap_mpm_pod_killpg(pod, ap_daemons_limit, TRUE);
1968
ap_relieve_child_processes();
1971
/* cleanup pid file on normal shutdown */
1972
const char *pidfile = NULL;
1973
pidfile = ap_server_root_relative (pconf, ap_pid_fname);
1974
if ( pidfile != NULL && unlink(pidfile) == 0)
1975
ap_log_error(APLOG_MARK, APLOG_INFO, 0,
1977
"removed PID file %s (pid=%ld)",
1978
pidfile, (long)getpid());
1980
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
1981
"caught " AP_SIG_GRACEFUL_STOP_STRING
1982
", shutting down gracefully");
1985
if (ap_graceful_shutdown_timeout) {
1986
cutoff = apr_time_now() +
1987
apr_time_from_sec(ap_graceful_shutdown_timeout);
1990
/* Don't really exit until each child has finished */
1991
shutdown_pending = 0;
1993
/* Pause for a second */
1994
apr_sleep(apr_time_from_sec(1));
1996
/* Relieve any children which have now exited */
1997
ap_relieve_child_processes();
1999
active_children = 0;
2000
for (index = 0; index < ap_daemons_limit; ++index) {
2001
if (MPM_CHILD_PID(index) != 0) {
2002
if (kill(MPM_CHILD_PID(index), 0) == 0) {
2003
active_children = 1;
2004
/* Having just one child is enough to stay around */
2009
} while (!shutdown_pending && active_children &&
2010
(!ap_graceful_shutdown_timeout || apr_time_now() < cutoff));
2012
/* We might be here because we received SIGTERM, either
2013
* way, try and make sure that all of our processes are
2016
ap_mpm_pod_killpg(pod, ap_daemons_limit, FALSE);
2017
ap_reclaim_child_processes(1);
2022
/* we've been told to restart */
2023
apr_signal(SIGHUP, SIG_IGN);
2026
/* not worth thinking about */
2030
/* advance to the next generation */
2031
/* XXX: we really need to make sure this new generation number isn't in
2032
* use by any of the children.
2035
ap_scoreboard_image->global->running_generation = ap_my_generation;
2038
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
2039
AP_SIG_GRACEFUL_STRING
2040
" received. Doing graceful restart");
2041
/* wake up the children...time to die. But we'll have more soon */
2042
ap_mpm_pod_killpg(pod, ap_daemons_limit, TRUE);
2045
/* This is mostly for debugging... so that we know what is still
2046
* gracefully dealing with existing request.
2051
/* Kill 'em all. Since the child acts the same on the parents SIGTERM
2052
* and a SIGHUP, we may as well use the same signal, because some user
2053
* pthreads are stealing signals from us left and right.
2055
ap_mpm_pod_killpg(pod, ap_daemons_limit, FALSE);
2057
ap_reclaim_child_processes(1); /* Start with SIGTERM */
2058
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
2059
"SIGHUP received. Attempting to restart");
2065
/* This really should be a post_config hook, but the error log is already
2066
* redirected by that point, so we need to do this in the open_logs phase.
2068
static int worker_open_logs(apr_pool_t * p, apr_pool_t * plog,
2069
apr_pool_t * ptemp, server_rec * s)
2076
if ((num_listensocks = ap_setup_listeners(ap_server_conf)) < 1) {
2077
ap_log_error(APLOG_MARK, APLOG_ALERT | APLOG_STARTUP, 0,
2078
NULL, "no listening sockets available, shutting down");
2083
if ((rv = ap_mpm_pod_open(pconf, &pod))) {
2084
ap_log_error(APLOG_MARK, APLOG_CRIT | APLOG_STARTUP, rv, NULL,
2085
"Could not open pipe-of-death.");
2092
static int worker_pre_config(apr_pool_t * pconf, apr_pool_t * plog,
2095
static int restart_num = 0;
2096
int no_detach, debug, foreground;
2097
ap_directive_t *pdir;
2098
ap_directive_t *max_clients = NULL;
2101
mpm_state = AP_MPMQ_STARTING;
2103
/* make sure that "ThreadsPerChild" gets set before "MaxClients" */
2104
for (pdir = ap_conftree; pdir != NULL; pdir = pdir->next) {
2105
if (strncasecmp(pdir->directive, "ThreadsPerChild", 15) == 0) {
2107
/* we're in the clear, got ThreadsPerChild first */
2111
/* now to swap the data */
2112
ap_directive_t temp;
2114
temp.directive = pdir->directive;
2115
temp.args = pdir->args;
2116
/* Make sure you don't change 'next', or you may get loops! */
2117
/* XXX: first_child, parent, and data can never be set
2118
* for these directives, right? -aaron */
2119
temp.filename = pdir->filename;
2120
temp.line_num = pdir->line_num;
2122
pdir->directive = max_clients->directive;
2123
pdir->args = max_clients->args;
2124
pdir->filename = max_clients->filename;
2125
pdir->line_num = max_clients->line_num;
2127
max_clients->directive = temp.directive;
2128
max_clients->args = temp.args;
2129
max_clients->filename = temp.filename;
2130
max_clients->line_num = temp.line_num;
2134
else if (!max_clients
2135
&& strncasecmp(pdir->directive, "MaxClients", 10) == 0) {
2140
debug = ap_exists_config_define("DEBUG");
2143
foreground = one_process = 1;
2147
one_process = ap_exists_config_define("ONE_PROCESS");
2148
no_detach = ap_exists_config_define("NO_DETACH");
2149
foreground = ap_exists_config_define("FOREGROUND");
2152
/* sigh, want this only the second time around */
2153
if (restart_num++ == 1) {
2155
rv = apr_pollset_create(&event_pollset, 1, plog,
2156
APR_POLLSET_THREADSAFE);
2157
if (rv != APR_SUCCESS) {
2158
ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL,
2159
"Couldn't create a Thread Safe Pollset. "
2160
"Is it supported on your platform?");
2161
return HTTP_INTERNAL_SERVER_ERROR;
2163
apr_pollset_destroy(event_pollset);
2165
if (!one_process && !foreground) {
2166
rv = apr_proc_detach(no_detach ? APR_PROC_DETACH_FOREGROUND
2167
: APR_PROC_DETACH_DAEMONIZE);
2168
if (rv != APR_SUCCESS) {
2169
ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL,
2170
"apr_proc_detach failed");
2171
return HTTP_INTERNAL_SERVER_ERROR;
2174
parent_pid = ap_my_pid = getpid();
2177
unixd_pre_config(ptemp);
2178
ap_listen_pre_config();
2179
ap_daemons_to_start = DEFAULT_START_DAEMON;
2180
min_spare_threads = DEFAULT_MIN_FREE_DAEMON * DEFAULT_THREADS_PER_CHILD;
2181
max_spare_threads = DEFAULT_MAX_FREE_DAEMON * DEFAULT_THREADS_PER_CHILD;
2182
ap_daemons_limit = server_limit;
2183
ap_threads_per_child = DEFAULT_THREADS_PER_CHILD;
2184
ap_pid_fname = DEFAULT_PIDLOG;
2185
ap_lock_fname = DEFAULT_LOCKFILE;
2186
ap_max_requests_per_child = DEFAULT_MAX_REQUESTS_PER_CHILD;
2187
ap_extended_status = 0;
2188
#ifdef AP_MPM_WANT_SET_MAX_MEM_FREE
2189
ap_max_mem_free = APR_ALLOCATOR_MAX_FREE_UNLIMITED;
2192
apr_cpystrn(ap_coredump_dir, ap_server_root, sizeof(ap_coredump_dir));
2197
static void event_hooks(apr_pool_t * p)
2199
/* The worker open_logs phase must run before the core's, or stderr
2200
* will be redirected to a file, and the messages won't print to the
2203
static const char *const aszSucc[] = { "core.c", NULL };
2206
ap_hook_open_logs(worker_open_logs, NULL, aszSucc, APR_HOOK_MIDDLE);
2207
/* we need to set the MPM state before other pre-config hooks use MPM query
2208
* to retrieve it, so register as REALLY_FIRST
2210
ap_hook_pre_config(worker_pre_config, NULL, NULL, APR_HOOK_REALLY_FIRST);
2213
static const char *set_daemons_to_start(cmd_parms *cmd, void *dummy,
2216
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
2221
ap_daemons_to_start = atoi(arg);
2225
static const char *set_min_spare_threads(cmd_parms * cmd, void *dummy,
2228
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
2233
min_spare_threads = atoi(arg);
2234
if (min_spare_threads <= 0) {
2235
ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
2236
"WARNING: detected MinSpareThreads set to non-positive.");
2237
ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
2238
"Resetting to 1 to avoid almost certain Apache failure.");
2239
ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
2240
"Please read the documentation.");
2241
min_spare_threads = 1;
2247
static const char *set_max_spare_threads(cmd_parms * cmd, void *dummy,
2250
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
2255
max_spare_threads = atoi(arg);
2259
static const char *set_max_clients(cmd_parms * cmd, void *dummy,
2263
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
2268
/* It is ok to use ap_threads_per_child here because we are
2269
* sure that it gets set before MaxClients in the pre_config stage. */
2270
max_clients = atoi(arg);
2271
if (max_clients < ap_threads_per_child) {
2272
ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
2273
"WARNING: MaxClients (%d) must be at least as large",
2275
ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
2276
" as ThreadsPerChild (%d). Automatically",
2277
ap_threads_per_child);
2278
ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
2279
" increasing MaxClients to %d.", ap_threads_per_child);
2280
max_clients = ap_threads_per_child;
2282
ap_daemons_limit = max_clients / ap_threads_per_child;
2283
if ((max_clients > 0) && (max_clients % ap_threads_per_child)) {
2284
ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
2285
"WARNING: MaxClients (%d) is not an integer multiple",
2287
ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
2288
" of ThreadsPerChild (%d), lowering MaxClients to %d",
2289
ap_threads_per_child,
2290
ap_daemons_limit * ap_threads_per_child);
2291
ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
2292
" for a maximum of %d child processes,",
2294
max_clients = ap_daemons_limit * ap_threads_per_child;
2296
if (ap_daemons_limit > server_limit) {
2297
ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
2298
"WARNING: MaxClients of %d would require %d servers,",
2299
max_clients, ap_daemons_limit);
2300
ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
2301
" and would exceed the ServerLimit value of %d.",
2303
ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
2304
" Automatically lowering MaxClients to %d. To increase,",
2305
server_limit * ap_threads_per_child);
2306
ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
2307
" please see the ServerLimit directive.");
2308
ap_daemons_limit = server_limit;
2310
else if (ap_daemons_limit < 1) {
2311
ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
2312
"WARNING: Require MaxClients > 0, setting to 1");
2313
ap_daemons_limit = 1;
2318
static const char *set_threads_per_child(cmd_parms * cmd, void *dummy,
2321
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
2326
ap_threads_per_child = atoi(arg);
2327
if (ap_threads_per_child > thread_limit) {
2328
ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
2329
"WARNING: ThreadsPerChild of %d exceeds ThreadLimit "
2330
"value of %d", ap_threads_per_child, thread_limit);
2331
ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
2332
"threads, lowering ThreadsPerChild to %d. To increase, "
2333
"please see the", thread_limit);
2334
ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
2335
" ThreadLimit directive.");
2336
ap_threads_per_child = thread_limit;
2338
else if (ap_threads_per_child < 1) {
2339
ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
2340
"WARNING: Require ThreadsPerChild > 0, setting to 1");
2341
ap_threads_per_child = 1;
2345
static const char *set_server_limit (cmd_parms *cmd, void *dummy, const char *arg)
2347
int tmp_server_limit;
2349
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
2354
tmp_server_limit = atoi(arg);
2355
/* you cannot change ServerLimit across a restart; ignore
2358
if (first_server_limit &&
2359
tmp_server_limit != server_limit) {
2360
/* how do we log a message? the error log is a bit bucket at this
2361
* point; we'll just have to set a flag so that ap_mpm_run()
2362
* logs a warning later
2364
changed_limit_at_restart = 1;
2367
server_limit = tmp_server_limit;
2369
if (server_limit > MAX_SERVER_LIMIT) {
2370
ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
2371
"WARNING: ServerLimit of %d exceeds compile time limit "
2372
"of %d servers,", server_limit, MAX_SERVER_LIMIT);
2373
ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
2374
" lowering ServerLimit to %d.", MAX_SERVER_LIMIT);
2375
server_limit = MAX_SERVER_LIMIT;
2377
else if (server_limit < 1) {
2378
ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
2379
"WARNING: Require ServerLimit > 0, setting to 1");
2385
static const char *set_thread_limit(cmd_parms * cmd, void *dummy,
2388
int tmp_thread_limit;
2390
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
2395
tmp_thread_limit = atoi(arg);
2396
/* you cannot change ThreadLimit across a restart; ignore
2399
if (first_thread_limit && tmp_thread_limit != thread_limit) {
2400
/* how do we log a message? the error log is a bit bucket at this
2401
* point; we'll just have to set a flag so that ap_mpm_run()
2402
* logs a warning later
2404
changed_limit_at_restart = 1;
2407
thread_limit = tmp_thread_limit;
2409
if (thread_limit > MAX_THREAD_LIMIT) {
2410
ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
2411
"WARNING: ThreadLimit of %d exceeds compile time limit "
2412
"of %d servers,", thread_limit, MAX_THREAD_LIMIT);
2413
ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
2414
" lowering ThreadLimit to %d.", MAX_THREAD_LIMIT);
2415
thread_limit = MAX_THREAD_LIMIT;
2417
else if (thread_limit < 1) {
2418
ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
2419
"WARNING: Require ThreadLimit > 0, setting to 1");
2425
static const command_rec event_cmds[] = {
2426
UNIX_DAEMON_COMMANDS,
2428
AP_INIT_TAKE1("StartServers", set_daemons_to_start, NULL, RSRC_CONF,
2429
"Number of child processes launched at server startup"),
2430
AP_INIT_TAKE1("ServerLimit", set_server_limit, NULL, RSRC_CONF,
2431
"Maximum number of child processes for this run of Apache"),
2432
AP_INIT_TAKE1("MinSpareThreads", set_min_spare_threads, NULL, RSRC_CONF,
2433
"Minimum number of idle threads, to handle request spikes"),
2434
AP_INIT_TAKE1("MaxSpareThreads", set_max_spare_threads, NULL, RSRC_CONF,
2435
"Maximum number of idle threads"),
2436
AP_INIT_TAKE1("MaxClients", set_max_clients, NULL, RSRC_CONF,
2437
"Maximum number of threads alive at the same time"),
2438
AP_INIT_TAKE1("ThreadsPerChild", set_threads_per_child, NULL, RSRC_CONF,
2439
"Number of threads each child creates"),
2440
AP_INIT_TAKE1("ThreadLimit", set_thread_limit, NULL, RSRC_CONF,
2441
"Maximum number of worker threads per child process for this "
2442
"run of Apache - Upper limit for ThreadsPerChild"),
2443
AP_GRACEFUL_SHUTDOWN_TIMEOUT_COMMAND,
2447
module AP_MODULE_DECLARE_DATA mpm_event_module = {
2449
ap_mpm_rewrite_args, /* hook to run before apache parses args */
2450
NULL, /* create per-directory config structure */
2451
NULL, /* merge per-directory config structures */
2452
NULL, /* create per-server config structure */
2453
NULL, /* merge per-server config structures */
2454
event_cmds, /* command apr_table_t */
2455
event_hooks /* register_hooks */