/[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 290179 - (show annotations)
Mon Sep 19 14:57:07 2005 UTC (4 years, 2 months ago) by colm
File MIME type: text/plain
File size: 77968 byte(s)
Backport r239710, r239711, r239732, r239740 and r241815 to the 2.2.x branch;
Fix PR 28167, which means we stop listening on ports when we do a
graceful-restart.

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

Properties

Name Value
svn:eol-style native

apache@apache.org
ViewVC Help
Powered by ViewVC 1.1.2