/[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 - (hide 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 fielding 421103 /* 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 rbb 89781 *
8 nd 102525 * http://www.apache.org/licenses/LICENSE-2.0
9 rbb 89781 *
10 nd 102525 * 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 rbb 89781 */
16    
17 rbb 89938 /* 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 rbb 89781 #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 aaron 91518 #include "apr_thread_mutex.h"
31 aaron 91582 #include "apr_proc_mutex.h"
32 rbb 96005 #include "apr_poll.h"
33 rbb 89781 #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 jim 332309 #include <sys/wait.h>
44 rbb 89781 #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 jim 332309 #define CORE_PRIVATE
54    
55 rbb 89781 #include "ap_config.h"
56 jim 332309 #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 rbb 89781 #include "http_connection.h"
62     #include "ap_mpm.h"
63 rbb 93358 #include "pod.h"
64 rbb 89781 #include "mpm_common.h"
65     #include "ap_listen.h"
66 jim 332309 #include "scoreboard.h"
67 rbb 89781 #include "fdqueue.h"
68 trawick 92512 #include "mpm_default.h"
69 rbb 89781
70     #include <signal.h>
71     #include <limits.h> /* for INT_MAX */
72    
73 trawick 92512 /* 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 trawick 92530 #ifndef DEFAULT_SERVER_LIMIT
85     #define DEFAULT_SERVER_LIMIT 16
86 trawick 92512 #endif
87    
88 trawick 92530 /* 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 trawick 92512 /* Limit on the threads per process. Clients will be locked out if more than
96 trawick 92530 * this * server_limit are needed.
97 trawick 92512 *
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 trawick 92530 #ifndef DEFAULT_THREAD_LIMIT
103 jim 332309 #define DEFAULT_THREAD_LIMIT 64
104 trawick 92512 #endif
105    
106 trawick 92530 /* 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 rbb 89781 /*
114     * Actual definitions of config globals
115     */
116    
117 jerenkrantz 92473 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 trawick 93528 static int ap_daemons_limit = 0;
122 trawick 92530 static int server_limit = DEFAULT_SERVER_LIMIT;
123 colm 293164 static int first_server_limit = 0;
124 trawick 92530 static int thread_limit = DEFAULT_THREAD_LIMIT;
125 colm 293164 static int first_thread_limit = 0;
126 trawick 92530 static int changed_limit_at_restart;
127 rbb 89781 static int dying = 0;
128     static int workers_may_exit = 0;
129 trawick 94095 static int start_thread_may_exit = 0;
130     static int listener_may_exit = 0;
131 rbb 89781 static int requests_this_child;
132     static int num_listensocks = 0;
133 gregames 93366 static int resource_shortage = 0;
134 rbb 90635 static fd_queue_t *worker_queue;
135 aaron 94824 static fd_queue_info_t *worker_queue_info;
136 trawick 102045 static int mpm_state = AP_MPMQ_STARTING;
137 gregames 168182 static int sick_child_detected;
138 rbb 89781
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 jim 332309 /* Structure used to pass information to the thread responsible for
147 rbb 89781 * creating the rest of the threads.
148     */
149     typedef struct {
150     apr_thread_t **threads;
151 trawick 94031 apr_thread_t *listener;
152 rbb 89781 int child_num_arg;
153     apr_threadattr_t *threadattr;
154     } thread_starter;
155    
156 trawick 92530 #define ID_FROM_CHILD_THREAD(c, t) ((c * thread_limit) + t)
157 trawick 92512
158 rbb 89781 /*
159     * The max child slot ever assigned, preserved across restarts. Necessary
160 jim 332309 * 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 jerenkrantz 91076 * scoreboard.
163 rbb 89781 */
164     int ap_max_daemons_limit = -1;
165    
166 brianp 93096 static ap_pod_t *pod;
167 rbb 89781
168     /* *Non*-shared http_main globals... */
169    
170     server_rec *ap_server_conf;
171    
172 jwoolley 90790 /* 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 rbb 89781 * 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 jerenkrantz 92473 static apr_pool_t *pconf; /* Pool for config stuff */
192     static apr_pool_t *pchild; /* Pool for httpd child stuff */
193 rbb 89781
194 jim 332309 static pid_t ap_my_pid; /* Linux getpid() doesn't work except in main
195 rbb 89781 thread. Use this instead */
196 gregames 90064 static pid_t parent_pid;
197 trawick 94031 static apr_os_thread_t *listener_os_thread;
198 rbb 89781
199     /* Locks for accept serialization */
200 aaron 91580 static apr_proc_mutex_t *accept_mutex;
201 rbb 89781
202 brianp 93096 #ifdef SINGLE_LISTEN_UNSERIALIZED_ACCEPT
203     #define SAFE_ACCEPT(stmt) (ap_listeners->next ? (stmt) : APR_SUCCESS)
204 rbb 89781 #else
205     #define SAFE_ACCEPT(stmt) (stmt)
206     #endif
207    
208 jim 332309 /* 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 trawick 94031 * 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 trawick 424876 /* 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 jerenkrantz 94886 /* 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 jim 332309
244 trawick 94031 static void wakeup_listener(void)
245     {
246 trawick 94095 listener_may_exit = 1;
247 trawick 94420 if (!listener_os_thread) {
248     /* XXX there is an obscure path that this doesn't handle perfectly:
249 jim 332309 * right after listener thread is created but before
250 trawick 94420 * listener_os_thread is set, the first worker thread hits an
251     * error and starts graceful termination
252     */
253     return;
254     }
255 trawick 94031 /*
256 trawick 94417 * we should just be able to "kill(ap_my_pid, LISTENER_SIGNAL)" on all
257 jim 332309 * platforms and wake up the listener thread since it is the only thread
258 trawick 94417 * with SIGHUP unblocked, but that doesn't work on Linux
259 trawick 94031 */
260 trawick 94417 #ifdef HAVE_PTHREAD_KILL
261 trawick 94031 pthread_kill(*listener_os_thread, LISTENER_SIGNAL);
262 trawick 94417 #else
263     kill(ap_my_pid, LISTENER_SIGNAL);
264     #endif
265 trawick 94031 }
266    
267 trawick 94232 #define ST_INIT 0
268 trawick 94095 #define ST_GRACEFUL 1
269     #define ST_UNGRACEFUL 2
270    
271 trawick 94232 static int terminate_mode = ST_INIT;
272    
273 trawick 94095 static void signal_threads(int mode)
274 rbb 89827 {
275 trawick 94232 if (terminate_mode == mode) {
276 trawick 94106 return;
277     }
278 trawick 94232 terminate_mode = mode;
279 trawick 102045 mpm_state = AP_MPMQ_STOPPING;
280 trawick 94106
281 trawick 94031 /* in case we weren't called from the listener thread, wake up the
282     * listener thread
283     */
284     wakeup_listener();
285    
286 trawick 94106 /* 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 aaron 94824 ap_queue_info_term(worker_queue_info);
294 jerenkrantz 94886 close_worker_sockets(); /* forcefully kill all current connections */
295 trawick 94106 }
296 rbb 89827 }
297    
298 rbb 89781 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 trawick 92530 *result = server_limit;
312 rbb 89781 return APR_SUCCESS;
313     case AP_MPMQ_HARD_LIMIT_THREADS:
314 trawick 92530 *result = thread_limit;
315 rbb 89781 return APR_SUCCESS;
316     case AP_MPMQ_MAX_THREADS:
317     *result = ap_threads_per_child;
318     return APR_SUCCESS;
319 jwoolley 91777 case AP_MPMQ_MIN_SPARE_DAEMONS:
320 rbb 89781 *result = 0;
321     return APR_SUCCESS;
322 jim 332309 case AP_MPMQ_MIN_SPARE_THREADS:
323 rbb 89781 *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 jwoolley 91777 case AP_MPMQ_MAX_REQUESTS_DAEMON:
332 rbb 89781 *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 trawick 102045 case AP_MPMQ_MPM_STATE:
338     *result = mpm_state;
339     return APR_SUCCESS;
340 rbb 89781 }
341     return APR_ENOTIMPL;
342     }
343    
344 jim 332309 /* a clean exit from a child with proper cleanup */
345 rbb 89781 static void clean_child_exit(int code) __attribute__ ((noreturn));
346     static void clean_child_exit(int code)
347     {
348 trawick 102045 mpm_state = AP_MPMQ_STOPPING;
349 rbb 89781 if (pchild) {
350 jerenkrantz 92473 apr_pool_destroy(pchild);
351 rbb 89781 }
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 trawick 92019 static volatile int child_fatal;
369 rbb 89781 ap_generation_t volatile ap_my_generation;
370    
371     /*
372     * ap_start_shutdown() and ap_start_restart(), below, are a first stab at
373 jim 332309 * functions to initiate shutdown or restart without relying on signals.
374     * Previously this was initiated in sig_term() and restart() signal handlers,
375 rbb 89781 * 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 colm 290189 static void ap_start_shutdown(int graceful)
391 rbb 89781 {
392 trawick 102045 mpm_state = AP_MPMQ_STOPPING;
393 rbb 89781 if (shutdown_pending == 1) {
394 jerenkrantz 92473 /* 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 rbb 89781 }
400     shutdown_pending = 1;
401 colm 290189 is_graceful = graceful;
402 rbb 89781 }
403    
404     /* do a graceful restart if graceful == 1 */
405     static void ap_start_restart(int graceful)
406     {
407 trawick 102045 mpm_state = AP_MPMQ_STOPPING;
408 rbb 89781 if (restart_pending == 1) {
409 jerenkrantz 92473 /* Probably not an error - don't bother reporting it */
410     return;
411 rbb 89781 }
412     restart_pending = 1;
413     is_graceful = graceful;
414     }
415    
416     static void sig_term(int sig)
417     {
418 colm 290189 ap_start_shutdown(sig == AP_SIG_GRACEFUL_STOP);
419 rbb 89781 }
420    
421     static void restart(int sig)
422     {
423 jerenkrantz 91076 ap_start_restart(sig == AP_SIG_GRACEFUL);
424 rbb 89781 }
425    
426     static void set_signals(void)
427     {
428     #ifndef NO_USE_SIGACTION
429     struct sigaction sa;
430 trawick 99312 #endif
431 rbb 89781
432 trawick 99312 if (!one_process) {
433     ap_fatal_signal_setup(ap_server_conf, pconf);
434     }
435    
436     #ifndef NO_USE_SIGACTION
437 rbb 89781 sigemptyset(&sa.sa_mask);
438     sa.sa_flags = 0;
439    
440     sa.sa_handler = sig_term;
441     if (sigaction(SIGTERM, &sa, NULL) < 0)
442 jim 332309 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
443 jerenkrantz 92473 "sigaction(SIGTERM)");
444 colm 290189 #ifdef AP_SIG_GRACEFUL_STOP
445     if (sigaction(AP_SIG_GRACEFUL_STOP, &sa, NULL) < 0)
446 jim 332309 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
447 colm 290189 "sigaction(" AP_SIG_GRACEFUL_STOP_STRING ")");
448     #endif
449 rbb 89781 #ifdef SIGINT
450     if (sigaction(SIGINT, &sa, NULL) < 0)
451 jim 332309 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
452 jerenkrantz 92473 "sigaction(SIGINT)");
453 rbb 89781 #endif
454     #ifdef SIGXCPU
455     sa.sa_handler = SIG_DFL;
456     if (sigaction(SIGXCPU, &sa, NULL) < 0)
457 jim 332309 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
458 jerenkrantz 92473 "sigaction(SIGXCPU)");
459 rbb 89781 #endif
460     #ifdef SIGXFSZ
461     sa.sa_handler = SIG_DFL;
462     if (sigaction(SIGXFSZ, &sa, NULL) < 0)
463 jim 332309 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
464 jerenkrantz 92473 "sigaction(SIGXFSZ)");
465 rbb 89781 #endif
466     #ifdef SIGPIPE
467     sa.sa_handler = SIG_IGN;
468     if (sigaction(SIGPIPE, &sa, NULL) < 0)
469 jim 332309 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
470 jerenkrantz 92473 "sigaction(SIGPIPE)");
471 rbb 89781 #endif
472    
473 jim 332309 /* we want to ignore HUPs and AP_SIG_GRACEFUL while we're busy
474 jerenkrantz 91076 * processing one */
475 rbb 89781 sigaddset(&sa.sa_mask, SIGHUP);
476 jerenkrantz 91076 sigaddset(&sa.sa_mask, AP_SIG_GRACEFUL);
477 rbb 89781 sa.sa_handler = restart;
478     if (sigaction(SIGHUP, &sa, NULL) < 0)
479 jim 332309 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
480 jerenkrantz 92473 "sigaction(SIGHUP)");
481 jerenkrantz 91076 if (sigaction(AP_SIG_GRACEFUL, &sa, NULL) < 0)
482 jim 332309 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
483 jerenkrantz 92473 "sigaction(" AP_SIG_GRACEFUL_STRING ")");
484 rbb 89781 #else
485     if (!one_process) {
486     #ifdef SIGXCPU
487 jerenkrantz 92473 apr_signal(SIGXCPU, SIG_DFL);
488 rbb 89781 #endif /* SIGXCPU */
489     #ifdef SIGXFSZ
490 jerenkrantz 92473 apr_signal(SIGXFSZ, SIG_DFL);
491 rbb 89781 #endif /* SIGXFSZ */
492     }
493    
494     apr_signal(SIGTERM, sig_term);
495     #ifdef SIGHUP
496     apr_signal(SIGHUP, restart);
497     #endif /* SIGHUP */
498 jerenkrantz 91076 #ifdef AP_SIG_GRACEFUL
499     apr_signal(AP_SIG_GRACEFUL, restart);
500     #endif /* AP_SIG_GRACEFUL */
501 colm 290189 #ifdef AP_SIG_GRACEFUL_STOP
502     apr_signal(AP_SIG_GRACEFUL_STOP, sig_term);
503     #endif /* AP_SIG_GRACEFUL_STOP */
504 rbb 89781 #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 gregames 89881 /* XXX this is really a bad confusing obsolete name
517     * maybe it should be ap_mpm_process_exiting?
518     */
519 rbb 89781 {
520 trawick 94095 /* 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 rbb 89781 }
525    
526     /*****************************************************************
527     * Child process main loop.
528     */
529    
530 jerenkrantz 92473 static void process_socket(apr_pool_t *p, apr_socket_t *sock, int my_child_num,
531 jwoolley 94304 int my_thread_num, apr_bucket_alloc_t *bucket_alloc)
532 rbb 89781 {
533     conn_rec *current_conn;
534 trawick 92512 long conn_id = ID_FROM_CHILD_THREAD(my_child_num, my_thread_num);
535 rbb 89781 int csd;
536 wrowe 92791 ap_sb_handle_t *sbh;
537 rbb 89781
538 trawick 92512 ap_create_sb_handle(&sbh, p, my_child_num, my_thread_num);
539 jwoolley 91082 apr_os_sock_get(&csd, sock);
540 rbb 89781
541 jwoolley 94304 current_conn = ap_run_create_connection(p, ap_server_conf, sock,
542     conn_id, sbh, bucket_alloc);
543 rbb 89781 if (current_conn) {
544 stoddard 93087 ap_process_connection(current_conn, sock);
545 rbb 91968 ap_lingering_close(current_conn);
546 rbb 89781 }
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 trawick 94095 signal_threads(ST_GRACEFUL);
556 rbb 89781 }
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 jim 332309 * you're running a threaded 2.0 on a 16 bit machine.
561 rbb 89781 *
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 jim 332309 * uncommitted performance patches, for example).
565 rbb 89781 *
566     * for the latter case, you probably deserve a beer too. Greg Ames
567     */
568 jim 332309
569     requests_this_child = INT_MAX; /* keep going */
570 rbb 89781 }
571     }
572    
573 trawick 94232 static void unblock_signal(int sig)
574 trawick 94031 {
575 trawick 94232 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 trawick 94031 /* XXX If specifying SIG_IGN is guaranteed to unblock a syscall,
589     * then we don't need this goofy function.
590     */
591     }
592    
593 rbb 89781 static void *listener_thread(apr_thread_t *thd, void * dummy)
594     {
595     proc_info * ti = dummy;
596     int process_slot = ti->pid;
597 rbb 90635 apr_pool_t *tpool = apr_thread_pool_get(thd);
598 rbb 91955 void *csd = NULL;
599 trawick 307222 apr_pool_t *ptrans = NULL; /* Pool for per-transaction stuff */
600 gstein 101801 apr_pollset_t *pollset;
601 rbb 89781 apr_status_t rv;
602 gstein 101801 ap_listen_rec *lr;
603 brianp 95270 int have_idle_worker = 0;
604 gstein 101801 int last_poll_idx = 0;
605 rbb 89781
606     free(ti);
607    
608 gstein 101801 /* ### check the status */
609     (void) apr_pollset_create(&pollset, num_listensocks, tpool, 0);
610 rbb 89781
611 gstein 101801 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 trawick 94031 /* Unblock the signal used to wake this thread up, and set a handler for
624     * it.
625     */
626 trawick 94232 unblock_signal(LISTENER_SIGNAL);
627     apr_signal(LISTENER_SIGNAL, dummy_signal_handler);
628 trawick 94031
629 rbb 89781 /* TODO: Switch to a system where threads reuse the results from earlier
630     poll calls - manoj */
631     while (1) {
632 rbb 90635 /* TODO: requests_this_child should be synchronized - aaron */
633 rbb 89781 if (requests_this_child <= 0) {
634     check_infinite_requests();
635     }
636 trawick 94095 if (listener_may_exit) break;
637 rbb 89781
638 brianp 95270 if (!have_idle_worker) {
639 trawick 307222 /* the following pops a recycled ptrans pool off a stack
640     * if there is one, in addition to reserving a worker thread
641     */
642 brianp 95270 rv = ap_queue_info_wait_for_idler(worker_queue_info,
643 trawick 307222 &ptrans);
644 brianp 95270 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 aaron 94824 }
656 jim 332309
657 aaron 94824 /* We've already decremented the idle worker count inside
658     * ap_queue_info_wait_for_idler. */
659    
660 aaron 91580 if ((rv = SAFE_ACCEPT(apr_proc_mutex_lock(accept_mutex)))
661 rbb 89781 != APR_SUCCESS) {
662 trawick 93720 int level = APLOG_EMERG;
663    
664 trawick 94095 if (listener_may_exit) {
665 trawick 94031 break;
666     }
667 jim 332309 if (ap_scoreboard_image->parent[process_slot].generation !=
668 trawick 93720 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 aaron 91582 "apr_proc_mutex_lock failed. Attempting to shutdown "
673 rbb 89781 "process gracefully.");
674 trawick 94095 signal_threads(ST_GRACEFUL);
675 trawick 93718 break; /* skip the lock release */
676 rbb 89781 }
677    
678 brianp 93096 if (!ap_listeners->next) {
679     /* Only one listener, so skip the poll */
680     lr = ap_listeners;
681     }
682     else {
683 trawick 94095 while (!listener_may_exit) {
684 gstein 101801 apr_int32_t numdesc;
685     const apr_pollfd_t *pdesc;
686 rbb 89781
687 gstein 101801 rv = apr_pollset_poll(pollset, -1, &numdesc, &pdesc);
688     if (rv != APR_SUCCESS) {
689     if (APR_STATUS_IS_EINTR(rv)) {
690 brianp 93096 continue;
691     }
692    
693 trawick 102045 /* apr_pollset_poll() will only return errors in catastrophic
694 brianp 93096 * circumstances. Let's try exiting gracefully, for now. */
695 gstein 101801 ap_log_error(APLOG_MARK, APLOG_ERR, rv,
696     (const server_rec *) ap_server_conf,
697     "apr_pollset_poll: (listen)");
698 trawick 94095 signal_threads(ST_GRACEFUL);
699 rbb 89781 }
700    
701 trawick 94095 if (listener_may_exit) break;
702 rbb 89781
703 gstein 101801 /* 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 trawick 94095 if (!listener_may_exit) {
731 trawick 307222 if (ptrans == NULL) {
732     /* we can't use a recycled transaction pool this time.
733     * create a new transaction pool */
734 striker 93943 apr_allocator_t *allocator;
735    
736     apr_allocator_create(&allocator);
737 striker 95954 apr_allocator_max_free_set(allocator, ap_max_mem_free);
738 jorton 170896 apr_pool_create_ex(&ptrans, pconf, NULL, allocator);
739 striker 95373 apr_allocator_owner_set(allocator, ptrans);
740 brianp 93386 }
741 brianp 92482 apr_pool_tag(ptrans, "transaction");
742 rbb 91960 rv = lr->accept_func(&csd, lr, ptrans);
743 trawick 94625 /* later we trash rv and rely on csd to indicate success/failure */
744     AP_DEBUG_ASSERT(rv == APR_SUCCESS || !csd);
745 rbb 91955
746     if (rv == APR_EGENERAL) {
747 gregames 93366 /* E[NM]FILE, ENOMEM, etc */
748     resource_shortage = 1;
749 trawick 94095 signal_threads(ST_GRACEFUL);
750 rbb 89781 }
751 aaron 91580 if ((rv = SAFE_ACCEPT(apr_proc_mutex_unlock(accept_mutex)))
752 rbb 89781 != APR_SUCCESS) {
753 trawick 93720 int level = APLOG_EMERG;
754    
755 trawick 94095 if (listener_may_exit) {
756 trawick 94031 break;
757     }
758 jim 332309 if (ap_scoreboard_image->parent[process_slot].generation !=
759 trawick 93720 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 trawick 93719 "apr_proc_mutex_unlock failed. Attempting to "
764 aaron 91582 "shutdown process gracefully.");
765 trawick 94095 signal_threads(ST_GRACEFUL);
766 rbb 89781 }
767     if (csd != NULL) {
768 brianp 94830 rv = ap_queue_push(worker_queue, csd, ptrans);
769 trawick 91089 if (rv) {
770     /* trash the connection; we couldn't queue the connected
771 jim 332309 * socket to a worker
772 trawick 91089 */
773     apr_socket_close(csd);
774 trawick 93530 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
775     "ap_queue_push failed");
776 trawick 91089 }
777 brianp 95270 else {
778     have_idle_worker = 0;
779     }
780 rbb 89781 }
781     }
782     else {
783 aaron 91580 if ((rv = SAFE_ACCEPT(apr_proc_mutex_unlock(accept_mutex)))
784 rbb 89781 != APR_SUCCESS) {
785 trawick 179317 int level = APLOG_EMERG;
786    
787 jim 332309 if (ap_scoreboard_image->parent[process_slot].generation !=
788 trawick 179317 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 aaron 91582 "apr_proc_mutex_unlock failed. Attempting to "
793     "shutdown process gracefully.");
794 trawick 94095 signal_threads(ST_GRACEFUL);
795 rbb 89781 }
796     break;
797     }
798     }
799    
800 colm 290179 ap_close_listeners();
801 trawick 94106 ap_queue_term(worker_queue);
802 rbb 89781 dying = 1;
803 rbb 90065 ap_scoreboard_image->parent[process_slot].quiescing = 1;
804 trawick 94112
805 trawick 94232 /* wake up the main thread */
806 rbb 90065 kill(ap_my_pid, SIGTERM);
807 rbb 89781
808 rbb 90635 apr_thread_exit(thd, APR_SUCCESS);
809 rbb 89781 return NULL;
810     }
811    
812 trawick 94068 /* 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 wrowe 93264 static void * APR_THREAD_FUNC worker_thread(apr_thread_t *thd, void * dummy)
820 rbb 89781 {
821     proc_info * ti = dummy;
822     int process_slot = ti->pid;
823     int thread_slot = ti->tid;
824     apr_socket_t *csd = NULL;
825 jwoolley 94304 apr_bucket_alloc_t *bucket_alloc;
826 brianp 93386 apr_pool_t *last_ptrans = NULL;
827 jerenkrantz 92473 apr_pool_t *ptrans; /* Pool for per-transaction stuff */
828 rbb 90635 apr_status_t rv;
829 brianp 95270 int is_idle = 0;
830 rbb 89781
831     free(ti);
832    
833 trawick 156274 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 trawick 92512 ap_update_child_status_from_indexes(process_slot, thread_slot, SERVER_STARTING, NULL);
836 jwoolley 94304
837 trawick 424876 #ifdef HAVE_PTHREAD_KILL
838     unblock_signal(WORKER_SIGNAL);
839     apr_signal(WORKER_SIGNAL, dummy_signal_handler);
840     #endif
841    
842 rbb 89781 while (!workers_may_exit) {
843 brianp 95270 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 aaron 94824 }
855    
856 trawick 92512 ap_update_child_status_from_indexes(process_slot, thread_slot, SERVER_READY, NULL);
857 aaron 94840 worker_pop:
858     if (workers_may_exit) {
859     break;
860     }
861 brianp 94830 rv = ap_queue_pop(worker_queue, &csd, &ptrans);
862 brianp 93386
863 trawick 94067 if (rv != APR_SUCCESS) {
864 trawick 94106 /* We get APR_EOF during a graceful shutdown once all the connections
865     * accepted by this server process have been handled.
866     */
867 aaron 94840 if (APR_STATUS_IS_EOF(rv)) {
868 trawick 94106 break;
869     }
870 trawick 94067 /* 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 trawick 94068 *
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 trawick 94067 */
881 aaron 94840 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 trawick 94067 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
887     "ap_queue_pop failed");
888     }
889 rbb 90065 continue;
890     }
891 brianp 95270 is_idle = 0;
892 jerenkrantz 94886 worker_sockets[thread_slot] = csd;
893 jwoolley 101122 bucket_alloc = apr_bucket_alloc_create(ptrans);
894 jwoolley 94304 process_socket(ptrans, csd, process_slot, thread_slot, bucket_alloc);
895 jerenkrantz 94886 worker_sockets[thread_slot] = NULL;
896 rbb 90635 requests_this_child--; /* FIXME: should be synchronized - aaron */
897 brianp 93386 apr_pool_clear(ptrans);
898     last_ptrans = ptrans;
899 rbb 89781 }
900    
901 trawick 92512 ap_update_child_status_from_indexes(process_slot, thread_slot,
902 rbb 90771 (dying) ? SERVER_DEAD : SERVER_GRACEFUL, (request_rec *) NULL);
903 rbb 89781
904 aaron 92622 apr_thread_exit(thd, APR_SUCCESS);
905 rbb 89781 return NULL;
906     }
907    
908 aaron 93403 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 trawick 94420 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 trawick 94700 my_info, pchild);
931 trawick 94420 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 gregames 168182 /* let the parent decide how bad this really is */
935     clean_child_exit(APEXIT_CHILDSICK);
936 trawick 94420 }
937     apr_os_thread_get(&listener_os_thread, ts->listener);
938     }
939    
940 trawick 94059 /* 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 trawick 94030 */
945 wrowe 93264 static void * APR_THREAD_FUNC start_threads(apr_thread_t *thd, void *dummy)
946 rbb 89781 {
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 trawick 94420 proc_info *my_info;
953 rbb 89781 apr_status_t rv;
954 trawick 94420 int i;
955 rbb 89781 int threads_created = 0;
956 stoddard 94889 int listener_started = 0;
957 trawick 94059 int loops;
958     int prev_threads_created;
959 rbb 89781
960 rbb 90771 /* We must create the fd queues before we start up the listener
961 rbb 90635 * and worker threads. */
962 rbb 91075 worker_queue = apr_pcalloc(pchild, sizeof(*worker_queue));
963 trawick 93530 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 rbb 90635
970 brianp 94830 rv = ap_queue_info_create(&worker_queue_info, pchild,
971     ap_threads_per_child);
972 aaron 94824 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 jerenkrantz 94886 worker_sockets = apr_pcalloc(pchild, ap_threads_per_child
979     * sizeof(apr_socket_t *));
980    
981 trawick 94059 loops = prev_threads_created = 0;
982 rbb 89781 while (1) {
983 dougm 90673 /* ap_threads_per_child does not include the listener thread */
984 dougm 90670 for (i = 0; i < ap_threads_per_child; i++) {
985 rbb 89781 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 aaron 92632 my_info = (proc_info *)malloc(sizeof(proc_info));
992 rbb 89781 if (my_info == NULL) {
993     ap_log_error(APLOG_MARK, APLOG_ALERT, errno, ap_server_conf,
994 jerenkrantz 92473 "malloc: out of memory");
995 rbb 89781 clean_child_exit(APEXIT_CHILDFATAL);
996     }
997 jerenkrantz 92473 my_info->pid = my_child_num;
998 rbb 89781 my_info->tid = i;
999 jerenkrantz 92473 my_info->sd = 0;
1000 jim 332309
1001 aaron 92632 /* We are creating threads right now */
1002     ap_update_child_status_from_indexes(my_child_num, i,
1003     SERVER_STARTING, NULL);
1004 rbb 89781 /* We let each thread update its own scoreboard entry. This is
1005     * done because it lets us deal with tid better.
1006 jerenkrantz 92473 */
1007 jim 332309 rv = apr_thread_create(&threads[i], thread_attr,
1008 trawick 94700 worker_thread, my_info, pchild);
1009 aaron 92632 if (rv != APR_SUCCESS) {
1010 jerenkrantz 92473 ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
1011 aaron 92632 "apr_thread_create: unable to create worker thread");
1012 gregames 168182 /* let the parent decide how bad this really is */
1013     clean_child_exit(APEXIT_CHILDSICK);
1014 jerenkrantz 92473 }
1015 rbb 89781 threads_created++;
1016     }
1017 stoddard 94889 /* 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 trawick 94095 if (start_thread_may_exit || threads_created == ap_threads_per_child) {
1023 rbb 89781 break;
1024     }
1025 wrowe 93264 /* wait for previous generation to clean up an entry */
1026 brianp 95959 apr_sleep(apr_time_from_sec(1));
1027 trawick 94059 ++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 rbb 89781 }
1038 jim 332309
1039     /* What state should this child_main process be listed as in the
1040 jerenkrantz 92473 * scoreboard...?
1041 jim 332309 * ap_update_child_status_from_indexes(my_child_num, i, SERVER_STARTING,
1042 trawick 92512 * (request_rec *) NULL);
1043 jim 332309 *
1044 rbb 89781 * This state should be listed separately in the scoreboard, in some kind
1045 jim 332309 * 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 rbb 89781 * the name could be clearer. gla
1048     */
1049 aaron 92622 apr_thread_exit(thd, APR_SUCCESS);
1050 rbb 89781 return NULL;
1051     }
1052    
1053 trawick 94031 static void join_workers(apr_thread_t *listener, apr_thread_t **threads)
1054 trawick 93561 {
1055     int i;
1056     apr_status_t rv, thread_rv;
1057    
1058 trawick 94031 if (listener) {
1059     int iter;
1060 jim 332309
1061 trawick 94031 /* 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 trawick 94095 * listener_may_exit flag is clear and the time it enters a
1065 trawick 94031 * 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 jim 332309 while (iter < 10 &&
1071 trawick 94417 #ifdef HAVE_PTHREAD_KILL
1072     pthread_kill(*listener_os_thread, 0)
1073     #else
1074     kill(ap_my_pid, 0)
1075     #endif
1076     == 0) {
1077 trawick 94031 /* listener not dead yet */
1078 brianp 95959 apr_sleep(apr_time_make(0, 500000));
1079 trawick 94031 wakeup_listener();
1080     ++iter;
1081     }
1082     if (iter >= 10) {
1083 trawick 101165 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
1084 trawick 94031 "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 jim 332309
1095 trawick 93561 for (i = 0; i < ap_threads_per_child; i++) {
1096     if (threads[i]) { /* if we ever created this thread */
1097 trawick 424876 #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 trawick 93561 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 jim 332309 start_thread_may_exit = 1; /* tell it to give up in case it is still
1120     * trying to take over slots from a
1121 trawick 94095 * previous generation
1122     */
1123 trawick 93561 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 rbb 89781 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 trawick 102045 mpm_state = AP_MPMQ_STARTING; /* for benefit of any hooks that run as this
1140     * child initializes
1141     */
1142 rbb 89781 ap_my_pid = getpid();
1143 trawick 99312 ap_fatal_signal_child_setup(ap_server_conf);
1144 rbb 89781 apr_pool_create(&pchild, pconf);
1145    
1146     /*stuff to do before we switch id's, so we have permissions.*/
1147 rbb 93119 ap_reopen_scoreboard(pchild, NULL, 0);
1148 rbb 89781
1149 trawick 92412 rv = SAFE_ACCEPT(apr_proc_mutex_child_init(&accept_mutex, ap_lock_fname,
1150 aaron 91580 pchild));
1151 rbb 89781 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 jerenkrantz 92473 clean_child_exit(APEXIT_CHILDFATAL);
1159 rbb 89781 }
1160    
1161     ap_run_child_init(pchild, ap_server_conf);
1162    
1163 rbb 90771 /* done with init critical section */
1164 rbb 89781
1165 rbb 93358 /* 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 rbb 89781 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 jim 332309
1184 rbb 89781 /* Setup worker threads */
1185    
1186 jim 332309 /* clear the storage; we may not create all our threads immediately,
1187 jerenkrantz 92473 * and we want a 0 entry to indicate a thread which was not created
1188 rbb 89781 */
1189 jim 332309 threads = (apr_thread_t **)calloc(1,
1190 jerenkrantz 92473 sizeof(apr_thread_t *) * ap_threads_per_child);
1191 rbb 89781 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 rbb 90635 ts = (thread_starter *)apr_palloc(pchild, sizeof(*ts));
1198 rbb 89781
1199     apr_threadattr_create(&thread_attr, pchild);
1200 jerenkrantz 92473 /* 0 means PTHREAD_CREATE_JOINABLE */
1201     apr_threadattr_detach_set(thread_attr, 0);
1202 rbb 89781
1203 trawick 102975 if (ap_thread_stacksize != 0) {
1204     apr_threadattr_stacksize_set(thread_attr, ap_thread_stacksize);
1205 trawick 102931 }
1206 jim 332309
1207 rbb 89781 ts->threads = threads;
1208 trawick 94031 ts->listener = NULL;
1209 rbb 89781 ts->child_num_arg = child_num_arg;
1210     ts->threadattr = thread_attr;
1211    
1212 aaron 92632 rv = apr_thread_create(&start_thread_id, thread_attr, start_threads,
1213 trawick 94700 ts, pchild);
1214 aaron 92632 if (rv != APR_SUCCESS) {
1215 rbb 89781 ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
1216     "apr_thread_create: unable to create worker thread");
1217 gregames 168649 /* let the parent decide how bad this really is */
1218     clean_child_exit(APEXIT_CHILDSICK);
1219 rbb 89781 }
1220    
1221 trawick 102045 mpm_state = AP_MPMQ_RUNNING;
1222    
1223 aaron 93403 /* If we are only running in one_process mode, we will want to
1224     * still handle signals. */
1225     if (one_process) {
1226 trawick 94091 /* Block until we get a terminating signal. */
1227 aaron 93403 apr_signal_thread(check_signal);
1228 jim 332309 /* make sure the start thread has finished; signal_threads()
1229 trawick 93561 * and join_workers() depend on that
1230     */
1231 trawick 94094 /* 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 trawick 93561 join_start_thread(start_thread_id);
1236 trawick 94095 signal_threads(ST_UNGRACEFUL); /* helps us terminate a little more
1237     * quickly than the dispatch of the signal thread
1238 aaron 93403 * 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 rbb 93358 */
1247 trawick 94031 join_workers(ts->listener, threads);
1248 rbb 89781 }
1249 aaron 93403 else { /* !one_process */
1250 trawick 94232 /* 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 aaron 93403 /* Watch for any messages from the parent over the POD */
1257     while (1) {
1258     rv = ap_mpm_pod_check(pod);
1259 trawick 94232 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 aaron 93403 if (rv == AP_GRACEFUL || rv == AP_RESTART) {
1271 jim 332309 /* make sure the start thread has finished;
1272 trawick 94095 * signal_threads() and join_workers depend on that
1273 trawick 93561 */
1274     join_start_thread(start_thread_id);
1275 trawick 94095 signal_threads(rv == AP_GRACEFUL ? ST_GRACEFUL : ST_UNGRACEFUL);
1276 aaron 93403 break;
1277     }
1278     }
1279 rbb 89781
1280 trawick 94892 /* 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 aaron 93403 }
1289    
1290 rbb 89781 free(threads);
1291    
1292 gregames 93366 clean_child_exit(resource_shortage ? APEXIT_CHILDSICK : 0);
1293 rbb 89781 }
1294    
1295 jim 332309 static int make_child(server_rec *s, int slot)
1296 rbb 89781 {
1297     int pid;
1298    
1299     if (slot + 1 > ap_max_daemons_limit) {
1300 jerenkrantz 92473 ap_max_daemons_limit = slot + 1;
1301 rbb 89781 }
1302    
1303     if (one_process) {
1304 jerenkrantz 92473 set_signals();
1305 rbb 89781 ap_scoreboard_image->parent[slot].pid = getpid();
1306 jerenkrantz 92473 child_main(slot);
1307 rbb 89781 }
1308    
1309     if ((pid = fork()) == -1) {
1310 jim 332309 ap_log_error(APLOG_MARK, APLOG_ERR, errno, s,
1311 jerenkrantz 92473 "fork: Unable to fork new process");
1312 rbb 89781
1313     /* fork didn't succeed. Fix the scoreboard or else
1314     * it will say SERVER_STARTING forever and ever
1315     */
1316 trawick 92512 ap_update_child_status_from_indexes(slot, 0, SERVER_DEAD, NULL);
1317 rbb 89781
1318 jerenkrantz 92473 /* 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 brianp 95959 apr_sleep(apr_time_from_sec(10));
1322 rbb 89781
1323 jerenkrantz 92473 return -1;
1324 rbb 89781 }
1325    
1326     if (!pid) {
1327     #ifdef HAVE_BINDPROCESSOR
1328     /* By default, AIX binds to a single processor. This bit unbinds
1329 jerenkrantz 92473 * children which will then bind to another CPU.
1330 rbb 89781 */
1331     int status = bindprocessor(BINDPROCESS, (int)getpid(),
1332 jerenkrantz 92473 PROCESSOR_CLASS_ANY);
1333     if (status != OK)
1334 jim 332309 ap_log_error(APLOG_MARK, APLOG_WARNING, errno,
1335 jerenkrantz 92473 ap_server_conf,
1336     "processor unbind failed %d", status);
1337 rbb 89781 #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 trawick 109510 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 rbb 89781 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 jerenkrantz 92473 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 rbb 89781 }
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 jerenkrantz 92473 #define MAX_SPAWN_RATE (32)
1392 rbb 89781 #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 gregames 89928 int totally_free_length = 0;
1403 rbb 89781 int free_slots[MAX_SPAWN_RATE];
1404     int last_non_dead;
1405     int total_non_dead;
1406 gregames 168182 int active_thread_count = 0;
1407 rbb 89781
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 jerenkrantz 92473 /* 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 rbb 89781
1423 jerenkrantz 92473 if (i >= ap_max_daemons_limit && totally_free_length == idle_spawn_rate)
1424     break;
1425 rbb 89781 ps = &ap_scoreboard_image->parent[i];
1426 jerenkrantz 92473 for (j = 0; j < ap_threads_per_child; j++) {
1427 rbb 89781 ws = &ap_scoreboard_image->servers[i][j];
1428 jerenkrantz 92473 status = ws->status;
1429 rbb 89781
1430 gregames 89928 /* XXX any_dying_threads is probably no longer needed GLA */
1431 jim 332309 any_dying_threads = any_dying_threads ||
1432 jerenkrantz 92473 (status == SERVER_GRACEFUL);
1433     any_dead_threads = any_dead_threads || (status == SERVER_DEAD);
1434     all_dead_threads = all_dead_threads &&
1435 gregames 89928 (status == SERVER_DEAD ||
1436     status == SERVER_GRACEFUL);
1437 rbb 89781
1438 jerenkrantz 92473 /* 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 gregames 168182 if (ps->pid != 0) { /* XXX just set all_dead_threads in outer for
1445     loop if no pid? not much else matters */
1446 trawick 424874 if (status <= SERVER_READY &&
1447 gregames 168182 !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 jerenkrantz 92473 }
1455     }
1456 trawick 102425 if (any_dead_threads && totally_free_length < idle_spawn_rate
1457     && free_length < MAX_SPAWN_RATE
1458 rbb 89781 && (!ps->pid /* no process in the slot */
1459     || ps->quiescing)) { /* or at least one is going away */
1460 gregames 89928 if (all_dead_threads) {
1461     /* great! we prefer these, because the new process can
1462 jim 332309 * start more threads sooner. So prioritize this slot
1463 gregames 89928 * 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 gregames 160211 free_slots[free_length] = i;
1475 gregames 89928 }
1476 jerenkrantz 92473 ++free_length;
1477     }
1478 gregames 89928 /* XXX if (!ps->quiescing) is probably more reliable GLA */
1479 jerenkrantz 92473 if (!any_dying_threads) {
1480 rbb 89781 last_non_dead = i;
1481     ++total_non_dead;
1482     }
1483     }
1484 gregames 168182
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 jim 332309 /* looks like a basket case. give up.
1494 gregames 168182 */
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 jim 332309
1506 rbb 89781 ap_max_daemons_limit = last_non_dead + 1;
1507    
1508     if (idle_thread_count > max_spare_threads) {
1509     /* Kill off one child */
1510 rbb 93358 ap_mpm_pod_signal(pod, TRUE);
1511 rbb 89781 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 jerenkrantz 92473 /* only report this condition once */
1517     static int reported = 0;
1518 jim 332309
1519 jerenkrantz 92473 if (!reported) {
1520 jim 332309 ap_log_error(APLOG_MARK, APLOG_ERR, 0,
1521 jerenkrantz 92473 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 gregames 89928 if (free_length > idle_spawn_rate) {
1530     free_length = idle_spawn_rate;
1531     }
1532 jerenkrantz 92473 if (idle_spawn_rate >= 8) {
1533 jim 332309 ap_log_error(APLOG_MARK, APLOG_INFO, 0,
1534 jerenkrantz 92473 ap_server_conf,
1535     "server seems busy, (you may need "
1536     "to increase StartServers, ThreadsPerChild "
1537 rbb 89781 "or Min/MaxSpareThreads), "
1538 jerenkrantz 92473 "spawning %d children, there are around %d idle "
1539 rbb 89781 "threads, and %d total children", free_length,
1540 jerenkrantz 92473 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 rbb 89781 }
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 rbb 91648 apr_exit_why_e exitwhy;
1565 gregames 93366 int status, processed_status;
1566 rbb 89781 apr_proc_t pid;
1567     int i;
1568    
1569     while (!restart_pending && !shutdown_pending) {
1570 rbb 91648 ap_wait_or_timeout(&exitwhy, &status, &pid, pconf);
1571 jim 332309
1572 rbb 89781 if (pid.pid != -1) {
1573 gregames 93366 processed_status = ap_process_child_status(&pid, exitwhy, status);
1574     if (processed_status == APEXIT_CHILDFATAL) {
1575 trawick 92019 shutdown_pending = 1;
1576     child_fatal = 1;
1577     return;
1578     }
1579 gregames 168182 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 rbb 89781 /* 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 jim 332309 ap_update_child_status_from_indexes(child_slot, i, SERVER_DEAD,
1590 trawick 92512 (request_rec *) NULL);
1591 jim 332309
1592 rbb 89781 ap_scoreboard_image->parent[child_slot].pid = 0;
1593     ap_scoreboard_image->parent[child_slot].quiescing = 0;
1594 gregames 93366 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 jerenkrantz 92473 && child_slot < ap_daemons_limit) {
1600     /* we're still doing a 1-for-1 replacement of dead
1601 rbb 89781 * children with new children
1602     */
1603 jerenkrantz 92473 make_child(ap_server_conf, child_slot);
1604     --remaining_children_to_start;
1605     }
1606 trawick 109510 }
1607     else if (ap_unregister_extra_mpm_process(pid.pid) == 1) {
1608     /* handled */
1609 rbb 89781 #if APR_HAS_OTHER_CHILD
1610 jerenkrantz 92473 }
1611 brianp 101858 else if (apr_proc_other_child_alert(&pid, APR_OC_REASON_DEATH,
1612     status) == 0) {
1613 jerenkrantz 92473 /* handled */
1614 rbb 89781 #endif
1615 jerenkrantz 92473 }
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 trawick 95149 ap_log_error(APLOG_MARK, APLOG_WARNING, 0,
1621 jerenkrantz 92473 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 rbb 89781 * 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 jerenkrantz 92473 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 rbb 89781
1646 jerenkrantz 92473 perform_idle_server_maintenance();
1647 rbb 89781 }
1648     }
1649    
1650 rbb 91955 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 rbb 93227 ap_log_pid(pconf, ap_pid_fname);
1656    
1657 trawick 92530 first_server_limit = server_limit;
1658     first_thread_limit = thread_limit;
1659     if (changed_limit_at_restart) {
1660 trawick 95149 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
1661 trawick 92530 "WARNING: Attempt to change ServerLimit or ThreadLimit "
1662     "ignored during restart");
1663     changed_limit_at_restart = 0;
1664     }
1665 jim 332309
1666 rbb 89781 /* Initialize cross-process accept lock */
1667 wrowe 93969 ap_lock_fname = apr_psprintf(_pconf, "%s.%" APR_PID_T_FMT,
1668 trawick 92412 ap_server_root_relative(_pconf, ap_lock_fname),
1669     ap_my_pid);
1670 dreid 92596
1671 jim 332309 rv = apr_proc_mutex_create(&accept_mutex, ap_lock_fname,
1672 trawick 92653 ap_accept_lock_mech, _pconf);
1673 rbb 89781 if (rv != APR_SUCCESS) {
1674     ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s,
1675     "Couldn't create accept lock");
1676 trawick 102045 mpm_state = AP_MPMQ_STOPPING;
1677 rbb 89781 return 1;
1678     }
1679    
1680 trawick 90213 #if APR_USE_SYSVSEM_SERIALIZE
1681 jim 332309 if (ap_accept_lock_mech == APR_LOCK_DEFAULT ||
1682 trawick 90213 ap_accept_lock_mech == APR_LOCK_SYSVSEM) {
1683     #else
1684     if (ap_accept_lock_mech == APR_LOCK_SYSVSEM) {
1685     #endif
1686 aaron 91580 rv = unixd_set_proc_mutex_perms(accept_mutex);
1687 trawick 90213 if (rv != APR_SUCCESS) {
1688     ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s,
1689 trawick 94541 "Couldn't set permissions on cross-process lock; "
1690     "check User and Group directives");
1691 trawick 102045 mpm_state = AP_MPMQ_STOPPING;
1692 trawick 90213 return 1;
1693     }
1694     }
1695    
1696 rbb 89781 if (!is_graceful) {
1697 wrowe 94039 if (ap_run_pre_mpm(s->process->pool, SB_SHARED) != OK) {
1698 trawick 102045 mpm_state = AP_MPMQ_STOPPING;
1699 trawick 93055 return 1;
1700     }
1701 trawick 93998 /* 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 rbb 89781 }
1706    
1707     set_signals();
1708     /* Don't thrash... */
1709     if (max_spare_threads < min_spare_threads + ap_threads_per_child)
1710 jerenkrantz 92473 max_spare_threads = min_spare_threads + ap_threads_per_child;
1711 rbb 89781
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 jerenkrantz 91076 * below (because we just sent them AP_SIG_GRACEFUL). This happens pretty
1715 rbb 89781 * 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 jerenkrantz 92473 remaining_children_to_start = ap_daemons_limit;
1723 rbb 89781 }
1724     if (!is_graceful) {
1725 jerenkrantz 92473 startup_children(remaining_children_to_start);
1726     remaining_children_to_start = 0;
1727 rbb 89781 }
1728     else {
1729 jerenkrantz 92473 /* give the system some time to recover before kicking into
1730     * exponential mode */
1731     hold_off_on_exponential_spawning = 10;
1732 rbb 89781 }
1733    
1734 trawick 95149 ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
1735 jerenkrantz 92473 "%s configured -- resuming normal operations",
1736 trawick 446606 ap_get_server_description());
1737 trawick 95149 ap_log_error(APLOG_MARK, APLOG_INFO, 0, ap_server_conf,
1738 jerenkrantz 92473 "Server built: %s", ap_get_server_built());
1739 jim 94055 #ifdef AP_MPM_WANT_SET_ACCEPT_LOCK_MECH
1740 trawick 95149 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
1741 jim 332307 "AcceptMutex: %s (default: %s)",
1742     apr_proc_mutex_name(accept_mutex),
1743     apr_proc_mutex_defname());
1744 jim 94055 #endif
1745 rbb 89781 restart_pending = shutdown_pending = 0;
1746 trawick 102045 mpm_state = AP_MPMQ_RUNNING;
1747 jim 332309
1748 rbb 89781 server_main_loop(remaining_children_to_start);
1749 trawick 102045 mpm_state = AP_MPMQ_STOPPING;
1750 rbb 89781
1751 colm 290189 if (shutdown_pending && !is_graceful) {
1752     /* Time to shut down:
1753 rbb 89781 * Kill child processes, tell them to call child_exit, etc...
1754     */
1755 trawick 94024 ap_mpm_pod_killpg(pod, ap_daemons_limit, FALSE);
1756 jerenkrantz 92473 ap_reclaim_child_processes(1); /* Start with SIGTERM */
1757 trawick 92019
1758     if (!child_fatal) {
1759     /* cleanup pid file on normal shutdown */
1760 rbb 89781 const char *pidfile = NULL;
1761     pidfile = ap_server_root_relative (pconf, ap_pid_fname);
1762     if ( pidfile != NULL && unlink(pidfile) == 0)
1763 trawick 95149 ap_log_error(APLOG_MARK, APLOG_INFO, 0,
1764 jerenkrantz 92473 ap_server_conf,
1765 colm 290189 "removed PID file %s (pid=%" APR_PID_T_FMT ")",
1766     pidfile, getpid());
1767 jim 332309
1768 trawick 95149 ap_log_error(APLOG_MARK, APLOG_NOTICE, 0,
1769 trawick 92019 ap_server_conf, "caught SIGTERM, shutting down");
1770 rbb 89781 }
1771 jerenkrantz 92473 return 1;
1772 colm 290189 } 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