/[Apache-SVN]/httpd/httpd/branches/2.2.x/server/mpm/worker/worker.c
ViewVC logotype

Contents of /httpd/httpd/branches/2.2.x/server/mpm/worker/worker.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 556936 - (show annotations)
Tue Jul 17 14:48:25 2007 UTC (2 years, 4 months ago) by jorton
File MIME type: text/plain
File size: 81596 byte(s)
Merge r551843, r551889 from trunk:

Add alternative fixes for CVE-2007-3304:

* configure.in: Check for getpgid.

* include/mpm_common.h (ap_mpm_safe_kill): New prototype.

* server/mpm_common.c (reclaim_one_pid): Ensure pid validity before
calling apr_proc_wait().
(ap_mpm_safe_kill): New function.

* server/mpm/prefork/prefork.c, server/mpm/worker/worker.c,
server/mpm/experimental/event/event.c: Use ap_mpm_safe_kill() on pids
from the scoreboard, throughout.

* include/ap_mmn.h: Minor bump.

* server/mpm_common.c: getpgid() returns a pid_t

Submitted by: jorton, jim
Reviewed by: jorton, jim, rpluem
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 /* The purpose of this MPM is to fix the design flaws in the threaded
18 * model. Because of the way that pthreads and mutex locks interact,
19 * it is basically impossible to cleanly gracefully shutdown a child
20 * process if multiple threads are all blocked in accept. This model
21 * fixes those problems.
22 */
23
24 #include "apr.h"
25 #include "apr_portable.h"
26 #include "apr_strings.h"
27 #include "apr_file_io.h"
28 #include "apr_thread_proc.h"
29 #include "apr_signal.h"
30 #include "apr_thread_mutex.h"
31 #include "apr_proc_mutex.h"
32 #include "apr_poll.h"
33 #define APR_WANT_STRFUNC
34 #include "apr_want.h"
35
36 #if APR_HAVE_UNISTD_H
37 #include <unistd.h>
38 #endif
39 #if APR_HAVE_SYS_SOCKET_H
40 #include <sys/socket.h>
41 #endif
42 #if APR_HAVE_SYS_WAIT_H
43 #include <sys/wait.h>
44 #endif
45 #ifdef HAVE_SYS_PROCESSOR_H
46 #include <sys/processor.h> /* for bindprocessor() */
47 #endif
48
49 #if !APR_HAS_THREADS
50 #error The Worker MPM requires APR threads, but they are unavailable.
51 #endif
52
53 #define CORE_PRIVATE
54
55 #include "ap_config.h"
56 #include "httpd.h"
57 #include "http_main.h"
58 #include "http_log.h"
59 #include "http_config.h" /* for read_config */
60 #include "http_core.h" /* for get_remote_host */
61 #include "http_connection.h"
62 #include "ap_mpm.h"
63 #include "pod.h"
64 #include "mpm_common.h"
65 #include "ap_listen.h"
66 #include "scoreboard.h"
67 #include "fdqueue.h"
68 #include "mpm_default.h"
69
70 #include <signal.h>
71 #include <limits.h> /* for INT_MAX */
72
73 /* Limit on the total --- clients will be locked out if more servers than
74 * this are needed. It is intended solely to keep the server from crashing
75 * when things get out of hand.
76 *
77 * We keep a hard maximum number of servers, for two reasons --- first off,
78 * in case something goes seriously wrong, we want to stop the fork bomb
79 * short of actually crashing the machine we're running on by filling some
80 * kernel table. Secondly, it keeps the size of the scoreboard file small
81 * enough that we can read the whole thing without worrying too much about
82 * the overhead.
83 */
84 #ifndef DEFAULT_SERVER_LIMIT
85 #define DEFAULT_SERVER_LIMIT 16
86 #endif
87
88 /* Admin can't tune ServerLimit beyond MAX_SERVER_LIMIT. We want
89 * some sort of compile-time limit to help catch typos.
90 */
91 #ifndef MAX_SERVER_LIMIT
92 #define MAX_SERVER_LIMIT 20000
93 #endif
94
95 /* Limit on the threads per process. Clients will be locked out if more than
96 * this * server_limit are needed.
97 *
98 * We keep this for one reason it keeps the size of the scoreboard file small
99 * enough that we can read the whole thing without worrying too much about
100 * the overhead.
101 */
102 #ifndef DEFAULT_THREAD_LIMIT
103 #define DEFAULT_THREAD_LIMIT 64
104 #endif
105
106 /* Admin can't tune ThreadLimit beyond MAX_THREAD_LIMIT. We want
107 * some sort of compile-time limit to help catch typos.
108 */
109 #ifndef MAX_THREAD_LIMIT
110 #define MAX_THREAD_LIMIT 20000
111 #endif
112
113 /*
114 * Actual definitions of config globals
115 */
116
117 int ap_threads_per_child = 0; /* Worker threads per child */
118 static int ap_daemons_to_start = 0;
119 static int min_spare_threads = 0;
120 static int max_spare_threads = 0;
121 static int ap_daemons_limit = 0;
122 static int server_limit = DEFAULT_SERVER_LIMIT;
123 static int first_server_limit = 0;
124 static int thread_limit = DEFAULT_THREAD_LIMIT;
125 static int first_thread_limit = 0;
126 static int changed_limit_at_restart;
127 static int dying = 0;
128 static int workers_may_exit = 0;
129 static int start_thread_may_exit = 0;
130 static int listener_may_exit = 0;
131 static int requests_this_child;
132 static int num_listensocks = 0;
133 static int resource_shortage = 0;
134 static fd_queue_t *worker_queue;
135 static fd_queue_info_t *worker_queue_info;
136 static int mpm_state = AP_MPMQ_STARTING;
137 static int sick_child_detected;
138
139 /* The structure used to pass unique initialization info to each thread */
140 typedef struct {
141 int pid;
142 int tid;
143 int sd;
144 } proc_info;
145
146 /* Structure used to pass information to the thread responsible for
147 * creating the rest of the threads.
148 */
149 typedef struct {
150 apr_thread_t **threads;
151 apr_thread_t *listener;
152 int child_num_arg;
153 apr_threadattr_t *threadattr;
154 } thread_starter;
155
156 #define ID_FROM_CHILD_THREAD(c, t) ((c * thread_limit) + t)
157
158 /*
159 * The max child slot ever assigned, preserved across restarts. Necessary
160 * to deal with MaxClients changes across AP_SIG_GRACEFUL restarts. We
161 * use this value to optimize routines that have to scan the entire
162 * scoreboard.
163 */
164 int ap_max_daemons_limit = -1;
165
166 static ap_pod_t *pod;
167
168 /* *Non*-shared http_main globals... */
169
170 server_rec *ap_server_conf;
171
172 /* The worker MPM respects a couple of runtime flags that can aid
173 * in debugging. Setting the -DNO_DETACH flag will prevent the root process
174 * from detaching from its controlling terminal. Additionally, setting
175 * the -DONE_PROCESS flag (which implies -DNO_DETACH) will get you the
176 * child_main loop running in the process which originally started up.
177 * This gives you a pretty nice debugging environment. (You'll get a SIGHUP
178 * early in standalone_main; just continue through. This is the server
179 * trying to kill off any child processes which it might have lying
180 * around --- Apache doesn't keep track of their pids, it just sends
181 * SIGHUP to the process group, ignoring it in the root process.
182 * Continue through and you'll be fine.).
183 */
184
185 static int one_process = 0;
186
187 #ifdef DEBUG_SIGSTOP
188 int raise_sigstop_flags;
189 #endif
190
191 static apr_pool_t *pconf; /* Pool for config stuff */
192 static apr_pool_t *pchild; /* Pool for httpd child stuff */
193
194 static pid_t ap_my_pid; /* Linux getpid() doesn't work except in main
195 thread. Use this instead */
196 static pid_t parent_pid;
197 static apr_os_thread_t *listener_os_thread;
198
199 /* Locks for accept serialization */
200 static apr_proc_mutex_t *accept_mutex;
201
202 #ifdef SINGLE_LISTEN_UNSERIALIZED_ACCEPT
203 #define SAFE_ACCEPT(stmt) (ap_listeners->next ? (stmt) : APR_SUCCESS)
204 #else
205 #define SAFE_ACCEPT(stmt) (stmt)
206 #endif
207
208 /* The LISTENER_SIGNAL signal will be sent from the main thread to the
209 * listener thread to wake it up for graceful termination (what a child
210 * process from an old generation does when the admin does "apachectl
211 * graceful"). This signal will be blocked in all threads of a child
212 * process except for the listener thread.
213 */
214 #define LISTENER_SIGNAL SIGHUP
215
216 /* The WORKER_SIGNAL signal will be sent from the main thread to the
217 * worker threads during an ungraceful restart or shutdown.
218 * This ensures that on systems (i.e., Linux) where closing the worker
219 * socket doesn't awake the worker thread when it is polling on the socket
220 * (especially in apr_wait_for_io_or_timeout() when handling
221 * Keep-Alive connections), close_worker_sockets() and join_workers()
222 * still function in timely manner and allow ungraceful shutdowns to
223 * proceed to completion. Otherwise join_workers() doesn't return
224 * before the main process decides the child process is non-responsive
225 * and sends a SIGKILL.
226 */
227 #define WORKER_SIGNAL AP_SIG_GRACEFUL
228
229 /* An array of socket descriptors in use by each thread used to
230 * perform a non-graceful (forced) shutdown of the server. */
231 static apr_socket_t **worker_sockets;
232
233 static void close_worker_sockets(void)
234 {
235 int i;
236 for (i = 0; i < ap_threads_per_child; i++) {
237 if (worker_sockets[i]) {
238 apr_socket_close(worker_sockets[i]);
239 worker_sockets[i] = NULL;
240 }
241 }
242 }
243
244 static void wakeup_listener(void)
245 {
246 listener_may_exit = 1;
247 if (!listener_os_thread) {
248 /* XXX there is an obscure path that this doesn't handle perfectly:
249 * right after listener thread is created but before
250 * listener_os_thread is set, the first worker thread hits an
251 * error and starts graceful termination
252 */
253 return;
254 }
255 /*
256 * we should just be able to "kill(ap_my_pid, LISTENER_SIGNAL)" on all
257 * platforms and wake up the listener thread since it is the only thread
258 * with SIGHUP unblocked, but that doesn't work on Linux
259 */
260 #ifdef HAVE_PTHREAD_KILL
261 pthread_kill(*listener_os_thread, LISTENER_SIGNAL);
262 #else
263 kill(ap_my_pid, LISTENER_SIGNAL);
264 #endif
265 }
266
267 #define ST_INIT 0
268 #define ST_GRACEFUL 1
269 #define ST_UNGRACEFUL 2
270
271 static int terminate_mode = ST_INIT;
272
273 static void signal_threads(int mode)
274 {
275 if (terminate_mode == mode) {
276 return;
277 }
278 terminate_mode = mode;
279 mpm_state = AP_MPMQ_STOPPING;
280
281 /* in case we weren't called from the listener thread, wake up the
282 * listener thread
283 */
284 wakeup_listener();
285
286 /* for ungraceful termination, let the workers exit now;
287 * for graceful termination, the listener thread will notify the
288 * workers to exit once it has stopped accepting new connections
289 */
290 if (mode == ST_UNGRACEFUL) {
291 workers_may_exit = 1;
292 ap_queue_interrupt_all(worker_queue);
293 ap_queue_info_term(worker_queue_info);
294 close_worker_sockets(); /* forcefully kill all current connections */
295 }
296 }
297
298 AP_DECLARE(apr_status_t) ap_mpm_query(int query_code, int *result)
299 {
300 switch(query_code){
301 case AP_MPMQ_MAX_DAEMON_USED:
302 *result = ap_max_daemons_limit;
303 return APR_SUCCESS;
304 case AP_MPMQ_IS_THREADED:
305 *result = AP_MPMQ_STATIC;
306 return APR_SUCCESS;
307 case AP_MPMQ_IS_FORKED:
308 *result = AP_MPMQ_DYNAMIC;
309 return APR_SUCCESS;
310 case AP_MPMQ_HARD_LIMIT_DAEMONS:
311 *result = server_limit;
312 return APR_SUCCESS;
313 case AP_MPMQ_HARD_LIMIT_THREADS:
314 *result = thread_limit;
315 return APR_SUCCESS;
316 case AP_MPMQ_MAX_THREADS:
317 *result = ap_threads_per_child;
318 return APR_SUCCESS;
319 case AP_MPMQ_MIN_SPARE_DAEMONS:
320 *result = 0;
321 return APR_SUCCESS;
322 case AP_MPMQ_MIN_SPARE_THREADS:
323 *result = min_spare_threads;
324 return APR_SUCCESS;
325 case AP_MPMQ_MAX_SPARE_DAEMONS:
326 *result = 0;
327 return APR_SUCCESS;
328 case AP_MPMQ_MAX_SPARE_THREADS:
329 *result = max_spare_threads;
330 return APR_SUCCESS;
331 case AP_MPMQ_MAX_REQUESTS_DAEMON:
332 *result = ap_max_requests_per_child;
333 return APR_SUCCESS;
334 case AP_MPMQ_MAX_DAEMONS:
335 *result = ap_daemons_limit;
336 return APR_SUCCESS;
337 case AP_MPMQ_MPM_STATE:
338 *result = mpm_state;
339 return APR_SUCCESS;
340 }
341 return APR_ENOTIMPL;
342 }
343
344 /* a clean exit from a child with proper cleanup */
345 static void clean_child_exit(int code) __attribute__ ((noreturn));
346 static void clean_child_exit(int code)
347 {
348 mpm_state = AP_MPMQ_STOPPING;
349 if (pchild) {
350 apr_pool_destroy(pchild);
351 }
352 exit(code);
353 }
354
355 static void just_die(int sig)
356 {
357 clean_child_exit(0);
358 }
359
360 /*****************************************************************
361 * Connection structures and accounting...
362 */
363
364 /* volatile just in case */
365 static int volatile shutdown_pending;
366 static int volatile restart_pending;
367 static int volatile is_graceful;
368 static volatile int child_fatal;
369 ap_generation_t volatile ap_my_generation;
370
371 /*
372 * ap_start_shutdown() and ap_start_restart(), below, are a first stab at
373 * functions to initiate shutdown or restart without relying on signals.
374 * Previously this was initiated in sig_term() and restart() signal handlers,
375 * but we want to be able to start a shutdown/restart from other sources --
376 * e.g. on Win32, from the service manager. Now the service manager can
377 * call ap_start_shutdown() or ap_start_restart() as appropiate. Note that
378 * these functions can also be called by the child processes, since global
379 * variables are no longer used to pass on the required action to the parent.
380 *
381 * These should only be called from the parent process itself, since the
382 * parent process will use the shutdown_pending and restart_pending variables
383 * to determine whether to shutdown or restart. The child process should
384 * call signal_parent() directly to tell the parent to die -- this will
385 * cause neither of those variable to be set, which the parent will
386 * assume means something serious is wrong (which it will be, for the
387 * child to force an exit) and so do an exit anyway.
388 */
389
390 static void ap_start_shutdown(int graceful)
391 {
392 mpm_state = AP_MPMQ_STOPPING;
393 if (shutdown_pending == 1) {
394 /* Um, is this _probably_ not an error, if the user has
395 * tried to do a shutdown twice quickly, so we won't
396 * worry about reporting it.
397 */
398 return;
399 }
400 shutdown_pending = 1;
401 is_graceful = graceful;
402 }
403
404 /* do a graceful restart if graceful == 1 */
405 static void ap_start_restart(int graceful)
406 {
407 mpm_state = AP_MPMQ_STOPPING;
408 if (restart_pending == 1) {
409 /* Probably not an error - don't bother reporting it */
410 return;
411 }
412 restart_pending = 1;
413 is_graceful = graceful;
414 }
415
416 static void sig_term(int sig)
417 {
418 ap_start_shutdown(sig == AP_SIG_GRACEFUL_STOP);
419 }
420
421 static void restart(int sig)
422 {
423 ap_start_restart(sig == AP_SIG_GRACEFUL);
424 }
425
426 static void set_signals(void)
427 {
428 #ifndef NO_USE_SIGACTION
429 struct sigaction sa;
430 #endif
431
432 if (!one_process) {
433 ap_fatal_signal_setup(ap_server_conf, pconf);
434 }
435
436 #ifndef NO_USE_SIGACTION
437 sigemptyset(&sa.sa_mask);
438 sa.sa_flags = 0;
439
440 sa.sa_handler = sig_term;
441 if (sigaction(SIGTERM, &sa, NULL) < 0)
442 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
443 "sigaction(SIGTERM)");
444 #ifdef AP_SIG_GRACEFUL_STOP
445 if (sigaction(AP_SIG_GRACEFUL_STOP, &sa, NULL) < 0)
446 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
447 "sigaction(" AP_SIG_GRACEFUL_STOP_STRING ")");
448 #endif
449 #ifdef SIGINT
450 if (sigaction(SIGINT, &sa, NULL) < 0)
451 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
452 "sigaction(SIGINT)");
453 #endif
454 #ifdef SIGXCPU
455 sa.sa_handler = SIG_DFL;
456 if (sigaction(SIGXCPU, &sa, NULL) < 0)
457 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
458 "sigaction(SIGXCPU)");
459 #endif
460 #ifdef SIGXFSZ
461 sa.sa_handler = SIG_DFL;
462 if (sigaction(SIGXFSZ, &sa, NULL) < 0)
463 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
464 "sigaction(SIGXFSZ)");
465 #endif
466 #ifdef SIGPIPE
467 sa.sa_handler = SIG_IGN;
468 if (sigaction(SIGPIPE, &sa, NULL) < 0)
469 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
470 "sigaction(SIGPIPE)");
471 #endif
472
473 /* we want to ignore HUPs and AP_SIG_GRACEFUL while we're busy
474 * processing one */
475 sigaddset(&sa.sa_mask, SIGHUP);
476 sigaddset(&sa.sa_mask, AP_SIG_GRACEFUL);
477 sa.sa_handler = restart;
478 if (sigaction(SIGHUP, &sa, NULL) < 0)
479 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
480 "sigaction(SIGHUP)");
481 if (sigaction(AP_SIG_GRACEFUL, &sa, NULL) < 0)
482 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
483 "sigaction(" AP_SIG_GRACEFUL_STRING ")");
484 #else
485 if (!one_process) {
486 #ifdef SIGXCPU
487 apr_signal(SIGXCPU, SIG_DFL);
488 #endif /* SIGXCPU */
489 #ifdef SIGXFSZ
490 apr_signal(SIGXFSZ, SIG_DFL);
491 #endif /* SIGXFSZ */
492 }
493
494 apr_signal(SIGTERM, sig_term);
495 #ifdef SIGHUP
496 apr_signal(SIGHUP, restart);
497 #endif /* SIGHUP */
498 #ifdef AP_SIG_GRACEFUL
499 apr_signal(AP_SIG_GRACEFUL, restart);
500 #endif /* AP_SIG_GRACEFUL */
501 #ifdef AP_SIG_GRACEFUL_STOP
502 apr_signal(AP_SIG_GRACEFUL_STOP, sig_term);
503 #endif /* AP_SIG_GRACEFUL_STOP */
504 #ifdef SIGPIPE
505 apr_signal(SIGPIPE, SIG_IGN);
506 #endif /* SIGPIPE */
507
508 #endif
509 }
510
511 /*****************************************************************
512 * Here follows a long bunch of generic server bookkeeping stuff...
513 */
514
515 int ap_graceful_stop_signalled(void)
516 /* XXX this is really a bad confusing obsolete name
517 * maybe it should be ap_mpm_process_exiting?
518 */
519 {
520 /* note: for a graceful termination, listener_may_exit will be set before
521 * workers_may_exit, so check listener_may_exit
522 */
523 return listener_may_exit;
524 }
525
526 /*****************************************************************
527 * Child process main loop.
528 */
529
530 static void process_socket(apr_pool_t *p, apr_socket_t *sock, int my_child_num,
531 int my_thread_num, apr_bucket_alloc_t *bucket_alloc)
532 {
533 conn_rec *current_conn;
534 long conn_id = ID_FROM_CHILD_THREAD(my_child_num, my_thread_num);
535 int csd;
536 ap_sb_handle_t *sbh;
537
538 ap_create_sb_handle(&sbh, p, my_child_num, my_thread_num);
539 apr_os_sock_get(&csd, sock);
540
541 current_conn = ap_run_create_connection(p, ap_server_conf, sock,
542 conn_id, sbh, bucket_alloc);
543 if (current_conn) {
544 ap_process_connection(current_conn, sock);
545 ap_lingering_close(current_conn);
546 }
547 }
548
549 /* requests_this_child has gone to zero or below. See if the admin coded
550 "MaxRequestsPerChild 0", and keep going in that case. Doing it this way
551 simplifies the hot path in worker_thread */
552 static void check_infinite_requests(void)
553 {
554 if (ap_max_requests_per_child) {
555 signal_threads(ST_GRACEFUL);
556 }
557 else {
558 /* wow! if you're executing this code, you may have set a record.
559 * either this child process has served over 2 billion requests, or
560 * you're running a threaded 2.0 on a 16 bit machine.
561 *
562 * I'll buy pizza and beers at Apachecon for the first person to do
563 * the former without cheating (dorking with INT_MAX, or running with
564 * uncommitted performance patches, for example).
565 *
566 * for the latter case, you probably deserve a beer too. Greg Ames
567 */
568
569 requests_this_child = INT_MAX; /* keep going */
570 }
571 }
572
573 static void unblock_signal(int sig)
574 {
575 sigset_t sig_mask;
576
577 sigemptyset(&sig_mask);
578 sigaddset(&sig_mask, sig);
579 #if defined(SIGPROCMASK_SETS_THREAD_MASK)
580 sigprocmask(SIG_UNBLOCK, &sig_mask, NULL);
581 #else
582 pthread_sigmask(SIG_UNBLOCK, &sig_mask, NULL);
583 #endif
584 }
585
586 static void dummy_signal_handler(int sig)
587 {
588 /* XXX If specifying SIG_IGN is guaranteed to unblock a syscall,
589 * then we don't need this goofy function.
590 */
591 }
592
593 static void *listener_thread(apr_thread_t *thd, void * dummy)
594 {
595 proc_info * ti = dummy;
596 int process_slot = ti->pid;
597 apr_pool_t *tpool = apr_thread_pool_get(thd);
598 void *csd = NULL;
599 apr_pool_t *ptrans = NULL; /* Pool for per-transaction stuff */
600 apr_pollset_t *pollset;
601 apr_status_t rv;
602 ap_listen_rec *lr;
603 int have_idle_worker = 0;
604 int last_poll_idx = 0;
605
606 free(ti);
607
608 /* ### check the status */
609 (void) apr_pollset_create(&pollset, num_listensocks, tpool, 0);
610
611 for (lr = ap_listeners; lr != NULL; lr = lr->next) {
612 apr_pollfd_t pfd = { 0 };
613
614 pfd.desc_type = APR_POLL_SOCKET;
615 pfd.desc.s = lr->sd;
616 pfd.reqevents = APR_POLLIN;
617 pfd.client_data = lr;
618
619 /* ### check the status */
620 (void) apr_pollset_add(pollset, &pfd);
621 }
622
623 /* Unblock the signal used to wake this thread up, and set a handler for
624 * it.
625 */
626 unblock_signal(LISTENER_SIGNAL);
627 apr_signal(LISTENER_SIGNAL, dummy_signal_handler);
628
629 /* TODO: Switch to a system where threads reuse the results from earlier
630 poll calls - manoj */
631 while (1) {
632 /* TODO: requests_this_child should be synchronized - aaron */
633 if (requests_this_child <= 0) {
634 check_infinite_requests();
635 }
636 if (listener_may_exit) break;
637
638 if (!have_idle_worker) {
639 /* the following pops a recycled ptrans pool off a stack
640 * if there is one, in addition to reserving a worker thread
641 */
642 rv = ap_queue_info_wait_for_idler(worker_queue_info,
643 &ptrans);
644 if (APR_STATUS_IS_EOF(rv)) {
645 break; /* we've been signaled to die now */
646 }
647 else if (rv != APR_SUCCESS) {
648 ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
649 "apr_queue_info_wait failed. Attempting to "
650 " shutdown process gracefully.");
651 signal_threads(ST_GRACEFUL);
652 break;
653 }
654 have_idle_worker = 1;
655 }
656
657 /* We've already decremented the idle worker count inside
658 * ap_queue_info_wait_for_idler. */
659
660 if ((rv = SAFE_ACCEPT(apr_proc_mutex_lock(accept_mutex)))
661 != APR_SUCCESS) {
662 int level = APLOG_EMERG;
663
664 if (listener_may_exit) {
665 break;
666 }
667 if (ap_scoreboard_image->parent[process_slot].generation !=
668 ap_scoreboard_image->global->running_generation) {
669 level = APLOG_DEBUG; /* common to get these at restart time */
670 }
671 ap_log_error(APLOG_MARK, level, rv, ap_server_conf,
672 "apr_proc_mutex_lock failed. Attempting to shutdown "
673 "process gracefully.");
674 signal_threads(ST_GRACEFUL);
675 break; /* skip the lock release */
676 }
677
678 if (!ap_listeners->next) {
679 /* Only one listener, so skip the poll */
680 lr = ap_listeners;
681 }
682 else {
683 while (!listener_may_exit) {
684 apr_int32_t numdesc;
685 const apr_pollfd_t *pdesc;
686
687 rv = apr_pollset_poll(pollset, -1, &numdesc, &pdesc);
688 if (rv != APR_SUCCESS) {
689 if (APR_STATUS_IS_EINTR(rv)) {
690 continue;
691 }
692
693 /* apr_pollset_poll() will only return errors in catastrophic
694 * circumstances. Let's try exiting gracefully, for now. */
695 ap_log_error(APLOG_MARK, APLOG_ERR, rv,
696 (const server_rec *) ap_server_conf,
697 "apr_pollset_poll: (listen)");
698 signal_threads(ST_GRACEFUL);
699 }
700
701 if (listener_may_exit) break;
702
703 /* We can always use pdesc[0], but sockets at position N
704 * could end up completely starved of attention in a very
705 * busy server. Therefore, we round-robin across the
706 * returned set of descriptors. While it is possible that
707 * the returned set of descriptors might flip around and
708 * continue to starve some sockets, we happen to know the
709 * internal pollset implementation retains ordering
710 * stability of the sockets. Thus, the round-robin should
711 * ensure that a socket will eventually be serviced.
712 */
713 if (last_poll_idx >= numdesc)
714 last_poll_idx = 0;
715
716 /* Grab a listener record from the client_data of the poll
717 * descriptor, and advance our saved index to round-robin
718 * the next fetch.
719 *
720 * ### hmm... this descriptor might have POLLERR rather
721 * ### than POLLIN
722 */
723 lr = pdesc[last_poll_idx++].client_data;
724 break;
725
726 } /* while */
727
728 } /* if/else */
729
730 if (!listener_may_exit) {
731 if (ptrans == NULL) {
732 /* we can't use a recycled transaction pool this time.
733 * create a new transaction pool */
734 apr_allocator_t *allocator;
735
736 apr_allocator_create(&allocator);
737 apr_allocator_max_free_set(allocator, ap_max_mem_free);
738 apr_pool_create_ex(&ptrans, pconf, NULL, allocator);
739 apr_allocator_owner_set(allocator, ptrans);
740 }
741 apr_pool_tag(ptrans, "transaction");
742 rv = lr->accept_func(&csd, lr, ptrans);
743 /* later we trash rv and rely on csd to indicate success/failure */
744 AP_DEBUG_ASSERT(rv == APR_SUCCESS || !csd);
745
746 if (rv == APR_EGENERAL) {
747 /* E[NM]FILE, ENOMEM, etc */
748 resource_shortage = 1;
749 signal_threads(ST_GRACEFUL);
750 }
751 if ((rv = SAFE_ACCEPT(apr_proc_mutex_unlock(accept_mutex)))
752 != APR_SUCCESS) {
753 int level = APLOG_EMERG;
754
755 if (listener_may_exit) {
756 break;
757 }
758 if (ap_scoreboard_image->parent[process_slot].generation !=
759 ap_scoreboard_image->global->running_generation) {
760 level = APLOG_DEBUG; /* common to get these at restart time */
761 }
762 ap_log_error(APLOG_MARK, level, rv, ap_server_conf,
763 "apr_proc_mutex_unlock failed. Attempting to "
764 "shutdown process gracefully.");
765 signal_threads(ST_GRACEFUL);
766 }
767 if (csd != NULL) {
768 rv = ap_queue_push(worker_queue, csd, ptrans);
769 if (rv) {
770 /* trash the connection; we couldn't queue the connected
771 * socket to a worker
772 */
773 apr_socket_close(csd);
774 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
775 "ap_queue_push failed");
776 }
777 else {
778 have_idle_worker = 0;
779 }
780 }
781 }
782 else {
783 if ((rv = SAFE_ACCEPT(apr_proc_mutex_unlock(accept_mutex)))
784 != APR_SUCCESS) {
785 int level = APLOG_EMERG;
786
787 if (ap_scoreboard_image->parent[process_slot].generation !=
788 ap_scoreboard_image->global->running_generation) {
789 level = APLOG_DEBUG; /* common to get these at restart time */
790 }
791 ap_log_error(APLOG_MARK, level, rv, ap_server_conf,
792 "apr_proc_mutex_unlock failed. Attempting to "
793 "shutdown process gracefully.");
794 signal_threads(ST_GRACEFUL);
795 }
796 break;
797 }
798 }
799
800 ap_close_listeners();
801 ap_queue_term(worker_queue);
802 dying = 1;
803 ap_scoreboard_image->parent[process_slot].quiescing = 1;
804
805 /* wake up the main thread */
806 kill(ap_my_pid, SIGTERM);
807
808 apr_thread_exit(thd, APR_SUCCESS);
809 return NULL;
810 }
811
812 /* XXX For ungraceful termination/restart, we definitely don't want to
813 * wait for active connections to finish but we may want to wait
814 * for idle workers to get out of the queue code and release mutexes,
815 * since those mutexes are cleaned up pretty soon and some systems
816 * may not react favorably (i.e., segfault) if operations are attempted
817 * on cleaned-up mutexes.
818 */
819 static void * APR_THREAD_FUNC worker_thread(apr_thread_t *thd, void * dummy)
820 {
821 proc_info * ti = dummy;
822 int process_slot = ti->pid;
823 int thread_slot = ti->tid;
824 apr_socket_t *csd = NULL;
825 apr_bucket_alloc_t *bucket_alloc;
826 apr_pool_t *last_ptrans = NULL;
827 apr_pool_t *ptrans; /* Pool for per-transaction stuff */
828 apr_status_t rv;
829 int is_idle = 0;
830
831 free(ti);
832
833 ap_scoreboard_image->servers[process_slot][thread_slot].pid = ap_my_pid;
834 ap_scoreboard_image->servers[process_slot][thread_slot].generation = ap_my_generation;
835 ap_update_child_status_from_indexes(process_slot, thread_slot, SERVER_STARTING, NULL);
836
837 #ifdef HAVE_PTHREAD_KILL
838 unblock_signal(WORKER_SIGNAL);
839 apr_signal(WORKER_SIGNAL, dummy_signal_handler);
840 #endif
841
842 while (!workers_may_exit) {
843 if (!is_idle) {
844 rv = ap_queue_info_set_idle(worker_queue_info, last_ptrans);
845 last_ptrans = NULL;
846 if (rv != APR_SUCCESS) {
847 ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
848 "ap_queue_info_set_idle failed. Attempting to "
849 "shutdown process gracefully.");
850 signal_threads(ST_GRACEFUL);
851 break;
852 }
853 is_idle = 1;
854 }
855
856 ap_update_child_status_from_indexes(process_slot, thread_slot, SERVER_READY, NULL);
857 worker_pop:
858 if (workers_may_exit) {
859 break;
860 }
861 rv = ap_queue_pop(worker_queue, &csd, &ptrans);
862
863 if (rv != APR_SUCCESS) {
864 /* We get APR_EOF during a graceful shutdown once all the connections
865 * accepted by this server process have been handled.
866 */
867 if (APR_STATUS_IS_EOF(rv)) {
868 break;
869 }
870 /* We get APR_EINTR whenever ap_queue_pop() has been interrupted
871 * from an explicit call to ap_queue_interrupt_all(). This allows
872 * us to unblock threads stuck in ap_queue_pop() when a shutdown
873 * is pending.
874 *
875 * If workers_may_exit is set and this is ungraceful termination/
876 * restart, we are bound to get an error on some systems (e.g.,
877 * AIX, which sanity-checks mutex operations) since the queue
878 * may have already been cleaned up. Don't log the "error" if
879 * workers_may_exit is set.
880 */
881 else if (APR_STATUS_IS_EINTR(rv)) {
882 goto worker_pop;
883 }
884 /* We got some other error. */
885 else if (!workers_may_exit) {
886 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
887 "ap_queue_pop failed");
888 }
889 continue;
890 }
891 is_idle = 0;
892 worker_sockets[thread_slot] = csd;
893 bucket_alloc = apr_bucket_alloc_create(ptrans);
894 process_socket(ptrans, csd, process_slot, thread_slot, bucket_alloc);
895 worker_sockets[thread_slot] = NULL;
896 requests_this_child--; /* FIXME: should be synchronized - aaron */
897 apr_pool_clear(ptrans);
898 last_ptrans = ptrans;
899 }
900
901 ap_update_child_status_from_indexes(process_slot, thread_slot,
902 (dying) ? SERVER_DEAD : SERVER_GRACEFUL, (request_rec *) NULL);
903
904 apr_thread_exit(thd, APR_SUCCESS);
905 return NULL;
906 }
907
908 static int check_signal(int signum)
909 {
910 switch (signum) {
911 case SIGTERM:
912 case SIGINT:
913 return 1;
914 }
915 return 0;
916 }
917
918 static void create_listener_thread(thread_starter *ts)
919 {
920 int my_child_num = ts->child_num_arg;
921 apr_threadattr_t *thread_attr = ts->threadattr;
922 proc_info *my_info;
923 apr_status_t rv;
924
925 my_info = (proc_info *)malloc(sizeof(proc_info));
926 my_info->pid = my_child_num;
927 my_info->tid = -1; /* listener thread doesn't have a thread slot */
928 my_info->sd = 0;
929 rv = apr_thread_create(&ts->listener, thread_attr, listener_thread,
930 my_info, pchild);
931 if (rv != APR_SUCCESS) {
932 ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
933 "apr_thread_create: unable to create listener thread");
934 /* let the parent decide how bad this really is */
935 clean_child_exit(APEXIT_CHILDSICK);
936 }
937 apr_os_thread_get(&listener_os_thread, ts->listener);
938 }
939
940 /* XXX under some circumstances not understood, children can get stuck
941 * in start_threads forever trying to take over slots which will
942 * never be cleaned up; for now there is an APLOG_DEBUG message issued
943 * every so often when this condition occurs
944 */
945 static void * APR_THREAD_FUNC start_threads(apr_thread_t *thd, void *dummy)
946 {
947 thread_starter *ts = dummy;
948 apr_thread_t **threads = ts->threads;
949 apr_threadattr_t *thread_attr = ts->threadattr;
950 int child_num_arg = ts->child_num_arg;
951 int my_child_num = child_num_arg;
952 proc_info *my_info;
953 apr_status_t rv;
954 int i;
955 int threads_created = 0;
956 int listener_started = 0;
957 int loops;
958 int prev_threads_created;
959
960 /* We must create the fd queues before we start up the listener
961 * and worker threads. */
962 worker_queue = apr_pcalloc(pchild, sizeof(*worker_queue));
963 rv = ap_queue_init(worker_queue, ap_threads_per_child, pchild);
964 if (rv != APR_SUCCESS) {
965 ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
966 "ap_queue_init() failed");
967 clean_child_exit(APEXIT_CHILDFATAL);
968 }
969
970 rv = ap_queue_info_create(&worker_queue_info, pchild,
971 ap_threads_per_child);
972 if (rv != APR_SUCCESS) {
973 ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
974 "ap_queue_info_create() failed");
975 clean_child_exit(APEXIT_CHILDFATAL);
976 }
977
978 worker_sockets = apr_pcalloc(pchild, ap_threads_per_child
979 * sizeof(apr_socket_t *));
980
981 loops = prev_threads_created = 0;
982 while (1) {
983 /* ap_threads_per_child does not include the listener thread */
984 for (i = 0; i < ap_threads_per_child; i++) {
985 int status = ap_scoreboard_image->servers[child_num_arg][i].status;
986
987 if (status != SERVER_GRACEFUL && status != SERVER_DEAD) {
988 continue;
989 }
990
991 my_info = (proc_info *)malloc(sizeof(proc_info));
992 if (my_info == NULL) {
993 ap_log_error(APLOG_MARK, APLOG_ALERT, errno, ap_server_conf,
994 "malloc: out of memory");
995 clean_child_exit(APEXIT_CHILDFATAL);
996 }
997 my_info->pid = my_child_num;
998 my_info->tid = i;
999 my_info->sd = 0;
1000
1001 /* We are creating threads right now */
1002 ap_update_child_status_from_indexes(my_child_num, i,
1003 SERVER_STARTING, NULL);
1004 /* We let each thread update its own scoreboard entry. This is
1005 * done because it lets us deal with tid better.
1006 */
1007 rv = apr_thread_create(&threads[i], thread_attr,
1008 worker_thread, my_info, pchild);
1009 if (rv != APR_SUCCESS) {
1010 ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
1011 "apr_thread_create: unable to create worker thread");
1012 /* let the parent decide how bad this really is */
1013 clean_child_exit(APEXIT_CHILDSICK);
1014 }
1015 threads_created++;
1016 }
1017 /* Start the listener only when there are workers available */
1018 if (!listener_started && threads_created) {
1019 create_listener_thread(ts);
1020 listener_started = 1;
1021 }
1022 if (start_thread_may_exit || threads_created == ap_threads_per_child) {
1023 break;
1024 }
1025 /* wait for previous generation to clean up an entry */
1026 apr_sleep(apr_time_from_sec(1));
1027 ++loops;
1028 if (loops % 120 == 0) { /* every couple of minutes */
1029 if (prev_threads_created == threads_created) {
1030 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
1031 "child %" APR_PID_T_FMT " isn't taking over "
1032 "slots very quickly (%d of %d)",
1033 ap_my_pid, threads_created, ap_threads_per_child);
1034 }
1035 prev_threads_created = threads_created;
1036 }
1037 }
1038
1039 /* What state should this child_main process be listed as in the
1040 * scoreboard...?
1041 * ap_update_child_status_from_indexes(my_child_num, i, SERVER_STARTING,
1042 * (request_rec *) NULL);
1043 *
1044 * This state should be listed separately in the scoreboard, in some kind
1045 * of process_status, not mixed in with the worker threads' status.
1046 * "life_status" is almost right, but it's in the worker's structure, and
1047 * the name could be clearer. gla
1048 */
1049 apr_thread_exit(thd, APR_SUCCESS);
1050 return NULL;
1051 }
1052
1053 static void join_workers(apr_thread_t *listener, apr_thread_t **threads)
1054 {
1055 int i;
1056 apr_status_t rv, thread_rv;
1057
1058 if (listener) {
1059 int iter;
1060
1061 /* deal with a rare timing window which affects waking up the
1062 * listener thread... if the signal sent to the listener thread
1063 * is delivered between the time it verifies that the
1064 * listener_may_exit flag is clear and the time it enters a
1065 * blocking syscall, the signal didn't do any good... work around
1066 * that by sleeping briefly and sending it again
1067 */
1068
1069 iter = 0;
1070 while (iter < 10 &&
1071 #ifdef HAVE_PTHREAD_KILL
1072 pthread_kill(*listener_os_thread, 0)
1073 #else
1074 kill(ap_my_pid, 0)
1075 #endif
1076 == 0) {
1077 /* listener not dead yet */
1078 apr_sleep(apr_time_make(0, 500000));
1079 wakeup_listener();
1080 ++iter;
1081 }
1082 if (iter >= 10) {
1083 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
1084 "the listener thread didn't exit");
1085 }
1086 else {
1087 rv = apr_thread_join(&thread_rv, listener);
1088 if (rv != APR_SUCCESS) {
1089 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
1090 "apr_thread_join: unable to join listener thread");
1091 }
1092 }
1093 }
1094
1095 for (i = 0; i < ap_threads_per_child; i++) {
1096 if (threads[i]) { /* if we ever created this thread */
1097 #ifdef HAVE_PTHREAD_KILL
1098 apr_os_thread_t *worker_os_thread;
1099
1100 apr_os_thread_get(&worker_os_thread, threads[i]);
1101 pthread_kill(*worker_os_thread, WORKER_SIGNAL);
1102 #endif
1103
1104 rv = apr_thread_join(&thread_rv, threads[i]);
1105 if (rv != APR_SUCCESS) {
1106 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
1107 "apr_thread_join: unable to join worker "
1108 "thread %d",
1109 i);
1110 }
1111 }
1112 }
1113 }
1114
1115 static void join_start_thread(apr_thread_t *start_thread_id)
1116 {
1117 apr_status_t rv, thread_rv;
1118
1119 start_thread_may_exit = 1; /* tell it to give up in case it is still
1120 * trying to take over slots from a
1121 * previous generation
1122 */
1123 rv = apr_thread_join(&thread_rv, start_thread_id);
1124 if (rv != APR_SUCCESS) {
1125 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
1126 "apr_thread_join: unable to join the start "
1127 "thread");
1128 }
1129 }
1130
1131 static void child_main(int child_num_arg)
1132 {
1133 apr_thread_t **threads;
1134 apr_status_t rv;
1135 thread_starter *ts;
1136 apr_threadattr_t *thread_attr;
1137 apr_thread_t *start_thread_id;
1138
1139 mpm_state = AP_MPMQ_STARTING; /* for benefit of any hooks that run as this
1140 * child initializes
1141 */
1142 ap_my_pid = getpid();
1143 ap_fatal_signal_child_setup(ap_server_conf);
1144 apr_pool_create(&pchild, pconf);
1145
1146 /*stuff to do before we switch id's, so we have permissions.*/
1147 ap_reopen_scoreboard(pchild, NULL, 0);
1148
1149 rv = SAFE_ACCEPT(apr_proc_mutex_child_init(&accept_mutex, ap_lock_fname,
1150 pchild));
1151 if (rv != APR_SUCCESS) {
1152 ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
1153 "Couldn't initialize cross-process lock in child");
1154 clean_child_exit(APEXIT_CHILDFATAL);
1155 }
1156
1157 if (unixd_setup_child()) {
1158 clean_child_exit(APEXIT_CHILDFATAL);
1159 }
1160
1161 ap_run_child_init(pchild, ap_server_conf);
1162
1163 /* done with init critical section */
1164
1165 /* Just use the standard apr_setup_signal_thread to block all signals
1166 * from being received. The child processes no longer use signals for
1167 * any communication with the parent process.
1168 */
1169 rv = apr_setup_signal_thread();
1170 if (rv != APR_SUCCESS) {
1171 ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
1172 "Couldn't initialize signal thread");
1173 clean_child_exit(APEXIT_CHILDFATAL);
1174 }
1175
1176 if (ap_max_requests_per_child) {
1177 requests_this_child = ap_max_requests_per_child;
1178 }
1179 else {
1180 /* coding a value of zero means infinity */
1181 requests_this_child = INT_MAX;
1182 }
1183
1184 /* Setup worker threads */
1185
1186 /* clear the storage; we may not create all our threads immediately,
1187 * and we want a 0 entry to indicate a thread which was not created
1188 */
1189 threads = (apr_thread_t **)calloc(1,
1190 sizeof(apr_thread_t *) * ap_threads_per_child);
1191 if (threads == NULL) {
1192 ap_log_error(APLOG_MARK, APLOG_ALERT, errno, ap_server_conf,
1193 "malloc: out of memory");
1194 clean_child_exit(APEXIT_CHILDFATAL);
1195 }
1196
1197 ts = (thread_starter *)apr_palloc(pchild, sizeof(*ts));
1198
1199 apr_threadattr_create(&thread_attr, pchild);
1200 /* 0 means PTHREAD_CREATE_JOINABLE */
1201 apr_threadattr_detach_set(thread_attr, 0);
1202
1203 if (ap_thread_stacksize != 0) {
1204 apr_threadattr_stacksize_set(thread_attr, ap_thread_stacksize);
1205 }
1206
1207 ts->threads = threads;
1208 ts->listener = NULL;
1209 ts->child_num_arg = child_num_arg;
1210 ts->threadattr = thread_attr;
1211
1212 rv = apr_thread_create(&start_thread_id, thread_attr, start_threads,
1213 ts, pchild);
1214 if (rv != APR_SUCCESS) {
1215 ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
1216 "apr_thread_create: unable to create worker thread");
1217 /* let the parent decide how bad this really is */
1218 clean_child_exit(APEXIT_CHILDSICK);
1219 }
1220
1221 mpm_state = AP_MPMQ_RUNNING;
1222
1223 /* If we are only running in one_process mode, we will want to
1224 * still handle signals. */
1225 if (one_process) {
1226 /* Block until we get a terminating signal. */
1227 apr_signal_thread(check_signal);
1228 /* make sure the start thread has finished; signal_threads()
1229 * and join_workers() depend on that
1230 */
1231 /* XXX join_start_thread() won't be awakened if one of our
1232 * threads encounters a critical error and attempts to
1233 * shutdown this child
1234 */
1235 join_start_thread(start_thread_id);
1236 signal_threads(ST_UNGRACEFUL); /* helps us terminate a little more
1237 * quickly than the dispatch of the signal thread
1238 * beats the Pipe of Death and the browsers
1239 */
1240 /* A terminating signal was received. Now join each of the
1241 * workers to clean them up.
1242 * If the worker already exited, then the join frees
1243 * their resources and returns.
1244 * If the worker hasn't exited, then this blocks until
1245 * they have (then cleans up).
1246 */
1247 join_workers(ts->listener, threads);
1248 }
1249 else { /* !one_process */
1250 /* remove SIGTERM from the set of blocked signals... if one of
1251 * the other threads in the process needs to take us down
1252 * (e.g., for MaxRequestsPerChild) it will send us SIGTERM
1253 */
1254 unblock_signal(SIGTERM);
1255 apr_signal(SIGTERM, dummy_signal_handler);
1256 /* Watch for any messages from the parent over the POD */
1257 while (1) {
1258 rv = ap_mpm_pod_check(pod);
1259 if (rv == AP_NORESTART) {
1260 /* see if termination was triggered while we slept */
1261 switch(terminate_mode) {
1262 case ST_GRACEFUL:
1263 rv = AP_GRACEFUL;
1264 break;
1265 case ST_UNGRACEFUL:
1266 rv = AP_RESTART;
1267 break;
1268 }
1269 }
1270 if (rv == AP_GRACEFUL || rv == AP_RESTART) {
1271 /* make sure the start thread has finished;
1272 * signal_threads() and join_workers depend on that
1273 */
1274 join_start_thread(start_thread_id);
1275 signal_threads(rv == AP_GRACEFUL ? ST_GRACEFUL : ST_UNGRACEFUL);
1276 break;
1277 }
1278 }
1279
1280 /* A terminating signal was received. Now join each of the
1281 * workers to clean them up.
1282 * If the worker already exited, then the join frees
1283 * their resources and returns.
1284 * If the worker hasn't exited, then this blocks until
1285 * they have (then cleans up).
1286 */
1287 join_workers(ts->listener, threads);
1288 }
1289
1290 free(threads);
1291
1292 clean_child_exit(resource_shortage ? APEXIT_CHILDSICK : 0);
1293 }
1294
1295 static int make_child(server_rec *s, int slot)
1296 {
1297 int pid;
1298
1299 if (slot + 1 > ap_max_daemons_limit) {
1300 ap_max_daemons_limit = slot + 1;
1301 }
1302
1303 if (one_process) {
1304 set_signals();
1305 ap_scoreboard_image->parent[slot].pid = getpid();
1306 child_main(slot);
1307 }
1308
1309 if ((pid = fork()) == -1) {
1310 ap_log_error(APLOG_MARK, APLOG_ERR, errno, s,
1311 "fork: Unable to fork new process");
1312
1313 /* fork didn't succeed. Fix the scoreboard or else
1314 * it will say SERVER_STARTING forever and ever
1315 */
1316 ap_update_child_status_from_indexes(slot, 0, SERVER_DEAD, NULL);
1317
1318 /* In case system resources are maxxed out, we don't want
1319 Apache running away with the CPU trying to fork over and
1320 over and over again. */
1321 apr_sleep(apr_time_from_sec(10));
1322
1323 return -1;
1324 }
1325
1326 if (!pid) {
1327 #ifdef HAVE_BINDPROCESSOR
1328 /* By default, AIX binds to a single processor. This bit unbinds
1329 * children which will then bind to another CPU.
1330 */
1331 int status = bindprocessor(BINDPROCESS, (int)getpid(),
1332 PROCESSOR_CLASS_ANY);
1333 if (status != OK)
1334 ap_log_error(APLOG_MARK, APLOG_WARNING, errno,
1335 ap_server_conf,
1336 "processor unbind failed %d", status);
1337 #endif
1338 RAISE_SIGSTOP(MAKE_CHILD);
1339
1340 apr_signal(SIGTERM, just_die);
1341 child_main(slot);
1342
1343 clean_child_exit(0);
1344 }
1345 /* else */
1346 if (ap_scoreboard_image->parent[slot].pid != 0) {
1347 /* This new child process is squatting on the scoreboard
1348 * entry owned by an exiting child process, which cannot
1349 * exit until all active requests complete.
1350 * Don't forget about this exiting child process, or we
1351 * won't be able to kill it if it doesn't exit by the
1352 * time the server is shut down.
1353 */
1354 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
1355 "taking over scoreboard slot from %" APR_PID_T_FMT "%s",
1356 ap_scoreboard_image->parent[slot].pid,
1357 ap_scoreboard_image->parent[slot].quiescing ?
1358 " (quiescing)" : "");
1359 ap_register_extra_mpm_process(ap_scoreboard_image->parent[slot].pid);
1360 }
1361 ap_scoreboard_image->parent[slot].quiescing = 0;
1362 ap_scoreboard_image->parent[slot].pid = pid;
1363 return 0;
1364 }
1365
1366 /* start up a bunch of children */
1367 static void startup_children(int number_to_start)
1368 {
1369 int i;
1370
1371 for (i = 0; number_to_start && i < ap_daemons_limit; ++i) {
1372 if (ap_scoreboard_image->parent[i].pid != 0) {
1373 continue;
1374 }
1375 if (make_child(ap_server_conf, i) < 0) {
1376 break;
1377 }
1378 --number_to_start;
1379 }
1380 }
1381
1382
1383 /*
1384 * idle_spawn_rate is the number of children that will be spawned on the
1385 * next maintenance cycle if there aren't enough idle servers. It is
1386 * doubled up to MAX_SPAWN_RATE, and reset only when a cycle goes by
1387 * without the need to spawn.
1388 */
1389 static int idle_spawn_rate = 1;
1390 #ifndef MAX_SPAWN_RATE
1391 #define MAX_SPAWN_RATE (32)
1392 #endif
1393 static int hold_off_on_exponential_spawning;
1394
1395 static void perform_idle_server_maintenance(void)
1396 {
1397 int i, j;
1398 int idle_thread_count;
1399 worker_score *ws;
1400 process_score *ps;
1401 int free_length;
1402 int totally_free_length = 0;
1403 int free_slots[MAX_SPAWN_RATE];
1404 int last_non_dead;
1405 int total_non_dead;
1406 int active_thread_count = 0;
1407
1408 /* initialize the free_list */
1409 free_length = 0;
1410
1411 idle_thread_count = 0;
1412 last_non_dead = -1;
1413 total_non_dead = 0;
1414
1415 for (i = 0; i < ap_daemons_limit; ++i) {
1416 /* Initialization to satisfy the compiler. It doesn't know
1417 * that ap_threads_per_child is always > 0 */
1418 int status = SERVER_DEAD;
1419 int any_dying_threads = 0;
1420 int any_dead_threads = 0;
1421 int all_dead_threads = 1;
1422
1423 if (i >= ap_max_daemons_limit && totally_free_length == idle_spawn_rate)
1424 break;
1425 ps = &ap_scoreboard_image->parent[i];
1426 for (j = 0; j < ap_threads_per_child; j++) {
1427 ws = &ap_scoreboard_image->servers[i][j];
1428 status = ws->status;
1429
1430 /* XXX any_dying_threads is probably no longer needed GLA */
1431 any_dying_threads = any_dying_threads ||
1432 (status == SERVER_GRACEFUL);
1433 any_dead_threads = any_dead_threads || (status == SERVER_DEAD);
1434 all_dead_threads = all_dead_threads &&
1435 (status == SERVER_DEAD ||
1436 status == SERVER_GRACEFUL);
1437
1438 /* We consider a starting server as idle because we started it
1439 * at least a cycle ago, and if it still hasn't finished starting
1440 * then we're just going to swamp things worse by forking more.
1441 * So we hopefully won't need to fork more if we count it.
1442 * This depends on the ordering of SERVER_READY and SERVER_STARTING.
1443 */
1444 if (ps->pid != 0) { /* XXX just set all_dead_threads in outer for
1445 loop if no pid? not much else matters */
1446 if (status <= SERVER_READY &&
1447 !ps->quiescing &&
1448 ps->generation == ap_my_generation) {
1449 ++idle_thread_count;
1450 }
1451 if (status >= SERVER_READY && status < SERVER_GRACEFUL) {
1452 ++active_thread_count;
1453 }
1454 }
1455 }
1456 if (any_dead_threads && totally_free_length < idle_spawn_rate
1457 && free_length < MAX_SPAWN_RATE
1458 && (!ps->pid /* no process in the slot */
1459 || ps->quiescing)) { /* or at least one is going away */
1460 if (all_dead_threads) {
1461 /* great! we prefer these, because the new process can
1462 * start more threads sooner. So prioritize this slot
1463 * by putting it ahead of any slots with active threads.
1464 *
1465 * first, make room by moving a slot that's potentially still
1466 * in use to the end of the array
1467 */
1468 free_slots[free_length] = free_slots[totally_free_length];
1469 free_slots[totally_free_length++] = i;
1470 }
1471 else {
1472 /* slot is still in use - back of the bus
1473 */
1474 free_slots[free_length] = i;
1475 }
1476 ++free_length;
1477 }
1478 /* XXX if (!ps->quiescing) is probably more reliable GLA */
1479 if (!any_dying_threads) {
1480 last_non_dead = i;
1481 ++total_non_dead;
1482 }
1483 }
1484
1485 if (sick_child_detected) {
1486 if (active_thread_count > 0) {
1487 /* some child processes appear to be working. don't kill the
1488 * whole server.
1489 */
1490 sick_child_detected = 0;
1491 }
1492 else {
1493 /* looks like a basket case. give up.
1494 */
1495 shutdown_pending = 1;
1496 child_fatal = 1;
1497 ap_log_error(APLOG_MARK, APLOG_ALERT, 0,
1498 ap_server_conf,
1499 "No active workers found..."
1500 " Apache is exiting!");
1501 /* the child already logged the failure details */
1502 return;
1503 }
1504 }
1505
1506 ap_max_daemons_limit = last_non_dead + 1;
1507
1508 if (idle_thread_count > max_spare_threads) {
1509 /* Kill off one child */
1510 ap_mpm_pod_signal(pod, TRUE);
1511 idle_spawn_rate = 1;
1512 }
1513 else if (idle_thread_count < min_spare_threads) {
1514 /* terminate the free list */
1515 if (free_length == 0) {
1516 /* only report this condition once */
1517 static int reported = 0;
1518
1519 if (!reported) {
1520 ap_log_error(APLOG_MARK, APLOG_ERR, 0,
1521 ap_server_conf,
1522 "server reached MaxClients setting, consider"
1523 " raising the MaxClients setting");
1524 reported = 1;
1525 }
1526 idle_spawn_rate = 1;
1527 }
1528 else {
1529 if (free_length > idle_spawn_rate) {
1530 free_length = idle_spawn_rate;
1531 }
1532 if (idle_spawn_rate >= 8) {
1533 ap_log_error(APLOG_MARK, APLOG_INFO, 0,
1534 ap_server_conf,
1535 "server seems busy, (you may need "
1536 "to increase StartServers, ThreadsPerChild "
1537 "or Min/MaxSpareThreads), "
1538 "spawning %d children, there are around %d idle "
1539 "threads, and %d total children", free_length,
1540 idle_thread_count, total_non_dead);
1541 }
1542 for (i = 0; i < free_length; ++i) {
1543 make_child(ap_server_conf, free_slots[i]);
1544 }
1545 /* the next time around we want to spawn twice as many if this
1546 * wasn't good enough, but not if we've just done a graceful
1547 */
1548 if (hold_off_on_exponential_spawning) {
1549 --hold_off_on_exponential_spawning;
1550 }
1551 else if (idle_spawn_rate < MAX_SPAWN_RATE) {
1552 idle_spawn_rate *= 2;
1553 }
1554 }
1555 }
1556 else {
1557 idle_spawn_rate = 1;
1558 }
1559 }
1560
1561 static void server_main_loop(int remaining_children_to_start)
1562 {
1563 int child_slot;
1564 apr_exit_why_e exitwhy;
1565 int status, processed_status;
1566 apr_proc_t pid;
1567 int i;
1568
1569 while (!restart_pending && !shutdown_pending) {
1570 ap_wait_or_timeout(&exitwhy, &status, &pid, pconf);
1571
1572 if (pid.pid != -1) {
1573 processed_status = ap_process_child_status(&pid, exitwhy, status);
1574 if (processed_status == APEXIT_CHILDFATAL) {
1575 shutdown_pending = 1;
1576 child_fatal = 1;
1577 return;
1578 }
1579 else if (processed_status == APEXIT_CHILDSICK) {
1580 /* tell perform_idle_server_maintenance to check into this
1581 * on the next timer pop
1582 */
1583 sick_child_detected = 1;
1584 }
1585 /* non-fatal death... note that it's gone in the scoreboard. */
1586 child_slot = find_child_by_pid(&pid);
1587 if (child_slot >= 0) {
1588 for (i = 0; i < ap_threads_per_child; i++)
1589 ap_update_child_status_from_indexes(child_slot, i, SERVER_DEAD,
1590 (request_rec *) NULL);
1591
1592 ap_scoreboard_image->parent[child_slot].pid = 0;
1593 ap_scoreboard_image->parent[child_slot].quiescing = 0;
1594 if (processed_status == APEXIT_CHILDSICK) {
1595 /* resource shortage, minimize the fork rate */
1596 idle_spawn_rate = 1;
1597 }
1598 else if (remaining_children_to_start
1599 && child_slot < ap_daemons_limit) {
1600 /* we're still doing a 1-for-1 replacement of dead
1601 * children with new children
1602 */
1603 make_child(ap_server_conf, child_slot);
1604 --remaining_children_to_start;
1605 }
1606 }
1607 else if (ap_unregister_extra_mpm_process(pid.pid) == 1) {
1608 /* handled */
1609 #if APR_HAS_OTHER_CHILD
1610 }
1611 else if (apr_proc_other_child_alert(&pid, APR_OC_REASON_DEATH,
1612 status) == 0) {
1613 /* handled */
1614 #endif
1615 }
1616 else if (is_graceful) {
1617 /* Great, we've probably just lost a slot in the
1618 * scoreboard. Somehow we don't know about this child.
1619 */
1620 ap_log_error(APLOG_MARK, APLOG_WARNING, 0,
1621 ap_server_conf,
1622 "long lost child came home! (pid %ld)",
1623 (long)pid.pid);
1624 }
1625 /* Don't perform idle maintenance when a child dies,
1626 * only do it when there's a timeout. Remember only a
1627 * finite number of children can die, and it's pretty
1628 * pathological for a lot to die suddenly.
1629 */
1630 continue;
1631 }
1632 else if (remaining_children_to_start) {
1633 /* we hit a 1 second timeout in which none of the previous
1634 * generation of children needed to be reaped... so assume
1635 * they're all done, and pick up the slack if any is left.
1636 */
1637 startup_children(remaining_children_to_start);
1638 remaining_children_to_start = 0;
1639 /* In any event we really shouldn't do the code below because
1640 * few of the servers we just started are in the IDLE state
1641 * yet, so we'd mistakenly create an extra server.
1642 */
1643 continue;
1644 }
1645
1646 perform_idle_server_maintenance();
1647 }
1648 }
1649
1650 int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
1651 {
1652 int remaining_children_to_start;
1653 apr_status_t rv;
1654
1655 ap_log_pid(pconf, ap_pid_fname);
1656
1657 first_server_limit = server_limit;
1658 first_thread_limit = thread_limit;
1659 if (changed_limit_at_restart) {
1660 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
1661 "WARNING: Attempt to change ServerLimit or ThreadLimit "
1662 "ignored during restart");
1663 changed_limit_at_restart = 0;
1664 }
1665
1666 /* Initialize cross-process accept lock */
1667 ap_lock_fname = apr_psprintf(_pconf, "%s.%" APR_PID_T_FMT,
1668 ap_server_root_relative(_pconf, ap_lock_fname),
1669 ap_my_pid);
1670
1671 rv = apr_proc_mutex_create(&accept_mutex, ap_lock_fname,
1672 ap_accept_lock_mech, _pconf);
1673 if (rv != APR_SUCCESS) {
1674 ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s,
1675 "Couldn't create accept lock");
1676 mpm_state = AP_MPMQ_STOPPING;
1677 return 1;
1678 }
1679
1680 #if APR_USE_SYSVSEM_SERIALIZE
1681 if (ap_accept_lock_mech == APR_LOCK_DEFAULT ||
1682 ap_accept_lock_mech == APR_LOCK_SYSVSEM) {
1683 #else
1684 if (ap_accept_lock_mech == APR_LOCK_SYSVSEM) {
1685 #endif
1686 rv = unixd_set_proc_mutex_perms(accept_mutex);
1687 if (rv != APR_SUCCESS) {
1688 ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s,
1689 "Couldn't set permissions on cross-process lock; "
1690 "check User and Group directives");
1691 mpm_state = AP_MPMQ_STOPPING;
1692 return 1;
1693 }
1694 }
1695
1696 if (!is_graceful) {
1697 if (ap_run_pre_mpm(s->process->pool, SB_SHARED) != OK) {
1698 mpm_state = AP_MPMQ_STOPPING;
1699 return 1;
1700 }
1701 /* fix the generation number in the global score; we just got a new,
1702 * cleared scoreboard
1703 */
1704 ap_scoreboard_image->global->running_generation = ap_my_generation;
1705 }
1706
1707 set_signals();
1708 /* Don't thrash... */
1709 if (max_spare_threads < min_spare_threads + ap_threads_per_child)
1710 max_spare_threads = min_spare_threads + ap_threads_per_child;
1711
1712 /* If we're doing a graceful_restart then we're going to see a lot
1713 * of children exiting immediately when we get into the main loop
1714 * below (because we just sent them AP_SIG_GRACEFUL). This happens pretty
1715 * rapidly... and for each one that exits we'll start a new one until
1716 * we reach at least daemons_min_free. But we may be permitted to
1717 * start more than that, so we'll just keep track of how many we're
1718 * supposed to start up without the 1 second penalty between each fork.
1719 */
1720 remaining_children_to_start = ap_daemons_to_start;
1721 if (remaining_children_to_start > ap_daemons_limit) {
1722 remaining_children_to_start = ap_daemons_limit;
1723 }
1724 if (!is_graceful) {
1725 startup_children(remaining_children_to_start);
1726 remaining_children_to_start = 0;
1727 }
1728 else {
1729 /* give the system some time to recover before kicking into
1730 * exponential mode */
1731 hold_off_on_exponential_spawning = 10;
1732 }
1733
1734 ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
1735 "%s configured -- resuming normal operations",
1736 ap_get_server_description());
1737 ap_log_error(APLOG_MARK, APLOG_INFO, 0, ap_server_conf,
1738 "Server built: %s", ap_get_server_built());
1739 #ifdef AP_MPM_WANT_SET_ACCEPT_LOCK_MECH
1740 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
1741 "AcceptMutex: %s (default: %s)",
1742 apr_proc_mutex_name(accept_mutex),
1743 apr_proc_mutex_defname());
1744 #endif
1745 restart_pending = shutdown_pending = 0;
1746 mpm_state = AP_MPMQ_RUNNING;
1747
1748 server_main_loop(remaining_children_to_start);
1749 mpm_state = AP_MPMQ_STOPPING;
1750
1751 if (shutdown_pending && !is_graceful) {
1752 /* Time to shut down:
1753 * Kill child processes, tell them to call child_exit, etc...
1754 */
1755 ap_mpm_pod_killpg(pod, ap_daemons_limit, FALSE);
1756 ap_reclaim_child_processes(1); /* Start with SIGTERM */
1757
1758 if (!child_fatal) {
1759 /* cleanup pid file on normal shutdown */
1760 const char *pidfile = NULL;
1761 pidfile = ap_server_root_relative (pconf, ap_pid_fname);
1762 if ( pidfile != NULL && unlink(pidfile) == 0)
1763 ap_log_error(APLOG_MARK, APLOG_INFO, 0,
1764 ap_server_conf,
1765 "removed PID file %s (pid=%" APR_PID_T_FMT ")",
1766 pidfile, getpid());
1767
1768 ap_log_error(APLOG_MARK, APLOG_NOTICE, 0,
1769 ap_server_conf, "caught SIGTERM, shutting down");
1770 }
1771 return 1;
1772 } else if (shutdown_pending) {
1773 /* Time to gracefully shut down:
1774 * Kill child processes, tell them to call child_exit, etc...
1775 */
1776 int active_children;
1777 int index;
1778 apr_time_t cutoff = 0;
1779
1780 /* Close our listeners, and then ask our children to do same */
1781 ap_close_listeners();
1782 ap_mpm_pod_killpg(pod, ap_daemons_limit, TRUE);
1783 ap_relieve_child_processes();
1784
1785 if (!child_fatal) {
1786 /* cleanup pid file on normal shutdown */
1787 const char *pidfile = NULL;
1788 pidfile = ap_server_root_relative (pconf, ap_pid_fname);
1789 if ( pidfile != NULL && unlink(pidfile) == 0)
1790 ap_log_error(APLOG_MARK, APLOG_INFO, 0,
1791 ap_server_conf,
1792 "removed PID file %s (pid=%" APR_PID_T_FMT ")",
1793 pidfile, getpid());
1794
1795 ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
1796 "caught " AP_SIG_GRACEFUL_STOP_STRING
1797 ", shutting down gracefully");
1798 }
1799
1800 if (ap_graceful_shutdown_timeout) {
1801 cutoff = apr_time_now() +
1802 apr_time_from_sec(ap_graceful_shutdown_timeout);
1803 }
1804
1805 /* Don't really exit until each child has finished */
1806 shutdown_pending = 0;
1807 do {
1808 /* Pause for a second */
1809 apr_sleep(apr_time_from_sec(1));
1810
1811 /* Relieve any children which have now exited */
1812 ap_relieve_child_processes();
1813
1814 active_children = 0;
1815 for (index = 0; index < ap_daemons_limit; ++index) {
1816 if (ap_mpm_safe_kill(MPM_CHILD_PID(index), 0) == APR_SUCCESS) {
1817 active_children = 1;
1818 /* Having just one child is enough to stay around */
1819 break;
1820 }
1821 }
1822 } while (!shutdown_pending && active_children &&
1823 (!ap_graceful_shutdown_timeout || apr_time_now() < cutoff));
1824
1825 /* We might be here because we received SIGTERM, either
1826 * way, try and make sure that all of our processes are
1827 * really dead.
1828 */
1829 ap_mpm_pod_killpg(pod, ap_daemons_limit, FALSE);
1830 ap_reclaim_child_processes(1);
1831
1832 return 1;
1833 }
1834
1835 /* we've been told to restart */
1836 apr_signal(SIGHUP, SIG_IGN);
1837
1838 if (one_process) {
1839 /* not worth thinking about */
1840 return 1;
1841 }
1842
1843 /* advance to the next generation */
1844 /* XXX: we really need to make sure this new generation number isn't in
1845 * use by any of the children.
1846 */
1847 ++ap_my_generation;
1848 ap_scoreboard_image->global->running_generation = ap_my_generation;
1849
1850 if (is_graceful) {
1851 ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
1852 AP_SIG_GRACEFUL_STRING " received. Doing graceful restart");
1853 /* wake up the children...time to die. But we'll have more soon */
1854 ap_mpm_pod_killpg(pod, ap_daemons_limit, TRUE);
1855
1856
1857 /* This is mostly for debugging... so that we know what is still
1858 * gracefully dealing with existing request.
1859 */
1860
1861 }
1862 else {
1863 /* Kill 'em all. Since the child acts the same on the parents SIGTERM
1864 * and a SIGHUP, we may as well use the same signal, because some user
1865 * pthreads are stealing signals from us left and right.
1866 */
1867 ap_mpm_pod_killpg(pod, ap_daemons_limit, FALSE);
1868
1869 ap_reclaim_child_processes(1); /* Start with SIGTERM */
1870 ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
1871 "SIGHUP received. Attempting to restart");
1872 }
1873
1874 return 0;
1875 }
1876
1877 /* This really should be a post_config hook, but the error log is already
1878 * redirected by that point, so we need to do this in the open_logs phase.
1879 */
1880 static int worker_open_logs(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
1881 {
1882 apr_status_t rv;
1883
1884 pconf = p;
1885 ap_server_conf = s;
1886
1887 if ((num_listensocks = ap_setup_listeners(ap_server_conf)) < 1) {
1888 ap_log_error(APLOG_MARK, APLOG_ALERT|APLOG_STARTUP, 0,
1889 NULL, "no listening sockets available, shutting down");
1890 return DONE;
1891 }
1892
1893 if (!one_process) {
1894 if ((rv = ap_mpm_pod_open(pconf, &pod))) {
1895 ap_log_error(APLOG_MARK, APLOG_CRIT|APLOG_STARTUP, rv, NULL,
1896 "Could not open pipe-of-death.");
1897 return DONE;
1898 }
1899 }
1900 return OK;
1901 }
1902
1903 static int worker_pre_config(apr_pool_t *pconf, apr_pool_t *plog,
1904 apr_pool_t *ptemp)
1905 {
1906 static int restart_num = 0;
1907 int no_detach, debug, foreground;
1908 ap_directive_t *pdir;
1909 ap_directive_t *max_clients = NULL;
1910 apr_status_t rv;
1911
1912 mpm_state = AP_MPMQ_STARTING;
1913
1914 /* make sure that "ThreadsPerChild" gets set before "MaxClients" */
1915 for (pdir = ap_conftree; pdir != NULL; pdir = pdir->next) {
1916 if (strncasecmp(pdir->directive, "ThreadsPerChild", 15) == 0) {
1917 if (!max_clients) {
1918 break; /* we're in the clear, got ThreadsPerChild first */
1919 }
1920 else {
1921 /* now to swap the data */
1922 ap_directive_t temp;
1923
1924 temp.directive = pdir->directive;
1925 temp.args = pdir->args;
1926 /* Make sure you don't change 'next', or you may get loops! */
1927 /* XXX: first_child, parent, and data can never be set
1928 * for these directives, right? -aaron */
1929 temp.filename = pdir->filename;
1930 temp.line_num = pdir->line_num;
1931
1932 pdir->directive = max_clients->directive;
1933 pdir->args = max_clients->args;
1934 pdir->filename = max_clients->filename;
1935 pdir->line_num = max_clients->line_num;
1936
1937 max_clients->directive = temp.directive;
1938 max_clients->args = temp.args;
1939 max_clients->filename = temp.filename;
1940 max_clients->line_num = temp.line_num;
1941 break;
1942 }
1943 }
1944 else if (!max_clients
1945 && strncasecmp(pdir->directive, "MaxClients", 10) == 0) {
1946 max_clients = pdir;
1947 }
1948 }
1949
1950 debug = ap_exists_config_define("DEBUG");
1951
1952 if (debug) {
1953 foreground = one_process = 1;
1954 no_detach = 0;
1955 }
1956 else {
1957 one_process = ap_exists_config_define("ONE_PROCESS");
1958 no_detach = ap_exists_config_define("NO_DETACH");
1959 foreground = ap_exists_config_define("FOREGROUND");
1960 }
1961
1962 /* sigh, want this only the second time around */
1963 if (restart_num++ == 1) {
1964 is_graceful = 0;
1965
1966 if (!one_process && !foreground) {
1967 rv = apr_proc_detach(no_detach ? APR_PROC_DETACH_FOREGROUND
1968 : APR_PROC_DETACH_DAEMONIZE);
1969 if (rv != APR_SUCCESS) {
1970 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL,
1971 "apr_proc_detach failed");
1972 return HTTP_INTERNAL_SERVER_ERROR;
1973 }
1974 }
1975 parent_pid = ap_my_pid = getpid();
1976 }
1977
1978 unixd_pre_config(ptemp);
1979 ap_listen_pre_config();
1980 ap_daemons_to_start = DEFAULT_START_DAEMON;
1981 min_spare_threads = DEFAULT_MIN_FREE_DAEMON * DEFAULT_THREADS_PER_CHILD;
1982 max_spare_threads = DEFAULT_MAX_FREE_DAEMON * DEFAULT_THREADS_PER_CHILD;
1983 ap_daemons_limit = server_limit;
1984 ap_threads_per_child = DEFAULT_THREADS_PER_CHILD;
1985 ap_pid_fname = DEFAULT_PIDLOG;
1986 ap_lock_fname = DEFAULT_LOCKFILE;
1987 ap_max_requests_per_child = DEFAULT_MAX_REQUESTS_PER_CHILD;
1988 ap_extended_status = 0;
1989 #ifdef AP_MPM_WANT_SET_MAX_MEM_FREE
1990 ap_max_mem_free = APR_ALLOCATOR_MAX_FREE_UNLIMITED;
1991 #endif
1992
1993 apr_cpystrn(ap_coredump_dir, ap_server_root, sizeof(ap_coredump_dir));
1994
1995 return OK;
1996 }
1997
1998 static void worker_hooks(apr_pool_t *p)
1999 {
2000 /* The worker open_logs phase must run before the core's, or stderr
2001 * will be redirected to a file, and the messages won't print to the
2002 * console.
2003 */
2004 static const char *const aszSucc[] = {"core.c", NULL};
2005 one_process = 0;
2006
2007 ap_hook_open_logs(worker_open_logs, NULL, aszSucc, APR_HOOK_MIDDLE);
2008 /* we need to set the MPM state before other pre-config hooks use MPM query
2009 * to retrieve it, so register as REALLY_FIRST
2010 */
2011 ap_hook_pre_config(worker_pre_config, NULL, NULL, APR_HOOK_REALLY_FIRST);
2012 }
2013
2014 static const char *set_daemons_to_start(cmd_parms *cmd, void *dummy,
2015 const char *arg)
2016 {
2017 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
2018 if (err != NULL) {
2019 return err;
2020 }
2021
2022 ap_daemons_to_start = atoi(arg);
2023 return NULL;
2024 }
2025
2026 static const char *set_min_spare_threads(cmd_parms *cmd, void *dummy,
2027 const char *arg)
2028 {
2029 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
2030 if (err != NULL) {
2031 return err;
2032 }
2033
2034 min_spare_threads = atoi(arg);
2035 if (min_spare_threads <= 0) {
2036 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
2037 "WARNING: detected MinSpareThreads set to non-positive.");
2038 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
2039 "Resetting to 1 to avoid almost certain Apache failure.");
2040 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
2041 "Please read the documentation.");
2042 min_spare_threads = 1;
2043 }
2044
2045 return NULL;
2046 }
2047
2048 static const char *set_max_spare_threads(cmd_parms *cmd, void *dummy,
2049 const char *arg)
2050 {
2051 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
2052 if (err != NULL) {
2053 return err;
2054 }
2055
2056 max_spare_threads = atoi(arg);
2057 return NULL;
2058 }
2059
2060 static const char *set_max_clients (cmd_parms *cmd, void *dummy,
2061 const char *arg)
2062 {
2063 int max_clients;
2064 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
2065 if (err != NULL) {
2066 return err;
2067 }
2068
2069 /* It is ok to use ap_threads_per_child here because we are
2070 * sure that it gets set before MaxClients in the pre_config stage. */
2071 max_clients = atoi(arg);
2072 if (max_clients < ap_threads_per_child) {
2073 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
2074 "WARNING: MaxClients (%d) must be at least as large",
2075 max_clients);
2076 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
2077 " as ThreadsPerChild (%d). Automatically",
2078 ap_threads_per_child);
2079 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
2080 " increasing MaxClients to %d.",
2081 ap_threads_per_child);
2082 max_clients = ap_threads_per_child;
2083 }
2084 ap_daemons_limit = max_clients / ap_threads_per_child;
2085 if ((max_clients > 0) && (max_clients % ap_threads_per_child)) {
2086 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
2087 "WARNING: MaxClients (%d) is not an integer multiple",
2088 max_clients);
2089 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
2090 " of ThreadsPerChild (%d), lowering MaxClients to %d",
2091 ap_threads_per_child,
2092 ap_daemons_limit * ap_threads_per_child);
2093 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
2094 " for a maximum of %d child processes,",
2095 ap_daemons_limit);
2096 max_clients = ap_daemons_limit * ap_threads_per_child;
2097 }
2098 if (ap_daemons_limit > server_limit) {
2099 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
2100 "WARNING: MaxClients of %d would require %d servers,",
2101 max_clients, ap_daemons_limit);
2102 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
2103 " and would exceed the ServerLimit value of %d.",
2104 server_limit);
2105 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
2106 " Automatically lowering MaxClients to %d. To increase,",
2107 server_limit * ap_threads_per_child);
2108 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
2109 " please see the ServerLimit directive.");
2110 ap_daemons_limit = server_limit;
2111 }
2112 else if (ap_daemons_limit < 1) {
2113 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
2114 "WARNING: Require MaxClients > 0, setting to 1");
2115 ap_daemons_limit = 1;
2116 }
2117 return NULL;
2118 }
2119
2120 static const char *set_threads_per_child (cmd_parms *cmd, void *dummy,
2121 const char *arg)
2122 {
2123 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
2124 if (err != NULL) {
2125 return err;
2126 }
2127
2128 ap_threads_per_child = atoi(arg);
2129 if (ap_threads_per_child > thread_limit) {
2130 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
2131 "WARNING: ThreadsPerChild of %d exceeds ThreadLimit "
2132 "value of %d", ap_threads_per_child,
2133 thread_limit);
2134 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
2135 "threads, lowering ThreadsPerChild to %d. To increase, please"
2136 " see the", thread_limit);
2137 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
2138 " ThreadLimit directive.");
2139 ap_threads_per_child = thread_limit;
2140 }
2141 else if (ap_threads_per_child < 1) {
2142 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
2143 "WARNING: Require ThreadsPerChild > 0, setting to 1");
2144 ap_threads_per_child = 1;
2145 }
2146 return NULL;
2147 }
2148
2149 static const char *set_server_limit (cmd_parms *cmd, void *dummy, const char *arg)
2150 {
2151 int tmp_server_limit;
2152
2153 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
2154 if (err != NULL) {
2155 return err;
2156 }
2157
2158 tmp_server_limit = atoi(arg);
2159 /* you cannot change ServerLimit across a restart; ignore
2160 * any such attempts
2161 */
2162 if (first_server_limit &&
2163 tmp_server_limit != server_limit) {
2164 /* how do we log a message? the error log is a bit bucket at this
2165 * point; we'll just have to set a flag so that ap_mpm_run()
2166 * logs a warning later
2167 */
2168 changed_limit_at_restart = 1;
2169 return NULL;
2170 }
2171 server_limit = tmp_server_limit;
2172
2173 if (server_limit > MAX_SERVER_LIMIT) {
2174 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
2175 "WARNING: ServerLimit of %d exceeds compile time limit "
2176 "of %d servers,", server_limit, MAX_SERVER_LIMIT);
2177 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
2178 " lowering ServerLimit to %d.", MAX_SERVER_LIMIT);
2179 server_limit = MAX_SERVER_LIMIT;
2180 }
2181 else if (server_limit < 1) {
2182 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
2183 "WARNING: Require ServerLimit > 0, setting to 1");
2184 server_limit = 1;
2185 }
2186 return NULL;
2187 }
2188
2189 static const char *set_thread_limit (cmd_parms *cmd, void *dummy, const char *arg)
2190 {
2191 int tmp_thread_limit;
2192
2193 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
2194 if (err != NULL) {
2195 return err;
2196 }
2197
2198 tmp_thread_limit = atoi(arg);
2199 /* you cannot change ThreadLimit across a restart; ignore
2200 * any such attempts
2201 */
2202 if (first_thread_limit &&
2203 tmp_thread_limit != thread_limit) {
2204 /* how do we log a message? the error log is a bit bucket at this
2205 * point; we'll just have to set a flag so that ap_mpm_run()
2206 * logs a warning later
2207 */
2208 changed_limit_at_restart = 1;
2209 return NULL;
2210 }
2211 thread_limit = tmp_thread_limit;
2212
2213 if (thread_limit > MAX_THREAD_LIMIT) {
2214 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
2215 "WARNING: ThreadLimit of %d exceeds compile time limit "
2216 "of %d servers,", thread_limit, MAX_THREAD_LIMIT);
2217 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
2218 " lowering ThreadLimit to %d.", MAX_THREAD_LIMIT);
2219 thread_limit = MAX_THREAD_LIMIT;
2220 }
2221 else if (thread_limit < 1) {
2222 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
2223 "WARNING: Require ThreadLimit > 0, setting to 1");
2224 thread_limit = 1;
2225 }
2226 return NULL;
2227 }
2228
2229 static const command_rec worker_cmds[] = {
2230 UNIX_DAEMON_COMMANDS,
2231 LISTEN_COMMANDS,
2232 AP_INIT_TAKE1("StartServers", set_daemons_to_start, NULL, RSRC_CONF,
2233 "Number of child processes launched at server startup"),
2234 AP_INIT_TAKE1("MinSpareThreads", set_min_spare_threads, NULL, RSRC_CONF,
2235 "Minimum number of idle threads, to handle request spikes"),
2236 AP_INIT_TAKE1("MaxSpareThreads", set_max_spare_threads, NULL, RSRC_CONF,
2237 "Maximum number of idle threads"),
2238 AP_INIT_TAKE1("MaxClients", set_max_clients, NULL, RSRC_CONF,
2239 "Maximum number of threads alive at the same time"),
2240 AP_INIT_TAKE1("ThreadsPerChild", set_threads_per_child, NULL, RSRC_CONF,
2241 "Number of threads each child creates"),
2242 AP_INIT_TAKE1("ServerLimit", set_server_limit, NULL, RSRC_CONF,
2243 "Maximum number of child processes for this run of Apache"),
2244 AP_INIT_TAKE1("ThreadLimit", set_thread_limit, NULL, RSRC_CONF,
2245 "Maximum number of worker threads per child process for this run of Apache - Upper limit for ThreadsPerChild"),
2246 AP_GRACEFUL_SHUTDOWN_TIMEOUT_COMMAND,
2247 { NULL }
2248 };
2249
2250 module AP_MODULE_DECLARE_DATA mpm_worker_module = {
2251 MPM20_MODULE_STUFF,
2252 ap_mpm_rewrite_args, /* hook to run before apache parses args */
2253 NULL, /* create per-directory config structure */
2254 NULL, /* merge per-directory config structures */
2255 NULL, /* create per-server config structure */
2256 NULL, /* merge per-server config structures */
2257 worker_cmds, /* command apr_table_t */
2258 worker_hooks /* register_hooks */
2259 };
2260

Properties

Name Value
svn:eol-style native

apache@apache.org
ViewVC Help
Powered by ViewVC 1.1.2