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
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
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.
15 */
16
17 /**
18 * This MPM tries to fix the 'keep alive problem' in HTTP.
19 *
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 * significant 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 Listening sockets,
26 * and all sockets that are in a Keep Alive status.
27 *
28 * The MPM assumes the underlying apr_pollset implementation 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.
32 *
33 * This MPM does not perform 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.
36 *
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`).
39 *
40 * For NetBSD, use at least 2.0.
41 *
42 * For Linux, you should use a 2.6 kernel, and make sure your glibc has epoll
43 * support compiled in.
44 *
45 */
46
47 #include "apr.h"
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_poll.h"
55 #include "apr_ring.h"
56 #include "apr_queue.h"
57 #include "apr_atomic.h"
58 #define APR_WANT_STRFUNC
59 #include "apr_want.h"
60 #include "apr_version.h"
61
62 #if APR_HAVE_UNISTD_H
63 #include <unistd.h>
64 #endif
65 #if APR_HAVE_SYS_SOCKET_H
66 #include <sys/socket.h>
67 #endif
68 #if APR_HAVE_SYS_WAIT_H
69 #include <sys/wait.h>
70 #endif
71 #ifdef HAVE_SYS_PROCESSOR_H
72 #include <sys/processor.h> /* for bindprocessor() */
73 #endif
74
75 #if !APR_HAS_THREADS
76 #error The Event MPM requires APR threads, but they are unavailable.
77 #endif
78
79 #include "ap_config.h"
80 #include "httpd.h"
81 #include "http_main.h"
82 #include "http_log.h"
83 #include "http_config.h" /* for read_config */
84 #include "http_core.h" /* for get_remote_host */
85 #include "http_connection.h"
86 #include "ap_mpm.h"
87 #include "pod.h"
88 #include "mpm_common.h"
89 #include "ap_listen.h"
90 #include "scoreboard.h"
91 #include "fdqueue.h"
92 #include "mpm_default.h"
93 #include "http_vhost.h"
94 #include "unixd.h"
95
96 #include <signal.h>
97 #include <limits.h> /* for INT_MAX */
98
99
100 /* Limit on the total --- clients will be locked out if more servers than
101 * this are needed. It is intended solely to keep the server from crashing
102 * when things get out of hand.
103 *
104 * We keep a hard maximum number of servers, for two reasons --- first off,
105 * in case something goes seriously wrong, we want to stop the fork bomb
106 * short of actually crashing the machine we're running on by filling some
107 * kernel table. Secondly, it keeps the size of the scoreboard file small
108 * enough that we can read the whole thing without worrying too much about
109 * the overhead.
110 */
111 #ifndef DEFAULT_SERVER_LIMIT
112 #define DEFAULT_SERVER_LIMIT 16
113 #endif
114
115 /* Admin can't tune ServerLimit beyond MAX_SERVER_LIMIT. We want
116 * some sort of compile-time limit to help catch typos.
117 */
118 #ifndef MAX_SERVER_LIMIT
119 #define MAX_SERVER_LIMIT 20000
120 #endif
121
122 /* Limit on the threads per process. Clients will be locked out if more than
123 * this are needed.
124 *
125 * We keep this for one reason it keeps the size of the scoreboard file small
126 * enough that we can read the whole thing without worrying too much about
127 * the overhead.
128 */
129 #ifndef DEFAULT_THREAD_LIMIT
130 #define DEFAULT_THREAD_LIMIT 64
131 #endif
132
133 /* Admin can't tune ThreadLimit beyond MAX_THREAD_LIMIT. We want
134 * some sort of compile-time limit to help catch typos.
135 */
136 #ifndef MAX_THREAD_LIMIT
137 #define MAX_THREAD_LIMIT 100000
138 #endif
139
140 #define MPM_CHILD_PID(i) (ap_scoreboard_image->parent[i].pid)
141
142 #if !APR_VERSION_AT_LEAST(1,4,0)
143 #define apr_time_from_msec(x) (x * 1000)
144 #endif
145
146 #ifndef MAX_SECS_TO_LINGER
147 #define MAX_SECS_TO_LINGER 30
148 #endif
149 #define SECONDS_TO_LINGER 2
150
151 /*
152 * Actual definitions of config globals
153 */
154
155 #ifndef DEFAULT_WORKER_FACTOR
156 #define DEFAULT_WORKER_FACTOR 2
157 #endif
158 #define WORKER_FACTOR_SCALE 16 /* scale factor to allow fractional values */
159 static unsigned int worker_factor = DEFAULT_WORKER_FACTOR * WORKER_FACTOR_SCALE;
160
161 static int threads_per_child = 0; /* Worker threads per child */
162 static int ap_daemons_to_start = 0;
163 static int min_spare_threads = 0;
164 static int max_spare_threads = 0;
165 static int ap_daemons_limit = 0;
166 static int max_workers = 0;
167 static int server_limit = 0;
168 static int thread_limit = 0;
169 static int had_healthy_child = 0;
170 static int dying = 0;
171 static int workers_may_exit = 0;
172 static int start_thread_may_exit = 0;
173 static int listener_may_exit = 0;
174 static int num_listensocks = 0;
175 static apr_int32_t conns_this_child; /* MaxConnectionsPerChild, only access
176 in listener thread */
177 static apr_uint32_t connection_count = 0; /* Number of open connections */
178 static apr_uint32_t lingering_count = 0; /* Number of connections in lingering close */
179 static apr_uint32_t suspended_count = 0; /* Number of suspended connections */
180 static apr_uint32_t clogged_count = 0; /* Number of threads processing ssl conns */
181 static int resource_shortage = 0;
182 static fd_queue_t *worker_queue;
183 static fd_queue_info_t *worker_queue_info;
184 static int mpm_state = AP_MPMQ_STARTING;
185
186 static apr_thread_mutex_t *timeout_mutex;
187
188 struct event_conn_state_t {
189 /** APR_RING of expiration timeouts */
190 APR_RING_ENTRY(event_conn_state_t) timeout_list;
191 /** the expiration time of the next keepalive timeout */
192 apr_time_t expiration_time;
193 /** connection record this struct refers to */
194 conn_rec *c;
195 /** memory pool to allocate from */
196 apr_pool_t *p;
197 /** bucket allocator */
198 apr_bucket_alloc_t *bucket_alloc;
199 /** poll file descriptor information */
200 apr_pollfd_t pfd;
201 /** public parts of the connection state */
202 conn_state_t pub;
203 };
204 APR_RING_HEAD(timeout_head_t, event_conn_state_t);
205
206 struct timeout_queue {
207 struct timeout_head_t head;
208 int count;
209 const char *tag;
210 };
211 /*
212 * Several timeout queues that use different timeouts, so that we always can
213 * simply append to the end.
214 * write_completion_q uses TimeOut
215 * keepalive_q uses KeepAliveTimeOut
216 * linger_q uses MAX_SECS_TO_LINGER
217 * short_linger_q uses SECONDS_TO_LINGER
218 */
219 static struct timeout_queue write_completion_q, keepalive_q, linger_q,
220 short_linger_q;
221 static apr_pollfd_t *listener_pollfd;
222
223 /*
224 * Macros for accessing struct timeout_queue.
225 * For TO_QUEUE_APPEND and TO_QUEUE_REMOVE, timeout_mutex must be held.
226 */
227 #define TO_QUEUE_APPEND(q, el) \
228 do { \
229 APR_RING_INSERT_TAIL(&(q).head, el, event_conn_state_t, timeout_list); \
230 (q).count++; \
231 } while (0)
232
233 #define TO_QUEUE_REMOVE(q, el) \
234 do { \
235 APR_RING_REMOVE(el, timeout_list); \
236 (q).count--; \
237 } while (0)
238
239 #define TO_QUEUE_INIT(q) \
240 do { \
241 APR_RING_INIT(&(q).head, event_conn_state_t, timeout_list); \
242 (q).tag = #q; \
243 } while (0)
244
245 #define TO_QUEUE_ELEM_INIT(el) APR_RING_ELEM_INIT(el, timeout_list)
246
247 /*
248 * The pollset for sockets that are in any of the timeout queues. Currently
249 * we use the timeout_mutex to make sure that connections are added/removed
250 * atomically to/from both event_pollset and a timeout queue. Otherwise
251 * some confusion can happen under high load if timeout queues and pollset
252 * get out of sync.
253 * XXX: It should be possible to make the lock unnecessary in many or even all
254 * XXX: cases.
255 */
256 static apr_pollset_t *event_pollset;
257
258 /* The structure used to pass unique initialization info to each thread */
259 typedef struct
260 {
261 int pid;
262 int tid;
263 int sd;
264 } proc_info;
265
266 /* Structure used to pass information to the thread responsible for
267 * creating the rest of the threads.
268 */
269 typedef struct
270 {
271 apr_thread_t **threads;
272 apr_thread_t *listener;
273 int child_num_arg;
274 apr_threadattr_t *threadattr;
275 } thread_starter;
276
277 typedef enum
278 {
279 PT_CSD,
280 PT_ACCEPT
281 } poll_type_e;
282
283 typedef struct
284 {
285 poll_type_e type;
286 void *baton;
287 } listener_poll_type;
288
289 /* data retained by event across load/unload of the module
290 * allocated on first call to pre-config hook; located on
291 * subsequent calls to pre-config hook
292 */
293 typedef struct event_retained_data {
294 int first_server_limit;
295 int first_thread_limit;
296 int module_loads;
297 int sick_child_detected;
298 ap_generation_t my_generation;
299 int volatile is_graceful; /* set from signal handler */
300 int maxclients_reported;
301 /*
302 * The max child slot ever assigned, preserved across restarts. Necessary
303 * to deal with MaxRequestWorkers changes across AP_SIG_GRACEFUL restarts.
304 * We use this value to optimize routines that have to scan the entire
305 * scoreboard.
306 */
307 int max_daemons_limit;
308 /*
309 * idle_spawn_rate is the number of children that will be spawned on the
310 * next maintenance cycle if there aren't enough idle servers. It is
311 * doubled up to MAX_SPAWN_RATE, and reset only when a cycle goes by
312 * without the need to spawn.
313 */
314 int idle_spawn_rate;
315 #ifndef MAX_SPAWN_RATE
316 #define MAX_SPAWN_RATE (32)
317 #endif
318 int hold_off_on_exponential_spawning;
319 } event_retained_data;
320 static event_retained_data *retained;
321
322 #define ID_FROM_CHILD_THREAD(c, t) ((c * thread_limit) + t)
323
324 static ap_event_pod_t *pod;
325
326 /* The event MPM respects a couple of runtime flags that can aid
327 * in debugging. Setting the -DNO_DETACH flag will prevent the root process
328 * from detaching from its controlling terminal. Additionally, setting
329 * the -DONE_PROCESS flag (which implies -DNO_DETACH) will get you the
330 * child_main loop running in the process which originally started up.
331 * This gives you a pretty nice debugging environment. (You'll get a SIGHUP
332 * early in standalone_main; just continue through. This is the server
333 * trying to kill off any child processes which it might have lying
334 * around --- Apache doesn't keep track of their pids, it just sends
335 * SIGHUP to the process group, ignoring it in the root process.
336 * Continue through and you'll be fine.).
337 */
338
339 static int one_process = 0;
340
341 #ifdef DEBUG_SIGSTOP
342 int raise_sigstop_flags;
343 #endif
344
345 static apr_pool_t *pconf; /* Pool for config stuff */
346 static apr_pool_t *pchild; /* Pool for httpd child stuff */
347
348 static pid_t ap_my_pid; /* Linux getpid() doesn't work except in main
349 thread. Use this instead */
350 static pid_t parent_pid;
351 static apr_os_thread_t *listener_os_thread;
352
353 /* The LISTENER_SIGNAL signal will be sent from the main thread to the
354 * listener thread to wake it up for graceful termination (what a child
355 * process from an old generation does when the admin does "apachectl
356 * graceful"). This signal will be blocked in all threads of a child
357 * process except for the listener thread.
358 */
359 #define LISTENER_SIGNAL SIGHUP
360
361 /* An array of socket descriptors in use by each thread used to
362 * perform a non-graceful (forced) shutdown of the server.
363 */
364 static apr_socket_t **worker_sockets;
365
disable_listensocks(int process_slot)366 static void disable_listensocks(int process_slot)
367 {
368 int i;
369 for (i = 0; i < num_listensocks; i++) {
370 apr_pollset_remove(event_pollset, &listener_pollfd[i]);
371 }
372 ap_scoreboard_image->parent[process_slot].not_accepting = 1;
373 }
374
enable_listensocks(int process_slot)375 static void enable_listensocks(int process_slot)
376 {
377 int i;
378 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(00457)
379 "Accepting new connections again: "
380 "%u active conns (%u lingering/%u clogged/%u suspended), "
381 "%u idle workers",
382 apr_atomic_read32(&connection_count),
383 apr_atomic_read32(&lingering_count),
384 apr_atomic_read32(&clogged_count),
385 apr_atomic_read32(&suspended_count),
386 ap_queue_info_get_idlers(worker_queue_info));
387 for (i = 0; i < num_listensocks; i++)
388 apr_pollset_add(event_pollset, &listener_pollfd[i]);
389 /*
390 * XXX: This is not yet optimal. If many workers suddenly become available,
391 * XXX: the parent may kill some processes off too soon.
392 */
393 ap_scoreboard_image->parent[process_slot].not_accepting = 0;
394 }
395
close_worker_sockets(void)396 static void close_worker_sockets(void)
397 {
398 int i;
399 for (i = 0; i < threads_per_child; i++) {
400 if (worker_sockets[i]) {
401 apr_socket_close(worker_sockets[i]);
402 worker_sockets[i] = NULL;
403 }
404 }
405 }
406
wakeup_listener(void)407 static void wakeup_listener(void)
408 {
409 listener_may_exit = 1;
410 if (!listener_os_thread) {
411 /* XXX there is an obscure path that this doesn't handle perfectly:
412 * right after listener thread is created but before
413 * listener_os_thread is set, the first worker thread hits an
414 * error and starts graceful termination
415 */
416 return;
417 }
418
419 /* unblock the listener if it's waiting for a worker */
420 ap_queue_info_term(worker_queue_info);
421
422 /*
423 * we should just be able to "kill(ap_my_pid, LISTENER_SIGNAL)" on all
424 * platforms and wake up the listener thread since it is the only thread
425 * with SIGHUP unblocked, but that doesn't work on Linux
426 */
427 #ifdef HAVE_PTHREAD_KILL
428 pthread_kill(*listener_os_thread, LISTENER_SIGNAL);
429 #else
430 kill(ap_my_pid, LISTENER_SIGNAL);
431 #endif
432 }
433
434 #define ST_INIT 0
435 #define ST_GRACEFUL 1
436 #define ST_UNGRACEFUL 2
437
438 static int terminate_mode = ST_INIT;
439
signal_threads(int mode)440 static void signal_threads(int mode)
441 {
442 if (terminate_mode == mode) {
443 return;
444 }
445 terminate_mode = mode;
446 mpm_state = AP_MPMQ_STOPPING;
447
448 /* in case we weren't called from the listener thread, wake up the
449 * listener thread
450 */
451 wakeup_listener();
452
453 /* for ungraceful termination, let the workers exit now;
454 * for graceful termination, the listener thread will notify the
455 * workers to exit once it has stopped accepting new connections
456 */
457 if (mode == ST_UNGRACEFUL) {
458 workers_may_exit = 1;
459 ap_queue_interrupt_all(worker_queue);
460 close_worker_sockets(); /* forcefully kill all current connections */
461 }
462 }
463
event_query(int query_code,int * result,apr_status_t * rv)464 static int event_query(int query_code, int *result, apr_status_t *rv)
465 {
466 *rv = APR_SUCCESS;
467 switch (query_code) {
468 case AP_MPMQ_MAX_DAEMON_USED:
469 *result = retained->max_daemons_limit;
470 break;
471 case AP_MPMQ_IS_THREADED:
472 *result = AP_MPMQ_STATIC;
473 break;
474 case AP_MPMQ_IS_FORKED:
475 *result = AP_MPMQ_DYNAMIC;
476 break;
477 case AP_MPMQ_IS_ASYNC:
478 *result = 1;
479 break;
480 case AP_MPMQ_HARD_LIMIT_DAEMONS:
481 *result = server_limit;
482 break;
483 case AP_MPMQ_HARD_LIMIT_THREADS:
484 *result = thread_limit;
485 break;
486 case AP_MPMQ_MAX_THREADS:
487 *result = threads_per_child;
488 break;
489 case AP_MPMQ_MIN_SPARE_DAEMONS:
490 *result = 0;
491 break;
492 case AP_MPMQ_MIN_SPARE_THREADS:
493 *result = min_spare_threads;
494 break;
495 case AP_MPMQ_MAX_SPARE_DAEMONS:
496 *result = 0;
497 break;
498 case AP_MPMQ_MAX_SPARE_THREADS:
499 *result = max_spare_threads;
500 break;
501 case AP_MPMQ_MAX_REQUESTS_DAEMON:
502 *result = ap_max_requests_per_child;
503 break;
504 case AP_MPMQ_MAX_DAEMONS:
505 *result = ap_daemons_limit;
506 break;
507 case AP_MPMQ_MPM_STATE:
508 *result = mpm_state;
509 break;
510 case AP_MPMQ_GENERATION:
511 *result = retained->my_generation;
512 break;
513 default:
514 *rv = APR_ENOTIMPL;
515 break;
516 }
517 return OK;
518 }
519
event_note_child_killed(int childnum,pid_t pid,ap_generation_t gen)520 static void event_note_child_killed(int childnum, pid_t pid, ap_generation_t gen)
521 {
522 if (childnum != -1) { /* child had a scoreboard slot? */
523 ap_run_child_status(ap_server_conf,
524 ap_scoreboard_image->parent[childnum].pid,
525 ap_scoreboard_image->parent[childnum].generation,
526 childnum, MPM_CHILD_EXITED);
527 ap_scoreboard_image->parent[childnum].pid = 0;
528 }
529 else {
530 ap_run_child_status(ap_server_conf, pid, gen, -1, MPM_CHILD_EXITED);
531 }
532 }
533
event_note_child_started(int slot,pid_t pid)534 static void event_note_child_started(int slot, pid_t pid)
535 {
536 ap_scoreboard_image->parent[slot].pid = pid;
537 ap_run_child_status(ap_server_conf,
538 ap_scoreboard_image->parent[slot].pid,
539 retained->my_generation, slot, MPM_CHILD_STARTED);
540 }
541
event_note_child_lost_slot(int slot,pid_t newpid)542 static void event_note_child_lost_slot(int slot, pid_t newpid)
543 {
544 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(00458)
545 "pid %" APR_PID_T_FMT " taking over scoreboard slot from "
546 "%" APR_PID_T_FMT "%s",
547 newpid,
548 ap_scoreboard_image->parent[slot].pid,
549 ap_scoreboard_image->parent[slot].quiescing ?
550 " (quiescing)" : "");
551 ap_run_child_status(ap_server_conf,
552 ap_scoreboard_image->parent[slot].pid,
553 ap_scoreboard_image->parent[slot].generation,
554 slot, MPM_CHILD_LOST_SLOT);
555 /* Don't forget about this exiting child process, or we
556 * won't be able to kill it if it doesn't exit by the
557 * time the server is shut down.
558 */
559 ap_register_extra_mpm_process(ap_scoreboard_image->parent[slot].pid,
560 ap_scoreboard_image->parent[slot].generation);
561 }
562
event_get_name(void)563 static const char *event_get_name(void)
564 {
565 return "event";
566 }
567
568 /* a clean exit from a child with proper cleanup */
569 static void clean_child_exit(int code) __attribute__ ((noreturn));
clean_child_exit(int code)570 static void clean_child_exit(int code)
571 {
572 mpm_state = AP_MPMQ_STOPPING;
573 if (pchild) {
574 apr_pool_destroy(pchild);
575 }
576
577 if (one_process) {
578 event_note_child_killed(/* slot */ 0, 0, 0);
579 }
580
581 exit(code);
582 }
583
just_die(int sig)584 static void just_die(int sig)
585 {
586 clean_child_exit(0);
587 }
588
589 /*****************************************************************
590 * Connection structures and accounting...
591 */
592
593 static int child_fatal;
594
595 /* volatile because they're updated from a signal handler */
596 static int volatile shutdown_pending;
597 static int volatile restart_pending;
598
decrement_connection_count(void * cs_)599 static apr_status_t decrement_connection_count(void *cs_)
600 {
601 event_conn_state_t *cs = cs_;
602 switch (cs->pub.state) {
603 case CONN_STATE_LINGER_NORMAL:
604 case CONN_STATE_LINGER_SHORT:
605 apr_atomic_dec32(&lingering_count);
606 break;
607 case CONN_STATE_SUSPENDED:
608 apr_atomic_dec32(&suspended_count);
609 break;
610 default:
611 break;
612 }
613 apr_atomic_dec32(&connection_count);
614 return APR_SUCCESS;
615 }
616
617 /*
618 * ap_start_shutdown() and ap_start_restart(), below, are a first stab at
619 * functions to initiate shutdown or restart without relying on signals.
620 * Previously this was initiated in sig_term() and restart() signal handlers,
621 * but we want to be able to start a shutdown/restart from other sources --
622 * e.g. on Win32, from the service manager. Now the service manager can
623 * call ap_start_shutdown() or ap_start_restart() as appropiate. Note that
624 * these functions can also be called by the child processes, since global
625 * variables are no longer used to pass on the required action to the parent.
626 *
627 * These should only be called from the parent process itself, since the
628 * parent process will use the shutdown_pending and restart_pending variables
629 * to determine whether to shutdown or restart. The child process should
630 * call signal_parent() directly to tell the parent to die -- this will
631 * cause neither of those variable to be set, which the parent will
632 * assume means something serious is wrong (which it will be, for the
633 * child to force an exit) and so do an exit anyway.
634 */
635
ap_start_shutdown(int graceful)636 static void ap_start_shutdown(int graceful)
637 {
638 mpm_state = AP_MPMQ_STOPPING;
639 if (shutdown_pending == 1) {
640 /* Um, is this _probably_ not an error, if the user has
641 * tried to do a shutdown twice quickly, so we won't
642 * worry about reporting it.
643 */
644 return;
645 }
646 shutdown_pending = 1;
647 retained->is_graceful = graceful;
648 }
649
650 /* do a graceful restart if graceful == 1 */
ap_start_restart(int graceful)651 static void ap_start_restart(int graceful)
652 {
653 mpm_state = AP_MPMQ_STOPPING;
654 if (restart_pending == 1) {
655 /* Probably not an error - don't bother reporting it */
656 return;
657 }
658 restart_pending = 1;
659 retained->is_graceful = graceful;
660 }
661
sig_term(int sig)662 static void sig_term(int sig)
663 {
664 ap_start_shutdown(sig == AP_SIG_GRACEFUL_STOP);
665 }
666
restart(int sig)667 static void restart(int sig)
668 {
669 ap_start_restart(sig == AP_SIG_GRACEFUL);
670 }
671
set_signals(void)672 static void set_signals(void)
673 {
674 #ifndef NO_USE_SIGACTION
675 struct sigaction sa;
676 #endif
677
678 if (!one_process) {
679 ap_fatal_signal_setup(ap_server_conf, pconf);
680 }
681
682 #ifndef NO_USE_SIGACTION
683 sigemptyset(&sa.sa_mask);
684 sa.sa_flags = 0;
685
686 sa.sa_handler = sig_term;
687 if (sigaction(SIGTERM, &sa, NULL) < 0)
688 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00459)
689 "sigaction(SIGTERM)");
690 #ifdef AP_SIG_GRACEFUL_STOP
691 if (sigaction(AP_SIG_GRACEFUL_STOP, &sa, NULL) < 0)
692 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00460)
693 "sigaction(" AP_SIG_GRACEFUL_STOP_STRING ")");
694 #endif
695 #ifdef SIGINT
696 if (sigaction(SIGINT, &sa, NULL) < 0)
697 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00461)
698 "sigaction(SIGINT)");
699 #endif
700 #ifdef SIGXCPU
701 sa.sa_handler = SIG_DFL;
702 if (sigaction(SIGXCPU, &sa, NULL) < 0)
703 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00462)
704 "sigaction(SIGXCPU)");
705 #endif
706 #ifdef SIGXFSZ
707 /* For systems following the LFS standard, ignoring SIGXFSZ allows
708 * a write() beyond the 2GB limit to fail gracefully with E2BIG
709 * rather than terminate the process. */
710 sa.sa_handler = SIG_IGN;
711 if (sigaction(SIGXFSZ, &sa, NULL) < 0)
712 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00463)
713 "sigaction(SIGXFSZ)");
714 #endif
715 #ifdef SIGPIPE
716 sa.sa_handler = SIG_IGN;
717 if (sigaction(SIGPIPE, &sa, NULL) < 0)
718 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00464)
719 "sigaction(SIGPIPE)");
720 #endif
721
722 /* we want to ignore HUPs and AP_SIG_GRACEFUL while we're busy
723 * processing one */
724 sigaddset(&sa.sa_mask, SIGHUP);
725 sigaddset(&sa.sa_mask, AP_SIG_GRACEFUL);
726 sa.sa_handler = restart;
727 if (sigaction(SIGHUP, &sa, NULL) < 0)
728 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00465)
729 "sigaction(SIGHUP)");
730 if (sigaction(AP_SIG_GRACEFUL, &sa, NULL) < 0)
731 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, APLOGNO(00466)
732 "sigaction(" AP_SIG_GRACEFUL_STRING ")");
733 #else
734 if (!one_process) {
735 #ifdef SIGXCPU
736 apr_signal(SIGXCPU, SIG_DFL);
737 #endif /* SIGXCPU */
738 #ifdef SIGXFSZ
739 apr_signal(SIGXFSZ, SIG_IGN);
740 #endif /* SIGXFSZ */
741 }
742
743 apr_signal(SIGTERM, sig_term);
744 #ifdef SIGHUP
745 apr_signal(SIGHUP, restart);
746 #endif /* SIGHUP */
747 #ifdef AP_SIG_GRACEFUL
748 apr_signal(AP_SIG_GRACEFUL, restart);
749 #endif /* AP_SIG_GRACEFUL */
750 #ifdef AP_SIG_GRACEFUL_STOP
751 apr_signal(AP_SIG_GRACEFUL_STOP, sig_term);
752 #endif /* AP_SIG_GRACEFUL_STOP */
753 #ifdef SIGPIPE
754 apr_signal(SIGPIPE, SIG_IGN);
755 #endif /* SIGPIPE */
756
757 #endif
758 }
759
start_lingering_close_common(event_conn_state_t * cs)760 static int start_lingering_close_common(event_conn_state_t *cs)
761 {
762 apr_status_t rv;
763 struct timeout_queue *q;
764 apr_socket_t *csd = cs->pfd.desc.s;
765 #ifdef AP_DEBUG
766 {
767 rv = apr_socket_timeout_set(csd, 0);
768 AP_DEBUG_ASSERT(rv == APR_SUCCESS);
769 }
770 #else
771 apr_socket_timeout_set(csd, 0);
772 #endif
773 /*
774 * If some module requested a shortened waiting period, only wait for
775 * 2s (SECONDS_TO_LINGER). This is useful for mitigating certain
776 * DoS attacks.
777 */
778 if (apr_table_get(cs->c->notes, "short-lingering-close")) {
779 cs->expiration_time =
780 apr_time_now() + apr_time_from_sec(SECONDS_TO_LINGER);
781 q = &short_linger_q;
782 cs->pub.state = CONN_STATE_LINGER_SHORT;
783 }
784 else {
785 cs->expiration_time =
786 apr_time_now() + apr_time_from_sec(MAX_SECS_TO_LINGER);
787 q = &linger_q;
788 cs->pub.state = CONN_STATE_LINGER_NORMAL;
789 }
790 apr_atomic_inc32(&lingering_count);
791 apr_thread_mutex_lock(timeout_mutex);
792 TO_QUEUE_APPEND(*q, cs);
793 cs->pfd.reqevents = APR_POLLIN | APR_POLLHUP | APR_POLLERR;
794 rv = apr_pollset_add(event_pollset, &cs->pfd);
795 apr_thread_mutex_unlock(timeout_mutex);
796 if (rv != APR_SUCCESS && !APR_STATUS_IS_EEXIST(rv)) {
797 ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf,
798 "start_lingering_close: apr_pollset_add failure");
799 apr_thread_mutex_lock(timeout_mutex);
800 TO_QUEUE_REMOVE(*q, cs);
801 apr_thread_mutex_unlock(timeout_mutex);
802 apr_socket_close(cs->pfd.desc.s);
803 apr_pool_clear(cs->p);
804 ap_push_pool(worker_queue_info, cs->p);
805 return 0;
806 }
807 return 1;
808 }
809
810 /*
811 * Close our side of the connection, flushing data to the client first.
812 * Pre-condition: cs is not in any timeout queue and not in the pollset,
813 * timeout_mutex is not locked
814 * return: 0 if connection is fully closed,
815 * 1 if connection is lingering
816 * May only be called by worker thread.
817 */
start_lingering_close_blocking(event_conn_state_t * cs)818 static int start_lingering_close_blocking(event_conn_state_t *cs)
819 {
820 if (ap_start_lingering_close(cs->c)) {
821 apr_pool_clear(cs->p);
822 ap_push_pool(worker_queue_info, cs->p);
823 return 0;
824 }
825 return start_lingering_close_common(cs);
826 }
827
828 /*
829 * Close our side of the connection, NOT flushing data to the client.
830 * This should only be called if there has been an error or if we know
831 * that our send buffers are empty.
832 * Pre-condition: cs is not in any timeout queue and not in the pollset,
833 * timeout_mutex is not locked
834 * return: 0 if connection is fully closed,
835 * 1 if connection is lingering
836 * may be called by listener thread
837 */
start_lingering_close_nonblocking(event_conn_state_t * cs)838 static int start_lingering_close_nonblocking(event_conn_state_t *cs)
839 {
840 conn_rec *c = cs->c;
841 apr_socket_t *csd = cs->pfd.desc.s;
842
843 if (c->aborted
844 || apr_socket_shutdown(csd, APR_SHUTDOWN_WRITE) != APR_SUCCESS) {
845 apr_socket_close(csd);
846 apr_pool_clear(cs->p);
847 ap_push_pool(worker_queue_info, cs->p);
848 return 0;
849 }
850 return start_lingering_close_common(cs);
851 }
852
853 /*
854 * forcibly close a lingering connection after the lingering period has
855 * expired
856 * Pre-condition: cs is not in any timeout queue and not in the pollset
857 * return: irrelevant (need same prototype as start_lingering_close)
858 */
stop_lingering_close(event_conn_state_t * cs)859 static int stop_lingering_close(event_conn_state_t *cs)
860 {
861 apr_status_t rv;
862 apr_socket_t *csd = ap_get_conn_socket(cs->c);
863 ap_log_error(APLOG_MARK, APLOG_TRACE4, 0, ap_server_conf,
864 "socket reached timeout in lingering-close state");
865 rv = apr_socket_close(csd);
866 if (rv != APR_SUCCESS) {
867 ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf, APLOGNO(00468) "error closing socket");
868 AP_DEBUG_ASSERT(0);
869 }
870 apr_pool_clear(cs->p);
871 ap_push_pool(worker_queue_info, cs->p);
872 return 0;
873 }
874
875 /*
876 * process one connection in the worker
877 */
process_socket(apr_thread_t * thd,apr_pool_t * p,apr_socket_t * sock,event_conn_state_t * cs,int my_child_num,int my_thread_num)878 static void process_socket(apr_thread_t *thd, apr_pool_t * p, apr_socket_t * sock,
879 event_conn_state_t * cs, int my_child_num,
880 int my_thread_num)
881 {
882 conn_rec *c;
883 long conn_id = ID_FROM_CHILD_THREAD(my_child_num, my_thread_num);
884 int rc;
885 ap_sb_handle_t *sbh;
886
887 /* XXX: This will cause unbounded mem usage for long lasting connections */
888 ap_create_sb_handle(&sbh, p, my_child_num, my_thread_num);
889
890 if (cs == NULL) { /* This is a new connection */
891 listener_poll_type *pt = apr_pcalloc(p, sizeof(*pt));
892 cs = apr_pcalloc(p, sizeof(event_conn_state_t));
893 cs->bucket_alloc = apr_bucket_alloc_create(p);
894 c = ap_run_create_connection(p, ap_server_conf, sock,
895 conn_id, sbh, cs->bucket_alloc);
896 if (!c) {
897 apr_bucket_alloc_destroy(cs->bucket_alloc);
898 apr_pool_clear(p);
899 ap_push_pool(worker_queue_info, p);
900 return;
901 }
902 apr_atomic_inc32(&connection_count);
903 apr_pool_cleanup_register(c->pool, cs, decrement_connection_count,
904 apr_pool_cleanup_null);
905 c->current_thread = thd;
906 cs->c = c;
907 c->cs = &(cs->pub);
908 cs->p = p;
909 cs->pfd.desc_type = APR_POLL_SOCKET;
910 cs->pfd.reqevents = APR_POLLIN;
911 cs->pfd.desc.s = sock;
912 pt->type = PT_CSD;
913 pt->baton = cs;
914 cs->pfd.client_data = pt;
915 TO_QUEUE_ELEM_INIT(cs);
916
917 ap_update_vhost_given_ip(c);
918
919 rc = ap_run_pre_connection(c, sock);
920 if (rc != OK && rc != DONE) {
921 ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(00469)
922 "process_socket: connection aborted");
923 c->aborted = 1;
924 }
925
926 /**
927 * XXX If the platform does not have a usable way of bundling
928 * accept() with a socket readability check, like Win32,
929 * and there are measurable delays before the
930 * socket is readable due to the first data packet arriving,
931 * it might be better to create the cs on the listener thread
932 * with the state set to CONN_STATE_CHECK_REQUEST_LINE_READABLE
933 *
934 * FreeBSD users will want to enable the HTTP accept filter
935 * module in their kernel for the highest performance
936 * When the accept filter is active, sockets are kept in the
937 * kernel until a HTTP request is received.
938 */
939 cs->pub.state = CONN_STATE_READ_REQUEST_LINE;
940
941 }
942 else {
943 c = cs->c;
944 c->sbh = sbh;
945 c->current_thread = thd;
946 }
947
948 if (c->clogging_input_filters && !c->aborted) {
949 /* Since we have an input filter which 'cloggs' the input stream,
950 * like mod_ssl, lets just do the normal read from input filters,
951 * like the Worker MPM does.
952 */
953 apr_atomic_inc32(&clogged_count);
954 ap_run_process_connection(c);
955 if (cs->pub.state != CONN_STATE_SUSPENDED) {
956 cs->pub.state = CONN_STATE_LINGER;
957 }
958 apr_atomic_dec32(&clogged_count);
959 }
960
961 read_request:
962 if (cs->pub.state == CONN_STATE_READ_REQUEST_LINE) {
963 if (!c->aborted) {
964 ap_run_process_connection(c);
965
966 /* state will be updated upon return
967 * fall thru to either wait for readability/timeout or
968 * do lingering close
969 */
970 }
971 else {
972 cs->pub.state = CONN_STATE_LINGER;
973 }
974 }
975
976 if (cs->pub.state == CONN_STATE_WRITE_COMPLETION) {
977 ap_filter_t *output_filter = c->output_filters;
978 apr_status_t rv;
979 ap_update_child_status_from_conn(sbh, SERVER_BUSY_WRITE, c);
980 while (output_filter->next != NULL) {
981 output_filter = output_filter->next;
982 }
983 rv = output_filter->frec->filter_func.out_func(output_filter, NULL);
984 if (rv != APR_SUCCESS) {
985 ap_log_cerror(APLOG_MARK, APLOG_DEBUG, rv, c, APLOGNO(00470)
986 "network write failure in core output filter");
987 cs->pub.state = CONN_STATE_LINGER;
988 }
989 else if (c->data_in_output_filters) {
990 /* Still in WRITE_COMPLETION_STATE:
991 * Set a write timeout for this connection, and let the
992 * event thread poll for writeability.
993 */
994 cs->expiration_time = ap_server_conf->timeout + apr_time_now();
995 apr_thread_mutex_lock(timeout_mutex);
996 TO_QUEUE_APPEND(write_completion_q, cs);
997 cs->pfd.reqevents = APR_POLLOUT | APR_POLLHUP | APR_POLLERR;
998 rc = apr_pollset_add(event_pollset, &cs->pfd);
999 apr_thread_mutex_unlock(timeout_mutex);
1000 return;
1001 }
1002 else if (c->keepalive != AP_CONN_KEEPALIVE || c->aborted ||
1003 listener_may_exit) {
1004 cs->pub.state = CONN_STATE_LINGER;
1005 }
1006 else if (c->data_in_input_filters) {
1007 cs->pub.state = CONN_STATE_READ_REQUEST_LINE;
1008 goto read_request;
1009 }
1010 else {
1011 cs->pub.state = CONN_STATE_CHECK_REQUEST_LINE_READABLE;
1012 }
1013 }
1014
1015 if (cs->pub.state == CONN_STATE_LINGER) {
1016 if (!start_lingering_close_blocking(cs))
1017 return;
1018 }
1019 else if (cs->pub.state == CONN_STATE_CHECK_REQUEST_LINE_READABLE) {
1020 apr_status_t rc;
1021
1022 /* It greatly simplifies the logic to use a single timeout value here
1023 * because the new element can just be added to the end of the list and
1024 * it will stay sorted in expiration time sequence. If brand new
1025 * sockets are sent to the event thread for a readability check, this
1026 * will be a slight behavior change - they use the non-keepalive
1027 * timeout today. With a normal client, the socket will be readable in
1028 * a few milliseconds anyway.
1029 */
1030 cs->expiration_time = ap_server_conf->keep_alive_timeout +
1031 apr_time_now();
1032 apr_thread_mutex_lock(timeout_mutex);
1033 TO_QUEUE_APPEND(keepalive_q, cs);
1034
1035 /* Add work to pollset. */
1036 cs->pfd.reqevents = APR_POLLIN;
1037 rc = apr_pollset_add(event_pollset, &cs->pfd);
1038 apr_thread_mutex_unlock(timeout_mutex);
1039
1040 if (rc != APR_SUCCESS) {
1041 ap_log_error(APLOG_MARK, APLOG_ERR, rc, ap_server_conf,
1042 "process_socket: apr_pollset_add failure");
1043 AP_DEBUG_ASSERT(rc == APR_SUCCESS);
1044 }
1045 }
1046 else if (cs->pub.state == CONN_STATE_SUSPENDED) {
1047 apr_atomic_inc32(&suspended_count);
1048 }
1049 /*
1050 * Prevent this connection from writing to our connection state after it
1051 * is no longer associated with this thread. This would happen if the EOR
1052 * bucket is destroyed from the listener thread due to a connection abort
1053 * or timeout.
1054 */
1055 c->sbh = NULL;
1056
1057 return;
1058 }
1059
1060 /* conns_this_child has gone to zero or below. See if the admin coded
1061 "MaxConnectionsPerChild 0", and keep going in that case. Doing it this way
1062 simplifies the hot path in worker_thread */
check_infinite_requests(void)1063 static void check_infinite_requests(void)
1064 {
1065 if (ap_max_requests_per_child) {
1066 ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, ap_server_conf,
1067 "Stopping process due to MaxConnectionsPerChild");
1068 signal_threads(ST_GRACEFUL);
1069 }
1070 else {
1071 /* keep going */
1072 conns_this_child = APR_INT32_MAX;
1073 }
1074 }
1075
close_listeners(int process_slot,int * closed)1076 static void close_listeners(int process_slot, int *closed) {
1077 if (!*closed) {
1078 int i;
1079 disable_listensocks(process_slot);
1080 ap_close_listeners();
1081 *closed = 1;
1082 dying = 1;
1083 ap_scoreboard_image->parent[process_slot].quiescing = 1;
1084 for (i = 0; i < threads_per_child; ++i) {
1085 ap_update_child_status_from_indexes(process_slot, i,
1086 SERVER_GRACEFUL, NULL);
1087 }
1088 /* wake up the main thread */
1089 kill(ap_my_pid, SIGTERM);
1090 }
1091 }
1092
unblock_signal(int sig)1093 static void unblock_signal(int sig)
1094 {
1095 sigset_t sig_mask;
1096
1097 sigemptyset(&sig_mask);
1098 sigaddset(&sig_mask, sig);
1099 #if defined(SIGPROCMASK_SETS_THREAD_MASK)
1100 sigprocmask(SIG_UNBLOCK, &sig_mask, NULL);
1101 #else
1102 pthread_sigmask(SIG_UNBLOCK, &sig_mask, NULL);
1103 #endif
1104 }
1105
dummy_signal_handler(int sig)1106 static void dummy_signal_handler(int sig)
1107 {
1108 /* XXX If specifying SIG_IGN is guaranteed to unblock a syscall,
1109 * then we don't need this goofy function.
1110 */
1111 }
1112
1113
init_pollset(apr_pool_t * p)1114 static apr_status_t init_pollset(apr_pool_t *p)
1115 {
1116 ap_listen_rec *lr;
1117 listener_poll_type *pt;
1118 int i = 0;
1119
1120 TO_QUEUE_INIT(write_completion_q);
1121 TO_QUEUE_INIT(keepalive_q);
1122 TO_QUEUE_INIT(linger_q);
1123 TO_QUEUE_INIT(short_linger_q);
1124
1125 listener_pollfd = apr_palloc(p, sizeof(apr_pollfd_t) * num_listensocks);
1126 for (lr = ap_listeners; lr != NULL; lr = lr->next, i++) {
1127 apr_pollfd_t *pfd;
1128 AP_DEBUG_ASSERT(i < num_listensocks);
1129 pfd = &listener_pollfd[i];
1130 pt = apr_pcalloc(p, sizeof(*pt));
1131 pfd->desc_type = APR_POLL_SOCKET;
1132 pfd->desc.s = lr->sd;
1133 pfd->reqevents = APR_POLLIN;
1134
1135 pt->type = PT_ACCEPT;
1136 pt->baton = lr;
1137
1138 pfd->client_data = pt;
1139
1140 apr_socket_opt_set(pfd->desc.s, APR_SO_NONBLOCK, 1);
1141 apr_pollset_add(event_pollset, pfd);
1142
1143 lr->accept_func = ap_unixd_accept;
1144 }
1145
1146 return APR_SUCCESS;
1147 }
1148
push_timer2worker(timer_event_t * te)1149 static apr_status_t push_timer2worker(timer_event_t* te)
1150 {
1151 return ap_queue_push_timer(worker_queue, te);
1152 }
1153
1154 /*
1155 * Pre-condition: pfd->cs is neither in pollset nor timeout queue
1156 * this function may only be called by the listener
1157 */
push2worker(const apr_pollfd_t * pfd,apr_pollset_t * pollset)1158 static apr_status_t push2worker(const apr_pollfd_t * pfd,
1159 apr_pollset_t * pollset)
1160 {
1161 listener_poll_type *pt = (listener_poll_type *) pfd->client_data;
1162 event_conn_state_t *cs = (event_conn_state_t *) pt->baton;
1163 apr_status_t rc;
1164
1165 rc = ap_queue_push(worker_queue, cs->pfd.desc.s, cs, cs->p);
1166 if (rc != APR_SUCCESS) {
1167 /* trash the connection; we couldn't queue the connected
1168 * socket to a worker
1169 */
1170 apr_bucket_alloc_destroy(cs->bucket_alloc);
1171 apr_socket_close(cs->pfd.desc.s);
1172 ap_log_error(APLOG_MARK, APLOG_CRIT, rc,
1173 ap_server_conf, APLOGNO(00471) "push2worker: ap_queue_push failed");
1174 apr_pool_clear(cs->p);
1175 ap_push_pool(worker_queue_info, cs->p);
1176 }
1177
1178 return rc;
1179 }
1180
1181 /* get_worker:
1182 * If *have_idle_worker_p == 0, reserve a worker thread, and set
1183 * *have_idle_worker_p = 1.
1184 * If *have_idle_worker_p is already 1, will do nothing.
1185 * If blocking == 1, block if all workers are currently busy.
1186 * If no worker was available immediately, will set *all_busy to 1.
1187 * XXX: If there are no workers, we should not block immediately but
1188 * XXX: close all keep-alive connections first.
1189 */
get_worker(int * have_idle_worker_p,int blocking,int * all_busy)1190 static void get_worker(int *have_idle_worker_p, int blocking, int *all_busy)
1191 {
1192 apr_status_t rc;
1193
1194 if (*have_idle_worker_p) {
1195 /* already reserved a worker thread - must have hit a
1196 * transient error on a previous pass
1197 */
1198 return;
1199 }
1200
1201 if (blocking)
1202 rc = ap_queue_info_wait_for_idler(worker_queue_info, all_busy);
1203 else
1204 rc = ap_queue_info_try_get_idler(worker_queue_info);
1205
1206 if (rc == APR_SUCCESS) {
1207 *have_idle_worker_p = 1;
1208 }
1209 else if (!blocking && rc == APR_EAGAIN) {
1210 *all_busy = 1;
1211 }
1212 else if (!APR_STATUS_IS_EOF(rc)) {
1213 ap_log_error(APLOG_MARK, APLOG_ERR, rc, ap_server_conf, APLOGNO(00472)
1214 "ap_queue_info_wait_for_idler failed. "
1215 "Attempting to shutdown process gracefully");
1216 signal_threads(ST_GRACEFUL);
1217 }
1218 }
1219
1220 /* XXXXXX: Convert to skiplist or other better data structure
1221 * (yes, this is VERY VERY VERY VERY BAD)
1222 */
1223
1224 /* Structures to reuse */
1225 static APR_RING_HEAD(timer_free_ring_t, timer_event_t) timer_free_ring;
1226 /* Active timers */
1227 static APR_RING_HEAD(timer_ring_t, timer_event_t) timer_ring;
1228
1229 static apr_thread_mutex_t *g_timer_ring_mtx;
1230
event_register_timed_callback(apr_time_t t,ap_mpm_callback_fn_t * cbfn,void * baton)1231 static apr_status_t event_register_timed_callback(apr_time_t t,
1232 ap_mpm_callback_fn_t *cbfn,
1233 void *baton)
1234 {
1235 int inserted = 0;
1236 timer_event_t *ep;
1237 timer_event_t *te;
1238 /* oh yeah, and make locking smarter/fine grained. */
1239 apr_thread_mutex_lock(g_timer_ring_mtx);
1240
1241 if (!APR_RING_EMPTY(&timer_free_ring, timer_event_t, link)) {
1242 te = APR_RING_FIRST(&timer_free_ring);
1243 APR_RING_REMOVE(te, link);
1244 }
1245 else {
1246 /* XXXXX: lol, pool allocation without a context from any thread.Yeah. Right. MPMs Suck. */
1247 te = ap_malloc(sizeof(timer_event_t));
1248 APR_RING_ELEM_INIT(te, link);
1249 }
1250
1251 te->cbfunc = cbfn;
1252 te->baton = baton;
1253 /* XXXXX: optimize */
1254 te->when = t + apr_time_now();
1255
1256 /* Okay, insert sorted by when.. */
1257 for (ep = APR_RING_FIRST(&timer_ring);
1258 ep != APR_RING_SENTINEL(&timer_ring,
1259 timer_event_t, link);
1260 ep = APR_RING_NEXT(ep, link))
1261 {
1262 if (ep->when > te->when) {
1263 inserted = 1;
1264 APR_RING_INSERT_BEFORE(ep, te, link);
1265 break;
1266 }
1267 }
1268
1269 if (!inserted) {
1270 APR_RING_INSERT_TAIL(&timer_ring, te, timer_event_t, link);
1271 }
1272
1273 apr_thread_mutex_unlock(g_timer_ring_mtx);
1274
1275 return APR_SUCCESS;
1276 }
1277
1278 /*
1279 * Close socket and clean up if remote closed its end while we were in
1280 * lingering close.
1281 * Only to be called in the listener thread;
1282 * Pre-condition: cs is in one of the linger queues and in the pollset
1283 */
process_lingering_close(event_conn_state_t * cs,const apr_pollfd_t * pfd)1284 static void process_lingering_close(event_conn_state_t *cs, const apr_pollfd_t *pfd)
1285 {
1286 apr_socket_t *csd = ap_get_conn_socket(cs->c);
1287 char dummybuf[2048];
1288 apr_size_t nbytes;
1289 apr_status_t rv;
1290 struct timeout_queue *q;
1291 q = (cs->pub.state == CONN_STATE_LINGER_SHORT) ? &short_linger_q : &linger_q;
1292
1293 /* socket is already in non-blocking state */
1294 do {
1295 nbytes = sizeof(dummybuf);
1296 rv = apr_socket_recv(csd, dummybuf, &nbytes);
1297 } while (rv == APR_SUCCESS);
1298
1299 if (!APR_STATUS_IS_EOF(rv)) {
1300 return;
1301 }
1302
1303 apr_thread_mutex_lock(timeout_mutex);
1304 rv = apr_pollset_remove(event_pollset, pfd);
1305 AP_DEBUG_ASSERT(rv == APR_SUCCESS);
1306
1307 rv = apr_socket_close(csd);
1308 AP_DEBUG_ASSERT(rv == APR_SUCCESS);
1309
1310 TO_QUEUE_REMOVE(*q, cs);
1311 apr_thread_mutex_unlock(timeout_mutex);
1312 TO_QUEUE_ELEM_INIT(cs);
1313
1314 apr_pool_clear(cs->p);
1315 ap_push_pool(worker_queue_info, cs->p);
1316 }
1317
1318 /* call 'func' for all elements of 'q' with timeout less than 'timeout_time'.
1319 * Pre-condition: timeout_mutex must already be locked
1320 * Post-condition: timeout_mutex will be locked again
1321 */
process_timeout_queue(struct timeout_queue * q,apr_time_t timeout_time,int (* func)(event_conn_state_t *))1322 static void process_timeout_queue(struct timeout_queue *q,
1323 apr_time_t timeout_time,
1324 int (*func)(event_conn_state_t *))
1325 {
1326 int count = 0;
1327 event_conn_state_t *first, *cs, *last;
1328 apr_status_t rv;
1329 if (!q->count) {
1330 return;
1331 }
1332 AP_DEBUG_ASSERT(!APR_RING_EMPTY(&q->head, event_conn_state_t, timeout_list));
1333
1334 cs = first = APR_RING_FIRST(&q->head);
1335 while (cs != APR_RING_SENTINEL(&q->head, event_conn_state_t, timeout_list)
1336 && cs->expiration_time < timeout_time) {
1337 last = cs;
1338 rv = apr_pollset_remove(event_pollset, &cs->pfd);
1339 if (rv != APR_SUCCESS && !APR_STATUS_IS_NOTFOUND(rv)) {
1340 ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, cs->c, APLOGNO(00473)
1341 "apr_pollset_remove failed");
1342 }
1343 cs = APR_RING_NEXT(cs, timeout_list);
1344 count++;
1345 }
1346 if (!count)
1347 return;
1348
1349 APR_RING_UNSPLICE(first, last, timeout_list);
1350 AP_DEBUG_ASSERT(q->count >= count);
1351 q->count -= count;
1352 apr_thread_mutex_unlock(timeout_mutex);
1353 while (count) {
1354 cs = APR_RING_NEXT(first, timeout_list);
1355 TO_QUEUE_ELEM_INIT(first);
1356 func(first);
1357 first = cs;
1358 count--;
1359 }
1360 apr_thread_mutex_lock(timeout_mutex);
1361 }
1362
listener_thread(apr_thread_t * thd,void * dummy)1363 static void * APR_THREAD_FUNC listener_thread(apr_thread_t * thd, void *dummy)
1364 {
1365 timer_event_t *ep;
1366 timer_event_t *te;
1367 apr_status_t rc;
1368 proc_info *ti = dummy;
1369 int process_slot = ti->pid;
1370 apr_pool_t *tpool = apr_thread_pool_get(thd);
1371 void *csd = NULL;
1372 apr_pool_t *ptrans; /* Pool for per-transaction stuff */
1373 ap_listen_rec *lr;
1374 int have_idle_worker = 0;
1375 event_conn_state_t *cs;
1376 const apr_pollfd_t *out_pfd;
1377 apr_int32_t num = 0;
1378 apr_interval_time_t timeout_interval;
1379 apr_time_t timeout_time = 0, now, last_log;
1380 listener_poll_type *pt;
1381 int closed = 0, listeners_disabled = 0;
1382
1383 last_log = apr_time_now();
1384 free(ti);
1385
1386 /* the following times out events that are really close in the future
1387 * to prevent extra poll calls
1388 *
1389 * current value is .1 second
1390 */
1391 #define TIMEOUT_FUDGE_FACTOR 100000
1392 #define EVENT_FUDGE_FACTOR 10000
1393
1394 rc = init_pollset(tpool);
1395 if (rc != APR_SUCCESS) {
1396 ap_log_error(APLOG_MARK, APLOG_ERR, rc, ap_server_conf,
1397 "failed to initialize pollset, "
1398 "attempting to shutdown process gracefully");
1399 signal_threads(ST_GRACEFUL);
1400 return NULL;
1401 }
1402
1403 /* Unblock the signal used to wake this thread up, and set a handler for
1404 * it.
1405 */
1406 unblock_signal(LISTENER_SIGNAL);
1407 apr_signal(LISTENER_SIGNAL, dummy_signal_handler);
1408
1409 for (;;) {
1410 int workers_were_busy = 0;
1411 if (listener_may_exit) {
1412 close_listeners(process_slot, &closed);
1413 if (terminate_mode == ST_UNGRACEFUL
1414 || apr_atomic_read32(&connection_count) == 0)
1415 break;
1416 }
1417
1418 if (conns_this_child <= 0)
1419 check_infinite_requests();
1420
1421 now = apr_time_now();
1422 if (APLOGtrace6(ap_server_conf)) {
1423 /* trace log status every second */
1424 if (now - last_log > apr_time_from_msec(1000)) {
1425 last_log = now;
1426 apr_thread_mutex_lock(timeout_mutex);
1427 ap_log_error(APLOG_MARK, APLOG_TRACE6, 0, ap_server_conf,
1428 "connections: %u (clogged: %u write-completion: %d "
1429 "keep-alive: %d lingering: %d suspended: %u)",
1430 apr_atomic_read32(&connection_count),
1431 apr_atomic_read32(&clogged_count),
1432 write_completion_q.count,
1433 keepalive_q.count,
1434 apr_atomic_read32(&lingering_count),
1435 apr_atomic_read32(&suspended_count));
1436 apr_thread_mutex_unlock(timeout_mutex);
1437 }
1438 }
1439
1440 apr_thread_mutex_lock(g_timer_ring_mtx);
1441 if (!APR_RING_EMPTY(&timer_ring, timer_event_t, link)) {
1442 te = APR_RING_FIRST(&timer_ring);
1443 if (te->when > now) {
1444 timeout_interval = te->when - now;
1445 }
1446 else {
1447 timeout_interval = 1;
1448 }
1449 }
1450 else {
1451 timeout_interval = apr_time_from_msec(100);
1452 }
1453 apr_thread_mutex_unlock(g_timer_ring_mtx);
1454
1455 rc = apr_pollset_poll(event_pollset, timeout_interval, &num, &out_pfd);
1456 if (rc != APR_SUCCESS) {
1457 if (APR_STATUS_IS_EINTR(rc)) {
1458 continue;
1459 }
1460 if (!APR_STATUS_IS_TIMEUP(rc)) {
1461 ap_log_error(APLOG_MARK, APLOG_CRIT, rc, ap_server_conf,
1462 "apr_pollset_poll failed. Attempting to "
1463 "shutdown process gracefully");
1464 signal_threads(ST_GRACEFUL);
1465 }
1466 }
1467
1468 if (listener_may_exit) {
1469 close_listeners(process_slot, &closed);
1470 if (terminate_mode == ST_UNGRACEFUL
1471 || apr_atomic_read32(&connection_count) == 0)
1472 break;
1473 }
1474
1475 now = apr_time_now();
1476 apr_thread_mutex_lock(g_timer_ring_mtx);
1477 for (ep = APR_RING_FIRST(&timer_ring);
1478 ep != APR_RING_SENTINEL(&timer_ring,
1479 timer_event_t, link);
1480 ep = APR_RING_FIRST(&timer_ring))
1481 {
1482 if (ep->when < now + EVENT_FUDGE_FACTOR) {
1483 APR_RING_REMOVE(ep, link);
1484 push_timer2worker(ep);
1485 }
1486 else {
1487 break;
1488 }
1489 }
1490 apr_thread_mutex_unlock(g_timer_ring_mtx);
1491
1492 while (num) {
1493 pt = (listener_poll_type *) out_pfd->client_data;
1494 if (pt->type == PT_CSD) {
1495 /* one of the sockets is readable */
1496 struct timeout_queue *remove_from_q = &write_completion_q;
1497 int blocking = 1;
1498 cs = (event_conn_state_t *) pt->baton;
1499 switch (cs->pub.state) {
1500 case CONN_STATE_CHECK_REQUEST_LINE_READABLE:
1501 cs->pub.state = CONN_STATE_READ_REQUEST_LINE;
1502 remove_from_q = &keepalive_q;
1503 /* don't wait for a worker for a keepalive request */
1504 blocking = 0;
1505 /* FALL THROUGH */
1506 case CONN_STATE_WRITE_COMPLETION:
1507 get_worker(&have_idle_worker, blocking,
1508 &workers_were_busy);
1509 apr_thread_mutex_lock(timeout_mutex);
1510 TO_QUEUE_REMOVE(*remove_from_q, cs);
1511 rc = apr_pollset_remove(event_pollset, &cs->pfd);
1512
1513 /*
1514 * Some of the pollset backends, like KQueue or Epoll
1515 * automagically remove the FD if the socket is closed,
1516 * therefore, we can accept _SUCCESS or _NOTFOUND,
1517 * and we still want to keep going
1518 */
1519 if (rc != APR_SUCCESS && !APR_STATUS_IS_NOTFOUND(rc)) {
1520 ap_log_error(APLOG_MARK, APLOG_ERR, rc, ap_server_conf,
1521 "pollset remove failed");
1522 apr_thread_mutex_unlock(timeout_mutex);
1523 start_lingering_close_nonblocking(cs);
1524 break;
1525 }
1526
1527 apr_thread_mutex_unlock(timeout_mutex);
1528 TO_QUEUE_ELEM_INIT(cs);
1529 /* If we didn't get a worker immediately for a keep-alive
1530 * request, we close the connection, so that the client can
1531 * re-connect to a different process.
1532 */
1533 if (!have_idle_worker) {
1534 start_lingering_close_nonblocking(cs);
1535 break;
1536 }
1537 rc = push2worker(out_pfd, event_pollset);
1538 if (rc != APR_SUCCESS) {
1539 ap_log_error(APLOG_MARK, APLOG_CRIT, rc,
1540 ap_server_conf, "push2worker failed");
1541 }
1542 else {
1543 have_idle_worker = 0;
1544 }
1545 break;
1546 case CONN_STATE_LINGER_NORMAL:
1547 case CONN_STATE_LINGER_SHORT:
1548 process_lingering_close(cs, out_pfd);
1549 break;
1550 default:
1551 ap_log_error(APLOG_MARK, APLOG_CRIT, rc,
1552 ap_server_conf,
1553 "event_loop: unexpected state %d",
1554 cs->pub.state);
1555 ap_assert(0);
1556 }
1557 }
1558 else if (pt->type == PT_ACCEPT) {
1559 /* A Listener Socket is ready for an accept() */
1560 if (workers_were_busy) {
1561 if (!listeners_disabled)
1562 disable_listensocks(process_slot);
1563 listeners_disabled = 1;
1564 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
1565 "All workers busy, not accepting new conns"
1566 "in this process");
1567 }
1568 else if ( (int)apr_atomic_read32(&connection_count)
1569 - (int)apr_atomic_read32(&lingering_count)
1570 > threads_per_child
1571 + ap_queue_info_get_idlers(worker_queue_info) *
1572 worker_factor / WORKER_FACTOR_SCALE)
1573 {
1574 if (!listeners_disabled)
1575 disable_listensocks(process_slot);
1576 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
1577 "Too many open connections (%u), "
1578 "not accepting new conns in this process",
1579 apr_atomic_read32(&connection_count));
1580 ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, ap_server_conf,
1581 "Idle workers: %u",
1582 ap_queue_info_get_idlers(worker_queue_info));
1583 listeners_disabled = 1;
1584 }
1585 else if (listeners_disabled) {
1586 listeners_disabled = 0;
1587 enable_listensocks(process_slot);
1588 }
1589 if (!listeners_disabled) {
1590 lr = (ap_listen_rec *) pt->baton;
1591 ap_pop_pool(&ptrans, worker_queue_info);
1592
1593 if (ptrans == NULL) {
1594 /* create a new transaction pool for each accepted socket */
1595 apr_allocator_t *allocator;
1596
1597 apr_allocator_create(&allocator);
1598 apr_allocator_max_free_set(allocator,
1599 ap_max_mem_free);
1600 apr_pool_create_ex(&ptrans, pconf, NULL, allocator);
1601 apr_allocator_owner_set(allocator, ptrans);
1602 if (ptrans == NULL) {
1603 ap_log_error(APLOG_MARK, APLOG_CRIT, rc,
1604 ap_server_conf,
1605 "Failed to create transaction pool");
1606 signal_threads(ST_GRACEFUL);
1607 return NULL;
1608 }
1609 }
1610 apr_pool_tag(ptrans, "transaction");
1611
1612 get_worker(&have_idle_worker, 1, &workers_were_busy);
1613 rc = lr->accept_func(&csd, lr, ptrans);
1614
1615 /* later we trash rv and rely on csd to indicate
1616 * success/failure
1617 */
1618 AP_DEBUG_ASSERT(rc == APR_SUCCESS || !csd);
1619
1620 if (rc == APR_EGENERAL) {
1621 /* E[NM]FILE, ENOMEM, etc */
1622 resource_shortage = 1;
1623 signal_threads(ST_GRACEFUL);
1624 }
1625
1626 if (csd != NULL) {
1627 conns_this_child--;
1628 rc = ap_queue_push(worker_queue, csd, NULL, ptrans);
1629 if (rc != APR_SUCCESS) {
1630 /* trash the connection; we couldn't queue the connected
1631 * socket to a worker
1632 */
1633 apr_socket_close(csd);
1634 ap_log_error(APLOG_MARK, APLOG_CRIT, rc,
1635 ap_server_conf,
1636 "ap_queue_push failed");
1637 apr_pool_clear(ptrans);
1638 ap_push_pool(worker_queue_info, ptrans);
1639 }
1640 else {
1641 have_idle_worker = 0;
1642 }
1643 }
1644 else {
1645 apr_pool_clear(ptrans);
1646 ap_push_pool(worker_queue_info, ptrans);
1647 }
1648 }
1649 } /* if:else on pt->type */
1650 out_pfd++;
1651 num--;
1652 } /* while for processing poll */
1653
1654 /* XXX possible optimization: stash the current time for use as
1655 * r->request_time for new requests
1656 */
1657 now = apr_time_now();
1658 /* we only do this once per 0.1s (TIMEOUT_FUDGE_FACTOR) */
1659 if (now > timeout_time) {
1660 struct process_score *ps;
1661 timeout_time = now + TIMEOUT_FUDGE_FACTOR;
1662
1663 /* handle timed out sockets */
1664 apr_thread_mutex_lock(timeout_mutex);
1665
1666 /* Step 1: keepalive timeouts */
1667 /* If all workers are busy, we kill older keep-alive connections so that they
1668 * may connect to another process.
1669 */
1670 if (workers_were_busy && keepalive_q.count) {
1671 ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, ap_server_conf,
1672 "All workers are busy, will close %d keep-alive "
1673 "connections",
1674 keepalive_q.count);
1675 process_timeout_queue(&keepalive_q,
1676 timeout_time + ap_server_conf->keep_alive_timeout,
1677 start_lingering_close_nonblocking);
1678 }
1679 else {
1680 process_timeout_queue(&keepalive_q, timeout_time,
1681 start_lingering_close_nonblocking);
1682 }
1683 /* Step 2: write completion timeouts */
1684 process_timeout_queue(&write_completion_q, timeout_time,
1685 start_lingering_close_nonblocking);
1686 /* Step 3: (normal) lingering close completion timeouts */
1687 process_timeout_queue(&linger_q, timeout_time, stop_lingering_close);
1688 /* Step 4: (short) lingering close completion timeouts */
1689 process_timeout_queue(&short_linger_q, timeout_time, stop_lingering_close);
1690
1691 ps = ap_get_scoreboard_process(process_slot);
1692 ps->write_completion = write_completion_q.count;
1693 ps->keep_alive = keepalive_q.count;
1694 apr_thread_mutex_unlock(timeout_mutex);
1695
1696 ps->connections = apr_atomic_read32(&connection_count);
1697 ps->suspended = apr_atomic_read32(&suspended_count);
1698 ps->lingering_close = apr_atomic_read32(&lingering_count);
1699 }
1700 if (listeners_disabled && !workers_were_busy
1701 && (int)apr_atomic_read32(&connection_count)
1702 - (int)apr_atomic_read32(&lingering_count)
1703 < ((int)ap_queue_info_get_idlers(worker_queue_info) - 1)
1704 * worker_factor / WORKER_FACTOR_SCALE + threads_per_child)
1705 {
1706 listeners_disabled = 0;
1707 enable_listensocks(process_slot);
1708 }
1709 /*
1710 * XXX: do we need to set some timeout that re-enables the listensocks
1711 * XXX: in case no other event occurs?
1712 */
1713 } /* listener main loop */
1714
1715 close_listeners(process_slot, &closed);
1716 ap_queue_term(worker_queue);
1717
1718 apr_thread_exit(thd, APR_SUCCESS);
1719 return NULL;
1720 }
1721
1722 /* XXX For ungraceful termination/restart, we definitely don't want to
1723 * wait for active connections to finish but we may want to wait
1724 * for idle workers to get out of the queue code and release mutexes,
1725 * since those mutexes are cleaned up pretty soon and some systems
1726 * may not react favorably (i.e., segfault) if operations are attempted
1727 * on cleaned-up mutexes.
1728 */
worker_thread(apr_thread_t * thd,void * dummy)1729 static void *APR_THREAD_FUNC worker_thread(apr_thread_t * thd, void *dummy)
1730 {
1731 proc_info *ti = dummy;
1732 int process_slot = ti->pid;
1733 int thread_slot = ti->tid;
1734 apr_socket_t *csd = NULL;
1735 event_conn_state_t *cs;
1736 apr_pool_t *ptrans; /* Pool for per-transaction stuff */
1737 apr_status_t rv;
1738 int is_idle = 0;
1739 timer_event_t *te = NULL;
1740
1741 free(ti);
1742
1743 ap_scoreboard_image->servers[process_slot][thread_slot].pid = ap_my_pid;
1744 ap_scoreboard_image->servers[process_slot][thread_slot].tid = apr_os_thread_current();
1745 ap_scoreboard_image->servers[process_slot][thread_slot].generation = retained->my_generation;
1746 ap_update_child_status_from_indexes(process_slot, thread_slot,
1747 SERVER_STARTING, NULL);
1748
1749 while (!workers_may_exit) {
1750 if (!is_idle) {
1751 rv = ap_queue_info_set_idle(worker_queue_info, NULL);
1752 if (rv != APR_SUCCESS) {
1753 ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
1754 "ap_queue_info_set_idle failed. Attempting to "
1755 "shutdown process gracefully.");
1756 signal_threads(ST_GRACEFUL);
1757 break;
1758 }
1759 is_idle = 1;
1760 }
1761
1762 ap_update_child_status_from_indexes(process_slot, thread_slot,
1763 dying ? SERVER_GRACEFUL : SERVER_READY, NULL);
1764 worker_pop:
1765 if (workers_may_exit) {
1766 break;
1767 }
1768
1769 te = NULL;
1770 rv = ap_queue_pop_something(worker_queue, &csd, &cs, &ptrans, &te);
1771
1772 if (rv != APR_SUCCESS) {
1773 /* We get APR_EOF during a graceful shutdown once all the
1774 * connections accepted by this server process have been handled.
1775 */
1776 if (APR_STATUS_IS_EOF(rv)) {
1777 break;
1778 }
1779 /* We get APR_EINTR whenever ap_queue_pop() has been interrupted
1780 * from an explicit call to ap_queue_interrupt_all(). This allows
1781 * us to unblock threads stuck in ap_queue_pop() when a shutdown
1782 * is pending.
1783 *
1784 * If workers_may_exit is set and this is ungraceful termination/
1785 * restart, we are bound to get an error on some systems (e.g.,
1786 * AIX, which sanity-checks mutex operations) since the queue
1787 * may have already been cleaned up. Don't log the "error" if
1788 * workers_may_exit is set.
1789 */
1790 else if (APR_STATUS_IS_EINTR(rv)) {
1791 goto worker_pop;
1792 }
1793 /* We got some other error. */
1794 else if (!workers_may_exit) {
1795 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
1796 "ap_queue_pop failed");
1797 }
1798 continue;
1799 }
1800 if (te != NULL) {
1801 te->cbfunc(te->baton);
1802
1803 {
1804 apr_thread_mutex_lock(g_timer_ring_mtx);
1805 APR_RING_INSERT_TAIL(&timer_free_ring, te, timer_event_t, link);
1806 apr_thread_mutex_unlock(g_timer_ring_mtx);
1807 }
1808 }
1809 else {
1810 is_idle = 0;
1811 worker_sockets[thread_slot] = csd;
1812 process_socket(thd, ptrans, csd, cs, process_slot, thread_slot);
1813 worker_sockets[thread_slot] = NULL;
1814 }
1815 }
1816
1817 ap_update_child_status_from_indexes(process_slot, thread_slot,
1818 dying ? SERVER_DEAD :
1819 SERVER_GRACEFUL,
1820 (request_rec *) NULL);
1821
1822 apr_thread_exit(thd, APR_SUCCESS);
1823 return NULL;
1824 }
1825
check_signal(int signum)1826 static int check_signal(int signum)
1827 {
1828 switch (signum) {
1829 case SIGTERM:
1830 case SIGINT:
1831 return 1;
1832 }
1833 return 0;
1834 }
1835
1836
1837
create_listener_thread(thread_starter * ts)1838 static void create_listener_thread(thread_starter * ts)
1839 {
1840 int my_child_num = ts->child_num_arg;
1841 apr_threadattr_t *thread_attr = ts->threadattr;
1842 proc_info *my_info;
1843 apr_status_t rv;
1844
1845 my_info = (proc_info *) ap_malloc(sizeof(proc_info));
1846 my_info->pid = my_child_num;
1847 my_info->tid = -1; /* listener thread doesn't have a thread slot */
1848 my_info->sd = 0;
1849 rv = apr_thread_create(&ts->listener, thread_attr, listener_thread,
1850 my_info, pchild);
1851 if (rv != APR_SUCCESS) {
1852 ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf, APLOGNO(00474)
1853 "apr_thread_create: unable to create listener thread");
1854 /* let the parent decide how bad this really is */
1855 clean_child_exit(APEXIT_CHILDSICK);
1856 }
1857 apr_os_thread_get(&listener_os_thread, ts->listener);
1858 }
1859
1860 /* XXX under some circumstances not understood, children can get stuck
1861 * in start_threads forever trying to take over slots which will
1862 * never be cleaned up; for now there is an APLOG_DEBUG message issued
1863 * every so often when this condition occurs
1864 */
start_threads(apr_thread_t * thd,void * dummy)1865 static void *APR_THREAD_FUNC start_threads(apr_thread_t * thd, void *dummy)
1866 {
1867 thread_starter *ts = dummy;
1868 apr_thread_t **threads = ts->threads;
1869 apr_threadattr_t *thread_attr = ts->threadattr;
1870 int child_num_arg = ts->child_num_arg;
1871 int my_child_num = child_num_arg;
1872 proc_info *my_info;
1873 apr_status_t rv;
1874 int i;
1875 int threads_created = 0;
1876 int listener_started = 0;
1877 int loops;
1878 int prev_threads_created;
1879 int max_recycled_pools = -1;
1880
1881 /* We must create the fd queues before we start up the listener
1882 * and worker threads. */
1883 worker_queue = apr_pcalloc(pchild, sizeof(*worker_queue));
1884 rv = ap_queue_init(worker_queue, threads_per_child, pchild);
1885 if (rv != APR_SUCCESS) {
1886 ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
1887 "ap_queue_init() failed");
1888 clean_child_exit(APEXIT_CHILDFATAL);
1889 }
1890
1891 if (ap_max_mem_free != APR_ALLOCATOR_MAX_FREE_UNLIMITED) {
1892 /* If we want to conserve memory, let's not keep an unlimited number of
1893 * pools & allocators.
1894 * XXX: This should probably be a separate config directive
1895 */
1896 max_recycled_pools = threads_per_child * 3 / 4 ;
1897 }
1898 rv = ap_queue_info_create(&worker_queue_info, pchild,
1899 threads_per_child, max_recycled_pools);
1900 if (rv != APR_SUCCESS) {
1901 ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
1902 "ap_queue_info_create() failed");
1903 clean_child_exit(APEXIT_CHILDFATAL);
1904 }
1905
1906 /* Create the timeout mutex and main pollset before the listener
1907 * thread starts.
1908 */
1909 rv = apr_thread_mutex_create(&timeout_mutex, APR_THREAD_MUTEX_DEFAULT,
1910 pchild);
1911 if (rv != APR_SUCCESS) {
1912 ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf,
1913 "creation of the timeout mutex failed.");
1914 clean_child_exit(APEXIT_CHILDFATAL);
1915 }
1916
1917 /* Create the main pollset */
1918 rv = apr_pollset_create(&event_pollset,
1919 threads_per_child, /* XXX don't we need more, to handle
1920 * connections in K-A or lingering
1921 * close?
1922 */
1923 pchild, APR_POLLSET_THREADSAFE | APR_POLLSET_NOCOPY);
1924 if (rv != APR_SUCCESS) {
1925 ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf,
1926 "apr_pollset_create with Thread Safety failed.");
1927 clean_child_exit(APEXIT_CHILDFATAL);
1928 }
1929
1930 worker_sockets = apr_pcalloc(pchild, threads_per_child
1931 * sizeof(apr_socket_t *));
1932
1933 loops = prev_threads_created = 0;
1934 while (1) {
1935 /* threads_per_child does not include the listener thread */
1936 for (i = 0; i < threads_per_child; i++) {
1937 int status =
1938 ap_scoreboard_image->servers[child_num_arg][i].status;
1939
1940 if (status != SERVER_GRACEFUL && status != SERVER_DEAD) {
1941 continue;
1942 }
1943
1944 my_info = (proc_info *) ap_malloc(sizeof(proc_info));
1945 my_info->pid = my_child_num;
1946 my_info->tid = i;
1947 my_info->sd = 0;
1948
1949 /* We are creating threads right now */
1950 ap_update_child_status_from_indexes(my_child_num, i,
1951 SERVER_STARTING, NULL);
1952 /* We let each thread update its own scoreboard entry. This is
1953 * done because it lets us deal with tid better.
1954 */
1955 rv = apr_thread_create(&threads[i], thread_attr,
1956 worker_thread, my_info, pchild);
1957 if (rv != APR_SUCCESS) {
1958 ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
1959 "apr_thread_create: unable to create worker thread");
1960 /* let the parent decide how bad this really is */
1961 clean_child_exit(APEXIT_CHILDSICK);
1962 }
1963 threads_created++;
1964 }
1965
1966 /* Start the listener only when there are workers available */
1967 if (!listener_started && threads_created) {
1968 create_listener_thread(ts);
1969 listener_started = 1;
1970 }
1971
1972
1973 if (start_thread_may_exit || threads_created == threads_per_child) {
1974 break;
1975 }
1976 /* wait for previous generation to clean up an entry */
1977 apr_sleep(apr_time_from_sec(1));
1978 ++loops;
1979 if (loops % 120 == 0) { /* every couple of minutes */
1980 if (prev_threads_created == threads_created) {
1981 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
1982 "child %" APR_PID_T_FMT " isn't taking over "
1983 "slots very quickly (%d of %d)",
1984 ap_my_pid, threads_created,
1985 threads_per_child);
1986 }
1987 prev_threads_created = threads_created;
1988 }
1989 }
1990
1991 /* What state should this child_main process be listed as in the
1992 * scoreboard...?
1993 * ap_update_child_status_from_indexes(my_child_num, i, SERVER_STARTING,
1994 * (request_rec *) NULL);
1995 *
1996 * This state should be listed separately in the scoreboard, in some kind
1997 * of process_status, not mixed in with the worker threads' status.
1998 * "life_status" is almost right, but it's in the worker's structure, and
1999 * the name could be clearer. gla
2000 */
2001 apr_thread_exit(thd, APR_SUCCESS);
2002 return NULL;
2003 }
2004
join_workers(apr_thread_t * listener,apr_thread_t ** threads)2005 static void join_workers(apr_thread_t * listener, apr_thread_t ** threads)
2006 {
2007 int i;
2008 apr_status_t rv, thread_rv;
2009
2010 if (listener) {
2011 int iter;
2012
2013 /* deal with a rare timing window which affects waking up the
2014 * listener thread... if the signal sent to the listener thread
2015 * is delivered between the time it verifies that the
2016 * listener_may_exit flag is clear and the time it enters a
2017 * blocking syscall, the signal didn't do any good... work around
2018 * that by sleeping briefly and sending it again
2019 */
2020
2021 iter = 0;
2022 while (iter < 10 && !dying) {
2023 /* listener has not stopped accepting yet */
2024 apr_sleep(apr_time_make(0, 500000));
2025 wakeup_listener();
2026 ++iter;
2027 }
2028 if (iter >= 10) {
2029 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(00475)
2030 "the listener thread didn't stop accepting");
2031 }
2032 else {
2033 rv = apr_thread_join(&thread_rv, listener);
2034 if (rv != APR_SUCCESS) {
2035 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf, APLOGNO(00476)
2036 "apr_thread_join: unable to join listener thread");
2037 }
2038 }
2039 }
2040
2041 for (i = 0; i < threads_per_child; i++) {
2042 if (threads[i]) { /* if we ever created this thread */
2043 rv = apr_thread_join(&thread_rv, threads[i]);
2044 if (rv != APR_SUCCESS) {
2045 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf, APLOGNO(00477)
2046 "apr_thread_join: unable to join worker "
2047 "thread %d", i);
2048 }
2049 }
2050 }
2051 }
2052
join_start_thread(apr_thread_t * start_thread_id)2053 static void join_start_thread(apr_thread_t * start_thread_id)
2054 {
2055 apr_status_t rv, thread_rv;
2056
2057 start_thread_may_exit = 1; /* tell it to give up in case it is still
2058 * trying to take over slots from a
2059 * previous generation
2060 */
2061 rv = apr_thread_join(&thread_rv, start_thread_id);
2062 if (rv != APR_SUCCESS) {
2063 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf, APLOGNO(00478)
2064 "apr_thread_join: unable to join the start " "thread");
2065 }
2066 }
2067
child_main(int child_num_arg)2068 static void child_main(int child_num_arg)
2069 {
2070 apr_thread_t **threads;
2071 apr_status_t rv;
2072 thread_starter *ts;
2073 apr_threadattr_t *thread_attr;
2074 apr_thread_t *start_thread_id;
2075
2076 mpm_state = AP_MPMQ_STARTING; /* for benefit of any hooks that run as this
2077 * child initializes
2078 */
2079 ap_my_pid = getpid();
2080 ap_fatal_signal_child_setup(ap_server_conf);
2081 apr_pool_create(&pchild, pconf);
2082
2083 /*stuff to do before we switch id's, so we have permissions. */
2084 ap_reopen_scoreboard(pchild, NULL, 0);
2085
2086 if (ap_run_drop_privileges(pchild, ap_server_conf)) {
2087 clean_child_exit(APEXIT_CHILDFATAL);
2088 }
2089
2090 apr_thread_mutex_create(&g_timer_ring_mtx, APR_THREAD_MUTEX_DEFAULT, pchild);
2091 APR_RING_INIT(&timer_free_ring, timer_event_t, link);
2092 APR_RING_INIT(&timer_ring, timer_event_t, link);
2093 ap_run_child_init(pchild, ap_server_conf);
2094
2095 /* done with init critical section */
2096
2097 /* Just use the standard apr_setup_signal_thread to block all signals
2098 * from being received. The child processes no longer use signals for
2099 * any communication with the parent process.
2100 */
2101 rv = apr_setup_signal_thread();
2102 if (rv != APR_SUCCESS) {
2103 ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf, APLOGNO(00479)
2104 "Couldn't initialize signal thread");
2105 clean_child_exit(APEXIT_CHILDFATAL);
2106 }
2107
2108 if (ap_max_requests_per_child) {
2109 conns_this_child = ap_max_requests_per_child;
2110 }
2111 else {
2112 /* coding a value of zero means infinity */
2113 conns_this_child = APR_INT32_MAX;
2114 }
2115
2116 /* Setup worker threads */
2117
2118 /* clear the storage; we may not create all our threads immediately,
2119 * and we want a 0 entry to indicate a thread which was not created
2120 */
2121 threads = ap_calloc(threads_per_child, sizeof(apr_thread_t *));
2122 ts = apr_palloc(pchild, sizeof(*ts));
2123
2124 apr_threadattr_create(&thread_attr, pchild);
2125 /* 0 means PTHREAD_CREATE_JOINABLE */
2126 apr_threadattr_detach_set(thread_attr, 0);
2127
2128 if (ap_thread_stacksize != 0) {
2129 rv = apr_threadattr_stacksize_set(thread_attr, ap_thread_stacksize);
2130 if (rv != APR_SUCCESS && rv != APR_ENOTIMPL) {
2131 ap_log_error(APLOG_MARK, APLOG_WARNING, rv, ap_server_conf, APLOGNO(02436)
2132 "WARNING: ThreadStackSize of %" APR_SIZE_T_FMT " is "
2133 "inappropriate, using default",
2134 ap_thread_stacksize);
2135 }
2136 }
2137
2138 ts->threads = threads;
2139 ts->listener = NULL;
2140 ts->child_num_arg = child_num_arg;
2141 ts->threadattr = thread_attr;
2142
2143 rv = apr_thread_create(&start_thread_id, thread_attr, start_threads,
2144 ts, pchild);
2145 if (rv != APR_SUCCESS) {
2146 ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf, APLOGNO(00480)
2147 "apr_thread_create: unable to create worker thread");
2148 /* let the parent decide how bad this really is */
2149 clean_child_exit(APEXIT_CHILDSICK);
2150 }
2151
2152 mpm_state = AP_MPMQ_RUNNING;
2153
2154 /* If we are only running in one_process mode, we will want to
2155 * still handle signals. */
2156 if (one_process) {
2157 /* Block until we get a terminating signal. */
2158 apr_signal_thread(check_signal);
2159 /* make sure the start thread has finished; signal_threads()
2160 * and join_workers() depend on that
2161 */
2162 /* XXX join_start_thread() won't be awakened if one of our
2163 * threads encounters a critical error and attempts to
2164 * shutdown this child
2165 */
2166 join_start_thread(start_thread_id);
2167
2168 /* helps us terminate a little more quickly than the dispatch of the
2169 * signal thread; beats the Pipe of Death and the browsers
2170 */
2171 signal_threads(ST_UNGRACEFUL);
2172
2173 /* A terminating signal was received. Now join each of the
2174 * workers to clean them up.
2175 * If the worker already exited, then the join frees
2176 * their resources and returns.
2177 * If the worker hasn't exited, then this blocks until
2178 * they have (then cleans up).
2179 */
2180 join_workers(ts->listener, threads);
2181 }
2182 else { /* !one_process */
2183 /* remove SIGTERM from the set of blocked signals... if one of
2184 * the other threads in the process needs to take us down
2185 * (e.g., for MaxConnectionsPerChild) it will send us SIGTERM
2186 */
2187 unblock_signal(SIGTERM);
2188 apr_signal(SIGTERM, dummy_signal_handler);
2189 /* Watch for any messages from the parent over the POD */
2190 while (1) {
2191 rv = ap_event_pod_check(pod);
2192 if (rv == AP_NORESTART) {
2193 /* see if termination was triggered while we slept */
2194 switch (terminate_mode) {
2195 case ST_GRACEFUL:
2196 rv = AP_GRACEFUL;
2197 break;
2198 case ST_UNGRACEFUL:
2199 rv = AP_RESTART;
2200 break;
2201 }
2202 }
2203 if (rv == AP_GRACEFUL || rv == AP_RESTART) {
2204 /* make sure the start thread has finished;
2205 * signal_threads() and join_workers depend on that
2206 */
2207 join_start_thread(start_thread_id);
2208 signal_threads(rv ==
2209 AP_GRACEFUL ? ST_GRACEFUL : ST_UNGRACEFUL);
2210 break;
2211 }
2212 }
2213
2214 /* A terminating signal was received. Now join each of the
2215 * workers to clean them up.
2216 * If the worker already exited, then the join frees
2217 * their resources and returns.
2218 * If the worker hasn't exited, then this blocks until
2219 * they have (then cleans up).
2220 */
2221 join_workers(ts->listener, threads);
2222 }
2223
2224 free(threads);
2225
2226 clean_child_exit(resource_shortage ? APEXIT_CHILDSICK : 0);
2227 }
2228
make_child(server_rec * s,int slot)2229 static int make_child(server_rec * s, int slot)
2230 {
2231 int pid;
2232
2233 if (slot + 1 > retained->max_daemons_limit) {
2234 retained->max_daemons_limit = slot + 1;
2235 }
2236
2237 if (one_process) {
2238 set_signals();
2239 event_note_child_started(slot, getpid());
2240 child_main(slot);
2241 /* NOTREACHED */
2242 }
2243
2244 if ((pid = fork()) == -1) {
2245 ap_log_error(APLOG_MARK, APLOG_ERR, errno, s, APLOGNO(00481)
2246 "fork: Unable to fork new process");
2247
2248 /* fork didn't succeed. There's no need to touch the scoreboard;
2249 * if we were trying to replace a failed child process, then
2250 * server_main_loop() marked its workers SERVER_DEAD, and if
2251 * we were trying to replace a child process that exited normally,
2252 * its worker_thread()s left SERVER_DEAD or SERVER_GRACEFUL behind.
2253 */
2254
2255 /* In case system resources are maxxed out, we don't want
2256 Apache running away with the CPU trying to fork over and
2257 over and over again. */
2258 apr_sleep(apr_time_from_sec(10));
2259
2260 return -1;
2261 }
2262
2263 if (!pid) {
2264 #ifdef HAVE_BINDPROCESSOR
2265 /* By default, AIX binds to a single processor. This bit unbinds
2266 * children which will then bind to another CPU.
2267 */
2268 int status = bindprocessor(BINDPROCESS, (int) getpid(),
2269 PROCESSOR_CLASS_ANY);
2270 if (status != OK)
2271 ap_log_error(APLOG_MARK, APLOG_DEBUG, errno,
2272 ap_server_conf, APLOGNO(00482)
2273 "processor unbind failed");
2274 #endif
2275 RAISE_SIGSTOP(MAKE_CHILD);
2276
2277 apr_signal(SIGTERM, just_die);
2278 child_main(slot);
2279 /* NOTREACHED */
2280 }
2281 /* else */
2282 if (ap_scoreboard_image->parent[slot].pid != 0) {
2283 /* This new child process is squatting on the scoreboard
2284 * entry owned by an exiting child process, which cannot
2285 * exit until all active requests complete.
2286 */
2287 event_note_child_lost_slot(slot, pid);
2288 }
2289 ap_scoreboard_image->parent[slot].quiescing = 0;
2290 ap_scoreboard_image->parent[slot].not_accepting = 0;
2291 event_note_child_started(slot, pid);
2292 return 0;
2293 }
2294
2295 /* start up a bunch of children */
startup_children(int number_to_start)2296 static void startup_children(int number_to_start)
2297 {
2298 int i;
2299
2300 for (i = 0; number_to_start && i < ap_daemons_limit; ++i) {
2301 if (ap_scoreboard_image->parent[i].pid != 0) {
2302 continue;
2303 }
2304 if (make_child(ap_server_conf, i) < 0) {
2305 break;
2306 }
2307 --number_to_start;
2308 }
2309 }
2310
perform_idle_server_maintenance(void)2311 static void perform_idle_server_maintenance(void)
2312 {
2313 int i, j;
2314 int idle_thread_count;
2315 worker_score *ws;
2316 process_score *ps;
2317 int free_length;
2318 int totally_free_length = 0;
2319 int free_slots[MAX_SPAWN_RATE];
2320 int last_non_dead;
2321 int total_non_dead;
2322 int active_thread_count = 0;
2323
2324 /* initialize the free_list */
2325 free_length = 0;
2326
2327 idle_thread_count = 0;
2328 last_non_dead = -1;
2329 total_non_dead = 0;
2330
2331 for (i = 0; i < ap_daemons_limit; ++i) {
2332 /* Initialization to satisfy the compiler. It doesn't know
2333 * that threads_per_child is always > 0 */
2334 int status = SERVER_DEAD;
2335 int any_dying_threads = 0;
2336 int any_dead_threads = 0;
2337 int all_dead_threads = 1;
2338 int child_threads_active = 0;
2339
2340 if (i >= retained->max_daemons_limit
2341 && totally_free_length == retained->idle_spawn_rate)
2342 /* short cut if all active processes have been examined and
2343 * enough empty scoreboard slots have been found
2344 */
2345
2346 break;
2347 ps = &ap_scoreboard_image->parent[i];
2348 for (j = 0; j < threads_per_child; j++) {
2349 ws = &ap_scoreboard_image->servers[i][j];
2350 status = ws->status;
2351
2352 /* XXX any_dying_threads is probably no longer needed GLA */
2353 any_dying_threads = any_dying_threads ||
2354 (status == SERVER_GRACEFUL);
2355 any_dead_threads = any_dead_threads || (status == SERVER_DEAD);
2356 all_dead_threads = all_dead_threads &&
2357 (status == SERVER_DEAD || status == SERVER_GRACEFUL);
2358
2359 /* We consider a starting server as idle because we started it
2360 * at least a cycle ago, and if it still hasn't finished starting
2361 * then we're just going to swamp things worse by forking more.
2362 * So we hopefully won't need to fork more if we count it.
2363 * This depends on the ordering of SERVER_READY and SERVER_STARTING.
2364 */
2365 if (ps->pid != 0) { /* XXX just set all_dead_threads in outer
2366 for loop if no pid? not much else matters */
2367 if (status <= SERVER_READY && !ps->quiescing && !ps->not_accepting
2368 && ps->generation == retained->my_generation)
2369 {
2370 ++idle_thread_count;
2371 }
2372 if (status >= SERVER_READY && status < SERVER_GRACEFUL) {
2373 ++child_threads_active;
2374 }
2375 }
2376 }
2377 active_thread_count += child_threads_active;
2378 if (any_dead_threads
2379 && totally_free_length < retained->idle_spawn_rate
2380 && free_length < MAX_SPAWN_RATE
2381 && (!ps->pid /* no process in the slot */
2382 || ps->quiescing)) { /* or at least one is going away */
2383 if (all_dead_threads) {
2384 /* great! we prefer these, because the new process can
2385 * start more threads sooner. So prioritize this slot
2386 * by putting it ahead of any slots with active threads.
2387 *
2388 * first, make room by moving a slot that's potentially still
2389 * in use to the end of the array
2390 */
2391 free_slots[free_length] = free_slots[totally_free_length];
2392 free_slots[totally_free_length++] = i;
2393 }
2394 else {
2395 /* slot is still in use - back of the bus
2396 */
2397 free_slots[free_length] = i;
2398 }
2399 ++free_length;
2400 }
2401 else if (child_threads_active == threads_per_child) {
2402 had_healthy_child = 1;
2403 }
2404 /* XXX if (!ps->quiescing) is probably more reliable GLA */
2405 if (!any_dying_threads) {
2406 last_non_dead = i;
2407 ++total_non_dead;
2408 }
2409 }
2410
2411 if (retained->sick_child_detected) {
2412 if (had_healthy_child) {
2413 /* Assume this is a transient error, even though it may not be. Leave
2414 * the server up in case it is able to serve some requests or the
2415 * problem will be resolved.
2416 */
2417 retained->sick_child_detected = 0;
2418 }
2419 else {
2420 /* looks like a basket case, as no child ever fully initialized; give up.
2421 */
2422 shutdown_pending = 1;
2423 child_fatal = 1;
2424 ap_log_error(APLOG_MARK, APLOG_ALERT, 0,
2425 ap_server_conf, APLOGNO(02324)
2426 "A resource shortage or other unrecoverable failure "
2427 "was encountered before any child process initialized "
2428 "successfully... httpd is exiting!");
2429 /* the child already logged the failure details */
2430 return;
2431 }
2432 }
2433
2434 retained->max_daemons_limit = last_non_dead + 1;
2435
2436 if (idle_thread_count > max_spare_threads) {
2437 /* Kill off one child */
2438 ap_event_pod_signal(pod, TRUE);
2439 retained->idle_spawn_rate = 1;
2440 }
2441 else if (idle_thread_count < min_spare_threads) {
2442 /* terminate the free list */
2443 if (free_length == 0) { /* scoreboard is full, can't fork */
2444
2445 if (active_thread_count >= ap_daemons_limit * threads_per_child) {
2446 if (!retained->maxclients_reported) {
2447 /* only report this condition once */
2448 ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, APLOGNO(00484)
2449 "server reached MaxRequestWorkers setting, "
2450 "consider raising the MaxRequestWorkers "
2451 "setting");
2452 retained->maxclients_reported = 1;
2453 }
2454 }
2455 else {
2456 ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, APLOGNO(00485)
2457 "scoreboard is full, not at MaxRequestWorkers");
2458 }
2459 retained->idle_spawn_rate = 1;
2460 }
2461 else {
2462 if (free_length > retained->idle_spawn_rate) {
2463 free_length = retained->idle_spawn_rate;
2464 }
2465 if (retained->idle_spawn_rate >= 8) {
2466 ap_log_error(APLOG_MARK, APLOG_INFO, 0, ap_server_conf, APLOGNO(00486)
2467 "server seems busy, (you may need "
2468 "to increase StartServers, ThreadsPerChild "
2469 "or Min/MaxSpareThreads), "
2470 "spawning %d children, there are around %d idle "
2471 "threads, and %d total children", free_length,
2472 idle_thread_count, total_non_dead);
2473 }
2474 for (i = 0; i < free_length; ++i) {
2475 make_child(ap_server_conf, free_slots[i]);
2476 }
2477 /* the next time around we want to spawn twice as many if this
2478 * wasn't good enough, but not if we've just done a graceful
2479 */
2480 if (retained->hold_off_on_exponential_spawning) {
2481 --retained->hold_off_on_exponential_spawning;
2482 }
2483 else if (retained->idle_spawn_rate < MAX_SPAWN_RATE) {
2484 retained->idle_spawn_rate *= 2;
2485 }
2486 }
2487 }
2488 else {
2489 retained->idle_spawn_rate = 1;
2490 }
2491 }
2492
server_main_loop(int remaining_children_to_start)2493 static void server_main_loop(int remaining_children_to_start)
2494 {
2495 ap_generation_t old_gen;
2496 int child_slot;
2497 apr_exit_why_e exitwhy;
2498 int status, processed_status;
2499 apr_proc_t pid;
2500 int i;
2501
2502 while (!restart_pending && !shutdown_pending) {
2503 ap_wait_or_timeout(&exitwhy, &status, &pid, pconf, ap_server_conf);
2504
2505 if (pid.pid != -1) {
2506 processed_status = ap_process_child_status(&pid, exitwhy, status);
2507 child_slot = ap_find_child_by_pid(&pid);
2508 if (processed_status == APEXIT_CHILDFATAL) {
2509 /* fix race condition found in PR 39311
2510 * A child created at the same time as a graceful happens
2511 * can find the lock missing and create a fatal error.
2512 * It is not fatal for the last generation to be in this state.
2513 */
2514 if (child_slot < 0
2515 || ap_get_scoreboard_process(child_slot)->generation
2516 == retained->my_generation) {
2517 shutdown_pending = 1;
2518 child_fatal = 1;
2519 return;
2520 }
2521 else {
2522 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ap_server_conf, APLOGNO(00487)
2523 "Ignoring fatal error in child of previous "
2524 "generation (pid %ld).",
2525 (long)pid.pid);
2526 retained->sick_child_detected = 1;
2527 }
2528 }
2529 else if (processed_status == APEXIT_CHILDSICK) {
2530 /* tell perform_idle_server_maintenance to check into this
2531 * on the next timer pop
2532 */
2533 retained->sick_child_detected = 1;
2534 }
2535 /* non-fatal death... note that it's gone in the scoreboard. */
2536 if (child_slot >= 0) {
2537 for (i = 0; i < threads_per_child; i++)
2538 ap_update_child_status_from_indexes(child_slot, i,
2539 SERVER_DEAD,
2540 (request_rec *) NULL);
2541
2542 event_note_child_killed(child_slot, 0, 0);
2543 ap_scoreboard_image->parent[child_slot].quiescing = 0;
2544 if (processed_status == APEXIT_CHILDSICK) {
2545 /* resource shortage, minimize the fork rate */
2546 retained->idle_spawn_rate = 1;
2547 }
2548 else if (remaining_children_to_start
2549 && child_slot < ap_daemons_limit) {
2550 /* we're still doing a 1-for-1 replacement of dead
2551 * children with new children
2552 */
2553 make_child(ap_server_conf, child_slot);
2554 --remaining_children_to_start;
2555 }
2556 }
2557 else if (ap_unregister_extra_mpm_process(pid.pid, &old_gen) == 1) {
2558
2559 event_note_child_killed(-1, /* already out of the scoreboard */
2560 pid.pid, old_gen);
2561 if (processed_status == APEXIT_CHILDSICK
2562 && old_gen == retained->my_generation) {
2563 /* resource shortage, minimize the fork rate */
2564 retained->idle_spawn_rate = 1;
2565 }
2566 #if APR_HAS_OTHER_CHILD
2567 }
2568 else if (apr_proc_other_child_alert(&pid, APR_OC_REASON_DEATH,
2569 status) == 0) {
2570 /* handled */
2571 #endif
2572 }
2573 else if (retained->is_graceful) {
2574 /* Great, we've probably just lost a slot in the
2575 * scoreboard. Somehow we don't know about this child.
2576 */
2577 ap_log_error(APLOG_MARK, APLOG_WARNING, 0,
2578 ap_server_conf, APLOGNO(00488)
2579 "long lost child came home! (pid %ld)",
2580 (long) pid.pid);
2581 }
2582 /* Don't perform idle maintenance when a child dies,
2583 * only do it when there's a timeout. Remember only a
2584 * finite number of children can die, and it's pretty
2585 * pathological for a lot to die suddenly.
2586 */
2587 continue;
2588 }
2589 else if (remaining_children_to_start) {
2590 /* we hit a 1 second timeout in which none of the previous
2591 * generation of children needed to be reaped... so assume
2592 * they're all done, and pick up the slack if any is left.
2593 */
2594 startup_children(remaining_children_to_start);
2595 remaining_children_to_start = 0;
2596 /* In any event we really shouldn't do the code below because
2597 * few of the servers we just started are in the IDLE state
2598 * yet, so we'd mistakenly create an extra server.
2599 */
2600 continue;
2601 }
2602
2603 perform_idle_server_maintenance();
2604 }
2605 }
2606
event_run(apr_pool_t * _pconf,apr_pool_t * plog,server_rec * s)2607 static int event_run(apr_pool_t * _pconf, apr_pool_t * plog, server_rec * s)
2608 {
2609 int remaining_children_to_start;
2610
2611 ap_log_pid(pconf, ap_pid_fname);
2612
2613 if (!retained->is_graceful) {
2614 if (ap_run_pre_mpm(s->process->pool, SB_SHARED) != OK) {
2615 mpm_state = AP_MPMQ_STOPPING;
2616 return DONE;
2617 }
2618 /* fix the generation number in the global score; we just got a new,
2619 * cleared scoreboard
2620 */
2621 ap_scoreboard_image->global->running_generation = retained->my_generation;
2622 }
2623
2624 restart_pending = shutdown_pending = 0;
2625 set_signals();
2626 /* Don't thrash... */
2627 if (max_spare_threads < min_spare_threads + threads_per_child)
2628 max_spare_threads = min_spare_threads + threads_per_child;
2629
2630 /* If we're doing a graceful_restart then we're going to see a lot
2631 * of children exiting immediately when we get into the main loop
2632 * below (because we just sent them AP_SIG_GRACEFUL). This happens pretty
2633 * rapidly... and for each one that exits we may start a new one, until
2634 * there are at least min_spare_threads idle threads, counting across
2635 * all children. But we may be permitted to start more children than
2636 * that, so we'll just keep track of how many we're
2637 * supposed to start up without the 1 second penalty between each fork.
2638 */
2639 remaining_children_to_start = ap_daemons_to_start;
2640 if (remaining_children_to_start > ap_daemons_limit) {
2641 remaining_children_to_start = ap_daemons_limit;
2642 }
2643 if (!retained->is_graceful) {
2644 startup_children(remaining_children_to_start);
2645 remaining_children_to_start = 0;
2646 }
2647 else {
2648 /* give the system some time to recover before kicking into
2649 * exponential mode */
2650 retained->hold_off_on_exponential_spawning = 10;
2651 }
2652
2653 ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, APLOGNO(00489)
2654 "%s configured -- resuming normal operations",
2655 ap_get_server_description());
2656 ap_log_error(APLOG_MARK, APLOG_INFO, 0, ap_server_conf, APLOGNO(00490)
2657 "Server built: %s", ap_get_server_built());
2658 ap_log_command_line(plog, s);
2659
2660 mpm_state = AP_MPMQ_RUNNING;
2661
2662 server_main_loop(remaining_children_to_start);
2663 mpm_state = AP_MPMQ_STOPPING;
2664
2665 if (shutdown_pending && !retained->is_graceful) {
2666 /* Time to shut down:
2667 * Kill child processes, tell them to call child_exit, etc...
2668 */
2669 ap_event_pod_killpg(pod, ap_daemons_limit, FALSE);
2670 ap_reclaim_child_processes(1, /* Start with SIGTERM */
2671 event_note_child_killed);
2672
2673 if (!child_fatal) {
2674 /* cleanup pid file on normal shutdown */
2675 ap_remove_pid(pconf, ap_pid_fname);
2676 ap_log_error(APLOG_MARK, APLOG_NOTICE, 0,
2677 ap_server_conf, APLOGNO(00491) "caught SIGTERM, shutting down");
2678 }
2679 return DONE;
2680 } else if (shutdown_pending) {
2681 /* Time to gracefully shut down:
2682 * Kill child processes, tell them to call child_exit, etc...
2683 */
2684 int active_children;
2685 int index;
2686 apr_time_t cutoff = 0;
2687
2688 /* Close our listeners, and then ask our children to do same */
2689 ap_close_listeners();
2690 ap_event_pod_killpg(pod, ap_daemons_limit, TRUE);
2691 ap_relieve_child_processes(event_note_child_killed);
2692
2693 if (!child_fatal) {
2694 /* cleanup pid file on normal shutdown */
2695 ap_remove_pid(pconf, ap_pid_fname);
2696 ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, APLOGNO(00492)
2697 "caught " AP_SIG_GRACEFUL_STOP_STRING
2698 ", shutting down gracefully");
2699 }
2700
2701 if (ap_graceful_shutdown_timeout) {
2702 cutoff = apr_time_now() +
2703 apr_time_from_sec(ap_graceful_shutdown_timeout);
2704 }
2705
2706 /* Don't really exit until each child has finished */
2707 shutdown_pending = 0;
2708 do {
2709 /* Pause for a second */
2710 apr_sleep(apr_time_from_sec(1));
2711
2712 /* Relieve any children which have now exited */
2713 ap_relieve_child_processes(event_note_child_killed);
2714
2715 active_children = 0;
2716 for (index = 0; index < ap_daemons_limit; ++index) {
2717 if (ap_mpm_safe_kill(MPM_CHILD_PID(index), 0) == APR_SUCCESS) {
2718 active_children = 1;
2719 /* Having just one child is enough to stay around */
2720 break;
2721 }
2722 }
2723 } while (!shutdown_pending && active_children &&
2724 (!ap_graceful_shutdown_timeout || apr_time_now() < cutoff));
2725
2726 /* We might be here because we received SIGTERM, either
2727 * way, try and make sure that all of our processes are
2728 * really dead.
2729 */
2730 ap_event_pod_killpg(pod, ap_daemons_limit, FALSE);
2731 ap_reclaim_child_processes(1, event_note_child_killed);
2732
2733 return DONE;
2734 }
2735
2736 /* we've been told to restart */
2737 apr_signal(SIGHUP, SIG_IGN);
2738
2739 if (one_process) {
2740 /* not worth thinking about */
2741 return DONE;
2742 }
2743
2744 /* advance to the next generation */
2745 /* XXX: we really need to make sure this new generation number isn't in
2746 * use by any of the children.
2747 */
2748 ++retained->my_generation;
2749 ap_scoreboard_image->global->running_generation = retained->my_generation;
2750
2751 if (retained->is_graceful) {
2752 ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, APLOGNO(00493)
2753 AP_SIG_GRACEFUL_STRING
2754 " received. Doing graceful restart");
2755 /* wake up the children...time to die. But we'll have more soon */
2756 ap_event_pod_killpg(pod, ap_daemons_limit, TRUE);
2757
2758
2759 /* This is mostly for debugging... so that we know what is still
2760 * gracefully dealing with existing request.
2761 */
2762
2763 }
2764 else {
2765 /* Kill 'em all. Since the child acts the same on the parents SIGTERM
2766 * and a SIGHUP, we may as well use the same signal, because some user
2767 * pthreads are stealing signals from us left and right.
2768 */
2769 ap_event_pod_killpg(pod, ap_daemons_limit, FALSE);
2770
2771 ap_reclaim_child_processes(1, /* Start with SIGTERM */
2772 event_note_child_killed);
2773 ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, APLOGNO(00494)
2774 "SIGHUP received. Attempting to restart");
2775 }
2776
2777 return OK;
2778 }
2779
2780 /* This really should be a post_config hook, but the error log is already
2781 * redirected by that point, so we need to do this in the open_logs phase.
2782 */
event_open_logs(apr_pool_t * p,apr_pool_t * plog,apr_pool_t * ptemp,server_rec * s)2783 static int event_open_logs(apr_pool_t * p, apr_pool_t * plog,
2784 apr_pool_t * ptemp, server_rec * s)
2785 {
2786 int startup = 0;
2787 int level_flags = 0;
2788 apr_status_t rv;
2789
2790 pconf = p;
2791
2792 /* the reverse of pre_config, we want this only the first time around */
2793 if (retained->module_loads == 1) {
2794 startup = 1;
2795 level_flags |= APLOG_STARTUP;
2796 }
2797
2798 if ((num_listensocks = ap_setup_listeners(ap_server_conf)) < 1) {
2799 ap_log_error(APLOG_MARK, APLOG_ALERT | level_flags, 0,
2800 (startup ? NULL : s),
2801 "no listening sockets available, shutting down");
2802 return DONE;
2803 }
2804
2805 if (!one_process) {
2806 if ((rv = ap_event_pod_open(pconf, &pod))) {
2807 ap_log_error(APLOG_MARK, APLOG_CRIT | level_flags, rv,
2808 (startup ? NULL : s),
2809 "could not open pipe-of-death");
2810 return DONE;
2811 }
2812 }
2813 return OK;
2814 }
2815
event_pre_config(apr_pool_t * pconf,apr_pool_t * plog,apr_pool_t * ptemp)2816 static int event_pre_config(apr_pool_t * pconf, apr_pool_t * plog,
2817 apr_pool_t * ptemp)
2818 {
2819 int no_detach, debug, foreground;
2820 apr_status_t rv;
2821 const char *userdata_key = "mpm_event_module";
2822
2823 mpm_state = AP_MPMQ_STARTING;
2824
2825 debug = ap_exists_config_define("DEBUG");
2826
2827 if (debug) {
2828 foreground = one_process = 1;
2829 no_detach = 0;
2830 }
2831 else {
2832 one_process = ap_exists_config_define("ONE_PROCESS");
2833 no_detach = ap_exists_config_define("NO_DETACH");
2834 foreground = ap_exists_config_define("FOREGROUND");
2835 }
2836
2837 /* sigh, want this only the second time around */
2838 retained = ap_retained_data_get(userdata_key);
2839 if (!retained) {
2840 retained = ap_retained_data_create(userdata_key, sizeof(*retained));
2841 retained->max_daemons_limit = -1;
2842 retained->idle_spawn_rate = 1;
2843 }
2844 ++retained->module_loads;
2845 if (retained->module_loads == 2) {
2846 rv = apr_pollset_create(&event_pollset, 1, plog,
2847 APR_POLLSET_THREADSAFE | APR_POLLSET_NOCOPY);
2848 if (rv != APR_SUCCESS) {
2849 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL, APLOGNO(00495)
2850 "Couldn't create a Thread Safe Pollset. "
2851 "Is it supported on your platform?"
2852 "Also check system or user limits!");
2853 return HTTP_INTERNAL_SERVER_ERROR;
2854 }
2855 apr_pollset_destroy(event_pollset);
2856
2857 if (!one_process && !foreground) {
2858 /* before we detach, setup crash handlers to log to errorlog */
2859 ap_fatal_signal_setup(ap_server_conf, pconf);
2860 rv = apr_proc_detach(no_detach ? APR_PROC_DETACH_FOREGROUND
2861 : APR_PROC_DETACH_DAEMONIZE);
2862 if (rv != APR_SUCCESS) {
2863 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL, APLOGNO(00496)
2864 "apr_proc_detach failed");
2865 return HTTP_INTERNAL_SERVER_ERROR;
2866 }
2867 }
2868 }
2869
2870 parent_pid = ap_my_pid = getpid();
2871
2872 ap_listen_pre_config();
2873 ap_daemons_to_start = DEFAULT_START_DAEMON;
2874 min_spare_threads = DEFAULT_MIN_FREE_DAEMON * DEFAULT_THREADS_PER_CHILD;
2875 max_spare_threads = DEFAULT_MAX_FREE_DAEMON * DEFAULT_THREADS_PER_CHILD;
2876 server_limit = DEFAULT_SERVER_LIMIT;
2877 thread_limit = DEFAULT_THREAD_LIMIT;
2878 ap_daemons_limit = server_limit;
2879 threads_per_child = DEFAULT_THREADS_PER_CHILD;
2880 max_workers = ap_daemons_limit * threads_per_child;
2881 had_healthy_child = 0;
2882 ap_extended_status = 0;
2883
2884 return OK;
2885 }
2886
event_check_config(apr_pool_t * p,apr_pool_t * plog,apr_pool_t * ptemp,server_rec * s)2887 static int event_check_config(apr_pool_t *p, apr_pool_t *plog,
2888 apr_pool_t *ptemp, server_rec *s)
2889 {
2890 int startup = 0;
2891
2892 /* the reverse of pre_config, we want this only the first time around */
2893 if (retained->module_loads == 1) {
2894 startup = 1;
2895 }
2896
2897 if (server_limit > MAX_SERVER_LIMIT) {
2898 if (startup) {
2899 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00497)
2900 "WARNING: ServerLimit of %d exceeds compile-time "
2901 "limit of", server_limit);
2902 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2903 " %d servers, decreasing to %d.",
2904 MAX_SERVER_LIMIT, MAX_SERVER_LIMIT);
2905 } else {
2906 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00498)
2907 "ServerLimit of %d exceeds compile-time limit "
2908 "of %d, decreasing to match",
2909 server_limit, MAX_SERVER_LIMIT);
2910 }
2911 server_limit = MAX_SERVER_LIMIT;
2912 }
2913 else if (server_limit < 1) {
2914 if (startup) {
2915 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00499)
2916 "WARNING: ServerLimit of %d not allowed, "
2917 "increasing to 1.", server_limit);
2918 } else {
2919 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00500)
2920 "ServerLimit of %d not allowed, increasing to 1",
2921 server_limit);
2922 }
2923 server_limit = 1;
2924 }
2925
2926 /* you cannot change ServerLimit across a restart; ignore
2927 * any such attempts
2928 */
2929 if (!retained->first_server_limit) {
2930 retained->first_server_limit = server_limit;
2931 }
2932 else if (server_limit != retained->first_server_limit) {
2933 /* don't need a startup console version here */
2934 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00501)
2935 "changing ServerLimit to %d from original value of %d "
2936 "not allowed during restart",
2937 server_limit, retained->first_server_limit);
2938 server_limit = retained->first_server_limit;
2939 }
2940
2941 if (thread_limit > MAX_THREAD_LIMIT) {
2942 if (startup) {
2943 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00502)
2944 "WARNING: ThreadLimit of %d exceeds compile-time "
2945 "limit of", thread_limit);
2946 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2947 " %d threads, decreasing to %d.",
2948 MAX_THREAD_LIMIT, MAX_THREAD_LIMIT);
2949 } else {
2950 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00503)
2951 "ThreadLimit of %d exceeds compile-time limit "
2952 "of %d, decreasing to match",
2953 thread_limit, MAX_THREAD_LIMIT);
2954 }
2955 thread_limit = MAX_THREAD_LIMIT;
2956 }
2957 else if (thread_limit < 1) {
2958 if (startup) {
2959 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00504)
2960 "WARNING: ThreadLimit of %d not allowed, "
2961 "increasing to 1.", thread_limit);
2962 } else {
2963 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00505)
2964 "ThreadLimit of %d not allowed, increasing to 1",
2965 thread_limit);
2966 }
2967 thread_limit = 1;
2968 }
2969
2970 /* you cannot change ThreadLimit across a restart; ignore
2971 * any such attempts
2972 */
2973 if (!retained->first_thread_limit) {
2974 retained->first_thread_limit = thread_limit;
2975 }
2976 else if (thread_limit != retained->first_thread_limit) {
2977 /* don't need a startup console version here */
2978 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00506)
2979 "changing ThreadLimit to %d from original value of %d "
2980 "not allowed during restart",
2981 thread_limit, retained->first_thread_limit);
2982 thread_limit = retained->first_thread_limit;
2983 }
2984
2985 if (threads_per_child > thread_limit) {
2986 if (startup) {
2987 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00507)
2988 "WARNING: ThreadsPerChild of %d exceeds ThreadLimit "
2989 "of", threads_per_child);
2990 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2991 " %d threads, decreasing to %d.",
2992 thread_limit, thread_limit);
2993 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
2994 " To increase, please see the ThreadLimit "
2995 "directive.");
2996 } else {
2997 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00508)
2998 "ThreadsPerChild of %d exceeds ThreadLimit "
2999 "of %d, decreasing to match",
3000 threads_per_child, thread_limit);
3001 }
3002 threads_per_child = thread_limit;
3003 }
3004 else if (threads_per_child < 1) {
3005 if (startup) {
3006 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00509)
3007 "WARNING: ThreadsPerChild of %d not allowed, "
3008 "increasing to 1.", threads_per_child);
3009 } else {
3010 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00510)
3011 "ThreadsPerChild of %d not allowed, increasing to 1",
3012 threads_per_child);
3013 }
3014 threads_per_child = 1;
3015 }
3016
3017 if (max_workers < threads_per_child) {
3018 if (startup) {
3019 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00511)
3020 "WARNING: MaxRequestWorkers of %d is less than "
3021 "ThreadsPerChild of", max_workers);
3022 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
3023 " %d, increasing to %d. MaxRequestWorkers must be at "
3024 "least as large",
3025 threads_per_child, threads_per_child);
3026 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
3027 " as the number of threads in a single server.");
3028 } else {
3029 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00512)
3030 "MaxRequestWorkers of %d is less than ThreadsPerChild "
3031 "of %d, increasing to match",
3032 max_workers, threads_per_child);
3033 }
3034 max_workers = threads_per_child;
3035 }
3036
3037 ap_daemons_limit = max_workers / threads_per_child;
3038
3039 if (max_workers % threads_per_child) {
3040 int tmp_max_workers = ap_daemons_limit * threads_per_child;
3041
3042 if (startup) {
3043 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00513)
3044 "WARNING: MaxRequestWorkers of %d is not an integer "
3045 "multiple of", max_workers);
3046 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
3047 " ThreadsPerChild of %d, decreasing to nearest "
3048 "multiple %d,", threads_per_child,
3049 tmp_max_workers);
3050 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
3051 " for a maximum of %d servers.",
3052 ap_daemons_limit);
3053 } else {
3054 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00514)
3055 "MaxRequestWorkers of %d is not an integer multiple "
3056 "of ThreadsPerChild of %d, decreasing to nearest "
3057 "multiple %d", max_workers, threads_per_child,
3058 tmp_max_workers);
3059 }
3060 max_workers = tmp_max_workers;
3061 }
3062
3063 if (ap_daemons_limit > server_limit) {
3064 if (startup) {
3065 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00515)
3066 "WARNING: MaxRequestWorkers of %d would require %d "
3067 "servers and ", max_workers, ap_daemons_limit);
3068 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
3069 " would exceed ServerLimit of %d, decreasing to %d.",
3070 server_limit, server_limit * threads_per_child);
3071 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
3072 " To increase, please see the ServerLimit "
3073 "directive.");
3074 } else {
3075 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00516)
3076 "MaxRequestWorkers of %d would require %d servers and "
3077 "exceed ServerLimit of %d, decreasing to %d",
3078 max_workers, ap_daemons_limit, server_limit,
3079 server_limit * threads_per_child);
3080 }
3081 ap_daemons_limit = server_limit;
3082 }
3083
3084 /* ap_daemons_to_start > ap_daemons_limit checked in ap_mpm_run() */
3085 if (ap_daemons_to_start < 0) {
3086 if (startup) {
3087 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00517)
3088 "WARNING: StartServers of %d not allowed, "
3089 "increasing to 1.", ap_daemons_to_start);
3090 } else {
3091 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00518)
3092 "StartServers of %d not allowed, increasing to 1",
3093 ap_daemons_to_start);
3094 }
3095 ap_daemons_to_start = 1;
3096 }
3097
3098 if (min_spare_threads < 1) {
3099 if (startup) {
3100 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00519)
3101 "WARNING: MinSpareThreads of %d not allowed, "
3102 "increasing to 1", min_spare_threads);
3103 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
3104 " to avoid almost certain server failure.");
3105 ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL,
3106 " Please read the documentation.");
3107 } else {
3108 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00520)
3109 "MinSpareThreads of %d not allowed, increasing to 1",
3110 min_spare_threads);
3111 }
3112 min_spare_threads = 1;
3113 }
3114
3115 /* max_spare_threads < min_spare_threads + threads_per_child
3116 * checked in ap_mpm_run()
3117 */
3118
3119 return OK;
3120 }
3121
event_hooks(apr_pool_t * p)3122 static void event_hooks(apr_pool_t * p)
3123 {
3124 /* Our open_logs hook function must run before the core's, or stderr
3125 * will be redirected to a file, and the messages won't print to the
3126 * console.
3127 */
3128 static const char *const aszSucc[] = { "core.c", NULL };
3129 one_process = 0;
3130
3131 ap_hook_open_logs(event_open_logs, NULL, aszSucc, APR_HOOK_REALLY_FIRST);
3132 /* we need to set the MPM state before other pre-config hooks use MPM query
3133 * to retrieve it, so register as REALLY_FIRST
3134 */
3135 ap_hook_pre_config(event_pre_config, NULL, NULL, APR_HOOK_REALLY_FIRST);
3136 ap_hook_check_config(event_check_config, NULL, NULL, APR_HOOK_MIDDLE);
3137 ap_hook_mpm(event_run, NULL, NULL, APR_HOOK_MIDDLE);
3138 ap_hook_mpm_query(event_query, NULL, NULL, APR_HOOK_MIDDLE);
3139 ap_hook_mpm_register_timed_callback(event_register_timed_callback, NULL, NULL,
3140 APR_HOOK_MIDDLE);
3141 ap_hook_mpm_get_name(event_get_name, NULL, NULL, APR_HOOK_MIDDLE);
3142 }
3143
set_daemons_to_start(cmd_parms * cmd,void * dummy,const char * arg)3144 static const char *set_daemons_to_start(cmd_parms *cmd, void *dummy,
3145 const char *arg)
3146 {
3147 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3148 if (err != NULL) {
3149 return err;
3150 }
3151
3152 ap_daemons_to_start = atoi(arg);
3153 return NULL;
3154 }
3155
set_min_spare_threads(cmd_parms * cmd,void * dummy,const char * arg)3156 static const char *set_min_spare_threads(cmd_parms * cmd, void *dummy,
3157 const char *arg)
3158 {
3159 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3160 if (err != NULL) {
3161 return err;
3162 }
3163
3164 min_spare_threads = atoi(arg);
3165 return NULL;
3166 }
3167
set_max_spare_threads(cmd_parms * cmd,void * dummy,const char * arg)3168 static const char *set_max_spare_threads(cmd_parms * cmd, void *dummy,
3169 const char *arg)
3170 {
3171 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3172 if (err != NULL) {
3173 return err;
3174 }
3175
3176 max_spare_threads = atoi(arg);
3177 return NULL;
3178 }
3179
set_max_workers(cmd_parms * cmd,void * dummy,const char * arg)3180 static const char *set_max_workers(cmd_parms * cmd, void *dummy,
3181 const char *arg)
3182 {
3183 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3184 if (err != NULL) {
3185 return err;
3186 }
3187 if (!strcasecmp(cmd->cmd->name, "MaxClients")) {
3188 ap_log_error(APLOG_MARK, APLOG_INFO, 0, NULL, APLOGNO(00521)
3189 "MaxClients is deprecated, use MaxRequestWorkers "
3190 "instead.");
3191 }
3192 max_workers = atoi(arg);
3193 return NULL;
3194 }
3195
set_threads_per_child(cmd_parms * cmd,void * dummy,const char * arg)3196 static const char *set_threads_per_child(cmd_parms * cmd, void *dummy,
3197 const char *arg)
3198 {
3199 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3200 if (err != NULL) {
3201 return err;
3202 }
3203
3204 threads_per_child = atoi(arg);
3205 return NULL;
3206 }
set_server_limit(cmd_parms * cmd,void * dummy,const char * arg)3207 static const char *set_server_limit (cmd_parms *cmd, void *dummy, const char *arg)
3208 {
3209 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3210 if (err != NULL) {
3211 return err;
3212 }
3213
3214 server_limit = atoi(arg);
3215 return NULL;
3216 }
3217
set_thread_limit(cmd_parms * cmd,void * dummy,const char * arg)3218 static const char *set_thread_limit(cmd_parms * cmd, void *dummy,
3219 const char *arg)
3220 {
3221 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3222 if (err != NULL) {
3223 return err;
3224 }
3225
3226 thread_limit = atoi(arg);
3227 return NULL;
3228 }
3229
set_worker_factor(cmd_parms * cmd,void * dummy,const char * arg)3230 static const char *set_worker_factor(cmd_parms * cmd, void *dummy,
3231 const char *arg)
3232 {
3233 double val;
3234 char *endptr;
3235 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3236 if (err != NULL) {
3237 return err;
3238 }
3239
3240 val = strtod(arg, &endptr);
3241 if (*endptr)
3242 return "error parsing value";
3243
3244 if (val <= 0)
3245 return "AsyncRequestWorkerFactor argument must be a positive number";
3246
3247 worker_factor = val * WORKER_FACTOR_SCALE;
3248 if (worker_factor == 0)
3249 worker_factor = 1;
3250 return NULL;
3251 }
3252
3253
3254 static const command_rec event_cmds[] = {
3255 LISTEN_COMMANDS,
3256 AP_INIT_TAKE1("StartServers", set_daemons_to_start, NULL, RSRC_CONF,
3257 "Number of child processes launched at server startup"),
3258 AP_INIT_TAKE1("ServerLimit", set_server_limit, NULL, RSRC_CONF,
3259 "Maximum number of child processes for this run of Apache"),
3260 AP_INIT_TAKE1("MinSpareThreads", set_min_spare_threads, NULL, RSRC_CONF,
3261 "Minimum number of idle threads, to handle request spikes"),
3262 AP_INIT_TAKE1("MaxSpareThreads", set_max_spare_threads, NULL, RSRC_CONF,
3263 "Maximum number of idle threads"),
3264 AP_INIT_TAKE1("MaxClients", set_max_workers, NULL, RSRC_CONF,
3265 "Deprecated name of MaxRequestWorkers"),
3266 AP_INIT_TAKE1("MaxRequestWorkers", set_max_workers, NULL, RSRC_CONF,
3267 "Maximum number of threads alive at the same time"),
3268 AP_INIT_TAKE1("ThreadsPerChild", set_threads_per_child, NULL, RSRC_CONF,
3269 "Number of threads each child creates"),
3270 AP_INIT_TAKE1("ThreadLimit", set_thread_limit, NULL, RSRC_CONF,
3271 "Maximum number of worker threads per child process for this "
3272 "run of Apache - Upper limit for ThreadsPerChild"),
3273 AP_INIT_TAKE1("AsyncRequestWorkerFactor", set_worker_factor, NULL, RSRC_CONF,
3274 "How many additional connects will be accepted per idle "
3275 "worker thread"),
3276 AP_GRACEFUL_SHUTDOWN_TIMEOUT_COMMAND,
3277 {NULL}
3278 };
3279
3280 AP_DECLARE_MODULE(mpm_event) = {
3281 MPM20_MODULE_STUFF,
3282 NULL, /* hook to run before apache parses args */
3283 NULL, /* create per-directory config structure */
3284 NULL, /* merge per-directory config structures */
3285 NULL, /* create per-server config structure */
3286 NULL, /* merge per-server config structures */
3287 event_cmds, /* command apr_table_t */
3288 event_hooks /* register_hooks */
3289 };
3290