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