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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 * This is a single process, with multiple worker threads.
21 * Under testing I found that given the inability of BeOS to handle threads
22 * and forks it didn't make sense to try and have a set of "children" threads
23 * that spawned the "worker" threads, so just missed out the middle mand and
24 * somehow arrived here.
26 * For 2.1 this has been rewritten to have simpler logic, though there is still
27 * some simplification that can be done. It's still a work in progress!
31 * - on exit most worker threads segfault trying to access a kernel page.
34 #include <kernel/OS.h>
36 #include <sys/socket.h>
39 #include "apr_strings.h"
40 #include "apr_portable.h"
42 #include "http_main.h"
44 #include "http_config.h" /* for read_config */
45 #include "http_core.h" /* for get_remote_host */
46 #include "http_connection.h"
49 #include "ap_listen.h"
50 #include "scoreboard.h"
51 #include "mpm_common.h"
53 #include "mpm_default.h"
54 #include "apr_thread_mutex.h"
57 extern int _kset_fd_limit_(int num
);
59 /* Limit on the total --- clients will be locked out if more servers than
60 * this are needed. It is intended solely to keep the server from crashing
61 * when things get out of hand.
63 * We keep a hard maximum number of servers, for two reasons:
64 * 1) in case something goes seriously wrong, we want to stop the server starting
65 * threads ad infinitum and crashing the server (remember that BeOS has a 192
66 * thread per team limit).
67 * 2) it keeps the size of the scoreboard file small
68 * enough that we can read the whole thing without worrying too much about
72 /* we only ever have 1 main process running... */
73 #define HARD_SERVER_LIMIT 1
75 /* Limit on the threads per process. Clients will be locked out if more than
76 * this * HARD_SERVER_LIMIT are needed.
78 * We keep this for one reason it keeps the size of the scoreboard file small
79 * enough that we can read the whole thing without worrying too much about
83 #define HARD_THREAD_LIMIT 1
85 #ifndef HARD_THREAD_LIMIT
86 #define HARD_THREAD_LIMIT 50
90 * Actual definitions of config globals
93 static int ap_threads_to_start
=0;
94 static int ap_max_requests_per_thread
= 0;
95 static int min_spare_threads
=0;
96 static int max_spare_threads
=0;
97 static int ap_thread_limit
=0;
98 static int num_listening_sockets
= 0;
99 static int mpm_state
= AP_MPMQ_STARTING
;
100 apr_thread_mutex_t
*accept_mutex
= NULL
;
102 static apr_pool_t
*pconf
; /* Pool for config stuff */
103 static apr_pool_t
*pmain
; /* Pool for httpd child stuff */
105 static int server_pid
;
109 * The max child slot ever assigned, preserved across restarts. Necessary
110 * to deal with MaxClients changes across AP_SIG_GRACEFUL restarts. We use
111 * this value to optimize routines that have to scan the entire scoreboard.
113 int ap_max_child_assigned
= -1;
114 int ap_max_threads_limit
= -1;
116 static apr_socket_t
*udp_sock
;
117 static apr_sockaddr_t
*udp_sa
;
119 server_rec
*ap_server_conf
;
122 static int one_process
= 0;
125 int raise_sigstop_flags
;
128 static void check_restart(void *data
);
130 /* When a worker thread gets to the end of it's life it dies with an
131 * exit value of the code supplied to this function. The thread has
132 * already had check_restart() registered to be called when dying, so
133 * we don't concern ourselves with restarting at all here. We do however
134 * mark the scoreboard slot as belonging to a dead server and zero out
137 * TODO - use the status we set to determine if we need to restart the
140 static void clean_child_exit(int code
, int slot
)
142 (void) ap_update_child_status_from_indexes(0, slot
, SERVER_DEAD
,
144 ap_scoreboard_image
->servers
[0][slot
].tid
= 0;
148 /* proper cleanup when returning from ap_mpm_run() */
149 static void mpm_main_cleanup(void)
152 apr_pool_destroy(pmain
);
157 /*****************************************************************
158 * Connection structures and accounting...
161 /* volatile just in case */
162 static int volatile shutdown_pending
;
163 static int volatile restart_pending
;
164 static int volatile is_graceful
;
165 static int volatile child_fatal
;
166 ap_generation_t
volatile ap_my_generation
= 0;
169 * ap_start_shutdown() and ap_start_restart(), below, are a first stab at
170 * functions to initiate shutdown or restart without relying on signals.
171 * Previously this was initiated in sig_term() and restart() signal handlers,
172 * but we want to be able to start a shutdown/restart from other sources --
173 * e.g. on Win32, from the service manager. Now the service manager can
174 * call ap_start_shutdown() or ap_start_restart() as appropiate. Note that
175 * these functions can also be called by the child processes, since global
176 * variables are no longer used to pass on the required action to the parent.
178 * These should only be called from the parent process itself, since the
179 * parent process will use the shutdown_pending and restart_pending variables
180 * to determine whether to shutdown or restart. The child process should
181 * call signal_parent() directly to tell the parent to die -- this will
182 * cause neither of those variable to be set, which the parent will
183 * assume means something serious is wrong (which it will be, for the
184 * child to force an exit) and so do an exit anyway.
187 static void ap_start_shutdown(void)
189 /* If the user tries to shut us down twice in quick succession then we
190 * may well get triggered while we are working through previous attempt
191 * to shutdown. We won't worry about even reporting it as it seems a little
194 if (shutdown_pending
== 1)
197 shutdown_pending
= 1;
200 /* do a graceful restart if graceful == 1 */
201 static void ap_start_restart(int graceful
)
203 if (restart_pending
== 1) {
204 /* Probably not an error - don't bother reporting it */
208 is_graceful
= graceful
;
211 /* sig_coredump attempts to handle all the potential signals we
212 * may get that should result in a core dump. This is called from
213 * the signal handler routine, so when we enter we are essentially blocked
214 * on the signal. Once we exit we will allow the signal to be processed by
215 * system, which may or may not produce a .core file. All this function does
216 * is try and respect the users wishes about where that file should be
217 * located (chdir) and then signal the parent with the signal.
219 * If we called abort() the parent would only see SIGABRT which doesn't provide
220 * as much information.
222 static void sig_coredump(int sig
)
224 chdir(ap_coredump_dir
);
225 signal(sig
, SIG_DFL
);
226 kill(server_pid
, sig
);
229 static void sig_term(int sig
)
234 static void restart(int sig
)
236 ap_start_restart(sig
== AP_SIG_GRACEFUL
);
239 /* Handle queries about our inner workings... */
240 AP_DECLARE(apr_status_t
) ap_mpm_query(int query_code
, int *result
)
243 case AP_MPMQ_MAX_DAEMON_USED
:
244 *result
= ap_max_child_assigned
;
246 case AP_MPMQ_IS_THREADED
:
247 *result
= AP_MPMQ_DYNAMIC
;
249 case AP_MPMQ_IS_FORKED
:
250 *result
= AP_MPMQ_NOT_SUPPORTED
;
252 case AP_MPMQ_HARD_LIMIT_DAEMONS
:
253 *result
= HARD_SERVER_LIMIT
;
255 case AP_MPMQ_HARD_LIMIT_THREADS
:
256 *result
= HARD_THREAD_LIMIT
;
258 case AP_MPMQ_MAX_THREADS
:
259 *result
= HARD_THREAD_LIMIT
;
261 case AP_MPMQ_MIN_SPARE_DAEMONS
:
264 case AP_MPMQ_MIN_SPARE_THREADS
:
265 *result
= max_spare_threads
;
267 case AP_MPMQ_MAX_SPARE_DAEMONS
:
270 case AP_MPMQ_MAX_SPARE_THREADS
:
271 *result
= min_spare_threads
;
273 case AP_MPMQ_MAX_REQUESTS_DAEMON
:
274 *result
= ap_max_requests_per_thread
;
276 case AP_MPMQ_MAX_DAEMONS
:
277 *result
= HARD_SERVER_LIMIT
;
279 case AP_MPMQ_MPM_STATE
:
286 /* This accepts a connection and allows us to handle the error codes better than
287 * the previous code, while also making it more obvious.
289 static apr_status_t
beos_accept(void **accepted
, ap_listen_rec
*lr
, apr_pool_t
*ptrans
)
296 status
= apr_socket_accept(&csd
, lr
->sd
, ptrans
);
297 if (status
== APR_SUCCESS
) {
299 apr_os_sock_get(&sockdes
, csd
);
303 if (APR_STATUS_IS_EINTR(status
)) {
306 /* This switch statement provides us with better error details. */
324 * When the network layer has been shut down, there
325 * is not much use in simply exiting: the parent
326 * would simply re-create us (and we'd fail again).
327 * Use the CHILDFATAL code to tear the server down.
328 * @@@ Martin's idea for possible improvement:
329 * A different approach would be to define
330 * a new APEXIT_NETDOWN exit code, the reception
331 * of which would make the parent shutdown all
332 * children, then idle-loop until it detected that
333 * the network is up again, and restart the children.
334 * Ben Hyde noted that temporary ENETDOWN situations
335 * occur in mobile IP.
337 ap_log_error(APLOG_MARK
, APLOG_EMERG
, status
, ap_server_conf
,
338 "apr_socket_accept: giving up.");
343 ap_log_error(APLOG_MARK
, APLOG_ERR
, status
, ap_server_conf
,
344 "apr_socket_accept: (client socket)");
350 static void tell_workers_to_exit(void)
354 for (i
= 0 ; i
< ap_max_child_assigned
; i
++){
356 if (apr_socket_sendto(udp_sock
, udp_sa
, 0, "die!", &len
) != APR_SUCCESS
)
361 static void set_signals(void)
365 sigemptyset(&sa
.sa_mask
);
368 /* The first batch get handled by sig_coredump */
370 sa
.sa_handler
= sig_coredump
;
372 if (sigaction(SIGSEGV
, &sa
, NULL
) < 0)
373 ap_log_error(APLOG_MARK
, APLOG_WARNING
, errno
, ap_server_conf
, "sigaction(SIGSEGV)");
374 if (sigaction(SIGBUS
, &sa
, NULL
) < 0)
375 ap_log_error(APLOG_MARK
, APLOG_WARNING
, errno
, ap_server_conf
, "sigaction(SIGBUS)");
376 if (sigaction(SIGABRT
, &sa
, NULL
) < 0)
377 ap_log_error(APLOG_MARK
, APLOG_WARNING
, errno
, ap_server_conf
, "sigaction(SIGABRT)");
378 if (sigaction(SIGILL
, &sa
, NULL
) < 0)
379 ap_log_error(APLOG_MARK
, APLOG_WARNING
, errno
, ap_server_conf
, "sigaction(SIGILL)");
383 /* These next two are handled by sig_term */
384 sa
.sa_handler
= sig_term
;
385 if (sigaction(SIGTERM
, &sa
, NULL
) < 0)
386 ap_log_error(APLOG_MARK
, APLOG_WARNING
, errno
, ap_server_conf
, "sigaction(SIGTERM)");
387 if (sigaction(SIGINT
, &sa
, NULL
) < 0)
388 ap_log_error(APLOG_MARK
, APLOG_WARNING
, errno
, ap_server_conf
, "sigaction(SIGINT)");
390 /* We ignore SIGPIPE */
391 sa
.sa_handler
= SIG_IGN
;
392 if (sigaction(SIGPIPE
, &sa
, NULL
) < 0)
393 ap_log_error(APLOG_MARK
, APLOG_WARNING
, errno
, ap_server_conf
, "sigaction(SIGPIPE)");
395 /* we want to ignore HUPs and AP_SIG_GRACEFUL while we're busy
397 sigaddset(&sa
.sa_mask
, SIGHUP
);
398 sigaddset(&sa
.sa_mask
, AP_SIG_GRACEFUL
);
399 sa
.sa_handler
= restart
;
400 if (sigaction(SIGHUP
, &sa
, NULL
) < 0)
401 ap_log_error(APLOG_MARK
, APLOG_WARNING
, errno
, ap_server_conf
, "sigaction(SIGHUP)");
402 if (sigaction(AP_SIG_GRACEFUL
, &sa
, NULL
) < 0)
403 ap_log_error(APLOG_MARK
, APLOG_WARNING
, errno
, ap_server_conf
, "sigaction(" AP_SIG_GRACEFUL_STRING
")");
406 /* This is the thread that actually does all the work. */
407 static int32
worker_thread(void *dummy
)
409 int worker_slot
= (int)dummy
;
410 apr_allocator_t
*allocator
;
411 apr_bucket_alloc_t
*bucket_alloc
;
412 apr_status_t rv
= APR_EINIT
;
413 int last_poll_idx
= 0;
415 int requests_this_child
= 0;
416 apr_pollset_t
*pollset
= NULL
;
417 ap_listen_rec
*lr
= NULL
;
418 ap_sb_handle_t
*sbh
= NULL
;
420 /* each worker thread is in control of its own destiny...*/
421 int this_worker_should_exit
= 0;
422 /* We have 2 pools that we create/use throughout the lifetime of this
423 * worker. The first and longest lived is the pworker pool. From
424 * this we create the ptrans pool, the lifetime of which is the same
425 * as each connection and is reset prior to each attempt to
426 * process a connection.
428 apr_pool_t
*ptrans
= NULL
;
429 apr_pool_t
*pworker
= NULL
;
431 mpm_state
= AP_MPMQ_STARTING
; /* for benefit of any hooks that run as this
435 on_exit_thread(check_restart
, (void*)worker_slot
);
437 /* block the signals for this thread only if we're not running as a
441 sigfillset(&sig_mask
);
442 sigprocmask(SIG_BLOCK
, &sig_mask
, NULL
);
445 /* Each worker thread is fully in control of it's destinay and so
446 * to allow each thread to handle the lifetime of it's own resources
447 * we create and use a subcontext for every thread.
448 * The subcontext is a child of the pconf pool.
450 apr_allocator_create(&allocator
);
451 apr_allocator_max_free_set(allocator
, ap_max_mem_free
);
452 apr_pool_create_ex(&pworker
, pconf
, NULL
, allocator
);
453 apr_allocator_owner_set(allocator
, pworker
);
455 apr_pool_create(&ptrans
, pworker
);
456 apr_pool_tag(ptrans
, "transaction");
458 ap_create_sb_handle(&sbh
, pworker
, 0, worker_slot
);
459 (void) ap_update_child_status(sbh
, SERVER_READY
, (request_rec
*) NULL
);
461 /* We add an extra socket here as we add the udp_sock we use for signalling
462 * death. This gets added after the others.
464 apr_pollset_create(&pollset
, num_listening_sockets
+ 1, pworker
, 0);
466 for (lr
= ap_listeners
, i
= num_listening_sockets
; i
--; lr
= lr
->next
) {
467 apr_pollfd_t pfd
= {0};
469 pfd
.desc_type
= APR_POLL_SOCKET
;
471 pfd
.reqevents
= APR_POLLIN
;
472 pfd
.client_data
= lr
;
474 apr_pollset_add(pollset
, &pfd
);
477 apr_pollfd_t pfd
= {0};
479 pfd
.desc_type
= APR_POLL_SOCKET
;
480 pfd
.desc
.s
= udp_sock
;
481 pfd
.reqevents
= APR_POLLIN
;
483 apr_pollset_add(pollset
, &pfd
);
486 bucket_alloc
= apr_bucket_alloc_create(pworker
);
488 mpm_state
= AP_MPMQ_RUNNING
;
490 while (!this_worker_should_exit
) {
491 conn_rec
*current_conn
;
494 /* (Re)initialize this child to a pre-connection state. */
495 apr_pool_clear(ptrans
);
497 if ((ap_max_requests_per_thread
> 0
498 && requests_this_child
++ >= ap_max_requests_per_thread
))
499 clean_child_exit(0, worker_slot
);
501 (void) ap_update_child_status(sbh
, SERVER_READY
, (request_rec
*) NULL
);
503 apr_thread_mutex_lock(accept_mutex
);
505 /* We always (presently) have at least 2 sockets we listen on, so
506 * we don't have the ability for a fast path for a single socket
507 * as some MPM's allow :(
510 apr_int32_t numdesc
= 0;
511 const apr_pollfd_t
*pdesc
= NULL
;
513 rv
= apr_pollset_poll(pollset
, -1, &numdesc
, &pdesc
);
514 if (rv
!= APR_SUCCESS
) {
515 if (APR_STATUS_IS_EINTR(rv
)) {
516 if (one_process
&& shutdown_pending
)
520 ap_log_error(APLOG_MARK
, APLOG_ERR
, rv
,
521 ap_server_conf
, "apr_pollset_poll: (listen)");
522 clean_child_exit(1, worker_slot
);
524 /* We can always use pdesc[0], but sockets at position N
525 * could end up completely starved of attention in a very
526 * busy server. Therefore, we round-robin across the
527 * returned set of descriptors. While it is possible that
528 * the returned set of descriptors might flip around and
529 * continue to starve some sockets, we happen to know the
530 * internal pollset implementation retains ordering
531 * stability of the sockets. Thus, the round-robin should
532 * ensure that a socket will eventually be serviced.
534 if (last_poll_idx
>= numdesc
)
537 /* Grab a listener record from the client_data of the poll
538 * descriptor, and advance our saved index to round-robin
541 * ### hmm... this descriptor might have POLLERR rather
545 lr
= pdesc
[last_poll_idx
++].client_data
;
547 /* The only socket we add without client_data is the first, the UDP socket
548 * we listen on for restart signals. If we've therefore gotten a hit on that
549 * listener lr will be NULL here and we know we've been told to die.
550 * Before we jump to the end of the while loop with this_worker_should_exit
551 * set to 1 (causing us to exit normally we hope) we release the accept_mutex
552 * as we want every thread to go through this same routine :)
553 * Bit of a hack, but compared to what I had before...
556 this_worker_should_exit
= 1;
557 apr_thread_mutex_unlock(accept_mutex
);
558 goto got_a_black_spot
;
563 /* Run beos_accept to accept the connection and set things up to
564 * allow us to process it. We always release the accept_lock here,
565 * even if we failt o accept as otherwise we'll starve other workers
566 * which would be bad.
568 rv
= beos_accept(&csd
, lr
, ptrans
);
569 apr_thread_mutex_unlock(accept_mutex
);
571 if (rv
== APR_EGENERAL
) {
572 /* resource shortage or should-not-occur occured */
573 clean_child_exit(1, worker_slot
);
574 } else if (rv
!= APR_SUCCESS
)
577 current_conn
= ap_run_create_connection(ptrans
, ap_server_conf
, csd
, worker_slot
, sbh
, bucket_alloc
);
579 ap_process_connection(current_conn
, csd
);
580 ap_lingering_close(current_conn
);
583 if (ap_my_generation
!=
584 ap_scoreboard_image
->global
->running_generation
) { /* restart? */
585 /* yeah, this could be non-graceful restart, in which case the
586 * parent will kill us soon enough, but why bother checking?
588 this_worker_should_exit
= 1;
593 apr_pool_destroy(ptrans
);
594 apr_pool_destroy(pworker
);
596 clean_child_exit(0, worker_slot
);
599 static int make_worker(int slot
)
603 if (slot
+ 1 > ap_max_child_assigned
)
604 ap_max_child_assigned
= slot
+ 1;
606 (void) ap_update_child_status_from_indexes(0, slot
, SERVER_STARTING
, (request_rec
*)NULL
);
610 ap_scoreboard_image
->parent
[0].pid
= getpid();
611 ap_scoreboard_image
->servers
[0][slot
].tid
= find_thread(NULL
);
615 tid
= spawn_thread(worker_thread
, "apache_worker", B_NORMAL_PRIORITY
,
617 if (tid
< B_NO_ERROR
) {
618 ap_log_error(APLOG_MARK
, APLOG_ERR
, errno
, NULL
,
619 "spawn_thread: Unable to start a new thread");
620 /* In case system resources are maxed out, we don't want
621 * Apache running away with the CPU trying to fork over and
622 * over and over again.
624 (void) ap_update_child_status_from_indexes(0, slot
, SERVER_DEAD
,
632 ap_scoreboard_image
->servers
[0][slot
].tid
= tid
;
636 /* When a worker thread exits, this function is called. If we are not in
637 * a shutdown situation then we restart the worker in the slot that was
640 static void check_restart(void *data
)
642 if (!restart_pending
&& !shutdown_pending
) {
643 int slot
= (int)data
;
645 ap_log_error(APLOG_MARK
, APLOG_INFO
, 0, NULL
,
646 "spawning a new worker thread in slot %d", slot
);
650 /* Start number_to_start children. This is used to start both the
651 * initial 'pool' of workers but also to replace existing workers who
652 * have reached the end of their time. It walks through the scoreboard to find
653 * an empty slot and starts the worker thread in that slot.
655 static void startup_threads(int number_to_start
)
659 for (i
= 0; number_to_start
&& i
< ap_thread_limit
; ++i
) {
660 if (ap_scoreboard_image
->servers
[0][i
].tid
)
663 if (make_worker(i
) < 0)
672 * spawn_rate is the number of children that will be spawned on the
673 * next maintenance cycle if there aren't enough idle servers. It is
674 * doubled up to MAX_SPAWN_RATE, and reset only when a cycle goes by
675 * without the need to spawn.
677 static int spawn_rate
= 1;
678 #ifndef MAX_SPAWN_RATE
679 #define MAX_SPAWN_RATE (32)
681 static int hold_off_on_exponential_spawning
;
683 static void perform_idle_server_maintenance(void)
687 int free_slots
[MAX_SPAWN_RATE
];
688 int last_non_dead
= -1;
690 /* initialize the free_list */
693 for (i
= 0; i
< ap_thread_limit
; ++i
) {
694 if (ap_scoreboard_image
->servers
[0][i
].tid
== 0) {
695 if (free_length
< spawn_rate
) {
696 free_slots
[free_length
] = i
;
704 if (i
>= ap_max_child_assigned
&& free_length
>= spawn_rate
) {
708 ap_max_child_assigned
= last_non_dead
+ 1;
710 if (free_length
> 0) {
711 for (i
= 0; i
< free_length
; ++i
) {
712 make_worker(free_slots
[i
]);
714 /* the next time around we want to spawn twice as many if this
715 * wasn't good enough, but not if we've just done a graceful
717 if (hold_off_on_exponential_spawning
) {
718 --hold_off_on_exponential_spawning
;
719 } else if (spawn_rate
< MAX_SPAWN_RATE
) {
727 static void server_main_loop(int remaining_threads_to_start
)
730 apr_exit_why_e exitwhy
;
735 while (!restart_pending
&& !shutdown_pending
) {
737 ap_wait_or_timeout(&exitwhy
, &status
, &pid
, pconf
);
740 if (ap_process_child_status(&pid
, exitwhy
, status
) == APEXIT_CHILDFATAL
) {
741 shutdown_pending
= 1;
745 /* non-fatal death... note that it's gone in the scoreboard. */
747 for (i
= 0; i
< ap_max_child_assigned
; ++i
) {
748 if (ap_scoreboard_image
->servers
[0][i
].tid
== pid
.pid
) {
753 if (child_slot
>= 0) {
754 ap_scoreboard_image
->servers
[0][child_slot
].tid
= 0;
755 (void) ap_update_child_status_from_indexes(0, child_slot
,
759 if (remaining_threads_to_start
760 && child_slot
< ap_thread_limit
) {
761 /* we're still doing a 1-for-1 replacement of dead
762 * children with new children
764 make_worker(child_slot
);
765 --remaining_threads_to_start
;
768 #if APR_HAS_OTHER_CHILD
770 else if (apr_proc_other_child_refresh(&pid, status) == 0) {
774 else if (is_graceful
) {
775 /* Great, we've probably just lost a slot in the
776 * scoreboard. Somehow we don't know about this
779 ap_log_error(APLOG_MARK
, APLOG_WARNING
, 0, ap_server_conf
,
780 "long lost child came home! (pid %ld)", pid
.pid
);
783 /* Don't perform idle maintenance when a child dies,
784 * only do it when there's a timeout. Remember only a
785 * finite number of children can die, and it's pretty
786 * pathological for a lot to die suddenly.
790 else if (remaining_threads_to_start
) {
791 /* we hit a 1 second timeout in which none of the previous
792 * generation of children needed to be reaped... so assume
793 * they're all done, and pick up the slack if any is left.
795 startup_threads(remaining_threads_to_start
);
796 remaining_threads_to_start
= 0;
797 /* In any event we really shouldn't do the code below because
798 * few of the servers we just started are in the IDLE state
799 * yet, so we'd mistakenly create an extra server.
803 perform_idle_server_maintenance();
807 /* This is called to not only setup and run for the initial time, but also
808 * when we've asked for a restart. This means it must be able to handle both
809 * situations. It also means that when we exit here we should have tidied
810 * up after ourselves fully.
812 int ap_mpm_run(apr_pool_t
*_pconf
, apr_pool_t
*plog
, server_rec
*s
)
814 int remaining_threads_to_start
, i
,j
;
820 /* Increase the available pool of fd's. This code from
821 * Joe Kloss <joek@be.com>
823 if( FD_SETSIZE
> 128 && (i
= _kset_fd_limit_( 128 )) < 0 ){
824 ap_log_error(APLOG_MARK
, APLOG_ERR
, i
, s
,
825 "could not set FD_SETSIZE (_kset_fd_limit_ failed)");
828 /* BeOS R5 doesn't support pipes on select() calls, so we use a
829 * UDP socket as these are supported in both R5 and BONE. If we only cared
830 * about BONE we'd use a pipe, but there it is.
831 * As we have UDP support in APR, now use the APR functions and check all the
834 if (apr_sockaddr_info_get(&udp_sa
, "127.0.0.1", APR_UNSPEC
, 7772, 0, _pconf
)
836 ap_log_error(APLOG_MARK
, APLOG_ALERT
, errno
, s
,
837 "couldn't create control socket information, shutting down");
840 if (apr_socket_create(&udp_sock
, udp_sa
->family
, SOCK_DGRAM
, 0,
841 _pconf
) != APR_SUCCESS
){
842 ap_log_error(APLOG_MARK
, APLOG_ALERT
, errno
, s
,
843 "couldn't create control socket, shutting down");
846 if (apr_socket_bind(udp_sock
, udp_sa
) != APR_SUCCESS
){
847 ap_log_error(APLOG_MARK
, APLOG_ALERT
, errno
, s
,
848 "couldn't bind UDP socket!");
852 if ((num_listening_sockets
= ap_setup_listeners(ap_server_conf
)) < 1) {
853 ap_log_error(APLOG_MARK
, APLOG_ALERT
, 0, s
,
854 "no listening sockets available, shutting down");
858 ap_log_pid(pconf
, ap_pid_fname
);
861 * Create our locks...
865 * used to lock around select so we only have one thread
866 * in select at a time
868 rv
= apr_thread_mutex_create(&accept_mutex
, 0, pconf
);
869 if (rv
!= APR_SUCCESS
) {
870 /* tsch tsch, can't have more than one thread in the accept loop
871 at a time so we need to fall on our sword... */
872 ap_log_error(APLOG_MARK
, APLOG_EMERG
, rv
, s
,
873 "Couldn't create accept lock");
878 * Startup/shutdown...
882 /* setup the scoreboard shared memory */
883 if (ap_run_pre_mpm(s
->process
->pool
, SB_SHARED
) != OK
) {
887 for (i
= 0; i
< HARD_SERVER_LIMIT
; i
++) {
888 ap_scoreboard_image
->parent
[i
].pid
= 0;
889 for (j
= 0;j
< HARD_THREAD_LIMIT
; j
++)
890 ap_scoreboard_image
->servers
[i
][j
].tid
= 0;
894 if (HARD_SERVER_LIMIT
== 1)
895 ap_scoreboard_image
->parent
[0].pid
= getpid();
899 apr_pool_create(&pmain
, pconf
);
900 ap_run_child_init(pmain
, ap_server_conf
);
902 /* Sanity checks to avoid thrashing... */
903 if (max_spare_threads
< min_spare_threads
)
904 max_spare_threads
= min_spare_threads
;
906 /* If we're doing a graceful_restart then we're going to see a lot
907 * of threads exiting immediately when we get into the main loop
908 * below (because we just sent them AP_SIG_GRACEFUL). This happens
909 * pretty rapidly... and for each one that exits we'll start a new one
910 * until we reach at least threads_min_free. But we may be permitted to
911 * start more than that, so we'll just keep track of how many we're
912 * supposed to start up without the 1 second penalty between each fork.
914 remaining_threads_to_start
= ap_threads_to_start
;
915 /* sanity check on the number to start... */
916 if (remaining_threads_to_start
> ap_thread_limit
) {
917 remaining_threads_to_start
= ap_thread_limit
;
920 /* If we're doing the single process thing or we're in a graceful_restart
921 * then we don't start threads here.
922 * if we're in one_process mode we don't want to start threads
925 if (!is_graceful
&& !one_process
) {
926 startup_threads(remaining_threads_to_start
);
927 remaining_threads_to_start
= 0;
929 /* give the system some time to recover before kicking into
930 * exponential mode */
931 hold_off_on_exponential_spawning
= 10;
935 * record that we've entered the world !
937 ap_log_error(APLOG_MARK
, APLOG_NOTICE
, 0, ap_server_conf
,
938 "%s configured -- resuming normal operations",
939 ap_get_server_description());
941 ap_log_error(APLOG_MARK
, APLOG_INFO
, 0, ap_server_conf
,
942 "Server built: %s", ap_get_server_built());
944 restart_pending
= shutdown_pending
= 0;
946 mpm_state
= AP_MPMQ_RUNNING
;
948 /* We sit in the server_main_loop() until we somehow manage to exit. When
949 * we do, we need to kill the workers we have, so we start by using the
950 * tell_workers_to_exit() function, but as it sometimes takes a short while
951 * to accomplish this we have a pause builtin to allow them the chance to
955 server_main_loop(remaining_threads_to_start
);
956 tell_workers_to_exit();
959 worker_thread((void*)0);
961 mpm_state
= AP_MPMQ_STOPPING
;
963 /* close the UDP socket we've been using... */
964 apr_socket_close(udp_sock
);
966 if ((one_process
|| shutdown_pending
) && !child_fatal
) {
967 const char *pidfile
= NULL
;
968 pidfile
= ap_server_root_relative (pconf
, ap_pid_fname
);
969 if ( pidfile
!= NULL
&& unlink(pidfile
) == 0)
970 ap_log_error(APLOG_MARK
, APLOG_INFO
, 0, ap_server_conf
,
971 "removed PID file %s (pid=%ld)", pidfile
,
981 * If we get here we're shutting down...
983 if (shutdown_pending
) {
984 /* Time to gracefully shut down:
985 * Kill child processes, tell them to call child_exit, etc...
987 if (beosd_killpg(getpgrp(), SIGTERM
) < 0)
988 ap_log_error(APLOG_MARK
, APLOG_WARNING
, errno
, ap_server_conf
,
991 /* use ap_reclaim_child_processes starting with SIGTERM */
992 ap_reclaim_child_processes(1);
994 if (!child_fatal
) { /* already recorded */
995 /* record the shutdown in the log */
996 ap_log_error(APLOG_MARK
, APLOG_NOTICE
, 0, ap_server_conf
,
997 "caught SIGTERM, shutting down");
1004 /* we've been told to restart */
1005 signal(SIGHUP
, SIG_IGN
);
1008 ap_log_error(APLOG_MARK
, APLOG_NOTICE
, 0, ap_server_conf
,
1009 AP_SIG_GRACEFUL_STRING
" received. Doing graceful restart");
1011 /* Kill 'em all. Since the child acts the same on the parents SIGTERM
1012 * and a SIGHUP, we may as well use the same signal, because some user
1013 * pthreads are stealing signals from us left and right.
1016 ap_reclaim_child_processes(1); /* Start with SIGTERM */
1017 ap_log_error(APLOG_MARK
, APLOG_NOTICE
, 0, ap_server_conf
,
1018 "SIGHUP received. Attempting to restart");
1021 /* just before we go, tidy up the lock we created to prevent a
1022 * potential leak of semaphores...
1024 apr_thread_mutex_destroy(accept_mutex
);
1030 static int beos_pre_config(apr_pool_t
*pconf
, apr_pool_t
*plog
, apr_pool_t
*ptemp
)
1032 static int restart_num
= 0;
1033 int no_detach
, debug
, foreground
;
1036 mpm_state
= AP_MPMQ_STARTING
;
1038 debug
= ap_exists_config_define("DEBUG");
1041 foreground
= one_process
= 1;
1046 one_process
= ap_exists_config_define("ONE_PROCESS");
1047 no_detach
= ap_exists_config_define("NO_DETACH");
1048 foreground
= ap_exists_config_define("FOREGROUND");
1051 /* sigh, want this only the second time around */
1052 if (restart_num
++ == 1) {
1055 if (!one_process
&& !foreground
) {
1056 rv
= apr_proc_detach(no_detach
? APR_PROC_DETACH_FOREGROUND
1057 : APR_PROC_DETACH_DAEMONIZE
);
1058 if (rv
!= APR_SUCCESS
) {
1059 ap_log_error(APLOG_MARK
, APLOG_CRIT
, rv
, NULL
,
1060 "apr_proc_detach failed");
1061 return HTTP_INTERNAL_SERVER_ERROR
;
1065 server_pid
= getpid();
1069 ap_listen_pre_config();
1070 ap_threads_to_start
= DEFAULT_START_THREADS
;
1071 min_spare_threads
= DEFAULT_MIN_FREE_THREADS
;
1072 max_spare_threads
= DEFAULT_MAX_FREE_THREADS
;
1073 ap_thread_limit
= HARD_THREAD_LIMIT
;
1074 ap_pid_fname
= DEFAULT_PIDLOG
;
1075 ap_max_requests_per_thread
= DEFAULT_MAX_REQUESTS_PER_THREAD
;
1076 #ifdef AP_MPM_WANT_SET_MAX_MEM_FREE
1077 ap_max_mem_free
= APR_ALLOCATOR_MAX_FREE_UNLIMITED
;
1080 apr_cpystrn(ap_coredump_dir
, ap_server_root
, sizeof(ap_coredump_dir
));
1085 static int beos_check_config(apr_pool_t
*pconf
, apr_pool_t
*plog
,
1086 apr_pool_t
*ptemp
, server_rec
*s
)
1088 static int restart_num
= 0;
1091 /* the reverse of pre_config, we want this only the first time around */
1092 if (restart_num
++ == 0) {
1096 if (ap_thread_limit
> HARD_THREAD_LIMIT
) {
1098 ap_log_error(APLOG_MARK
, APLOG_WARNING
| APLOG_STARTUP
, 0, NULL
,
1099 "WARNING: MaxClients of %d exceeds compile-time "
1100 "limit of", ap_thread_limit
);
1101 ap_log_error(APLOG_MARK
, APLOG_WARNING
| APLOG_STARTUP
, 0, NULL
,
1102 " %d servers, decreasing to %d.",
1103 HARD_THREAD_LIMIT
, HARD_THREAD_LIMIT
);
1104 ap_log_error(APLOG_MARK
, APLOG_WARNING
| APLOG_STARTUP
, 0, NULL
,
1105 " To increase, please see the HARD_THREAD_LIMIT"
1107 ap_log_error(APLOG_MARK
, APLOG_WARNING
| APLOG_STARTUP
, 0, NULL
,
1108 " server/mpm/beos%s.", AP_MPM_HARD_LIMITS_FILE
);
1110 ap_log_error(APLOG_MARK
, APLOG_WARNING
, 0, s
,
1111 "MaxClients of %d exceeds compile-time limit "
1112 "of %d, decreasing to match",
1113 ap_thread_limit
, HARD_THREAD_LIMIT
);
1115 ap_thread_limit
= HARD_THREAD_LIMIT
;
1117 else if (ap_thread_limit
< 1) {
1119 ap_log_error(APLOG_MARK
, APLOG_WARNING
| APLOG_STARTUP
, 0, NULL
,
1120 "WARNING: MaxClients of %d not allowed, "
1121 "increasing to 1.", ap_thread_limit
);
1123 ap_log_error(APLOG_MARK
, APLOG_WARNING
, 0, s
,
1124 "MaxClients of %d not allowed, increasing to 1",
1127 ap_thread_limit
= 1;
1130 /* ap_threads_to_start > ap_thread_limit checked in ap_mpm_run() */
1131 if (ap_threads_to_start
< 0) {
1133 ap_log_error(APLOG_MARK
, APLOG_WARNING
| APLOG_STARTUP
, 0, NULL
,
1134 "WARNING: StartThreads of %d not allowed, "
1135 "increasing to 1.", ap_threads_to_start
);
1137 ap_log_error(APLOG_MARK
, APLOG_WARNING
, 0, s
,
1138 "StartThreads of %d not allowed, increasing to 1",
1139 ap_threads_to_start
);
1141 ap_threads_to_start
= 1;
1144 if (min_spare_threads
< 1) {
1146 ap_log_error(APLOG_MARK
, APLOG_WARNING
| APLOG_STARTUP
, 0, NULL
,
1147 "WARNING: MinSpareThreads of %d not allowed, "
1148 "increasing to 1", min_spare_threads
);
1149 ap_log_error(APLOG_MARK
, APLOG_WARNING
| APLOG_STARTUP
, 0, NULL
,
1150 " to avoid almost certain server failure.");
1151 ap_log_error(APLOG_MARK
, APLOG_WARNING
| APLOG_STARTUP
, 0, NULL
,
1152 " Please read the documentation.");
1154 ap_log_error(APLOG_MARK
, APLOG_WARNING
, 0, s
,
1155 "MinSpareThreads of %d not allowed, increasing to 1",
1158 min_spare_threads
= 1;
1161 /* max_spare_threads < min_spare_threads checked in ap_mpm_run() */
1163 if (ap_max_requests_per_thread
< 0) {
1165 ap_log_error(APLOG_MARK
, APLOG_WARNING
| APLOG_STARTUP
, 0, NULL
,
1166 "WARNING: MaxRequestsPerThread of %d not allowed, "
1167 "increasing to 0,", ap_max_requests_per_thread
);
1168 ap_log_error(APLOG_MARK
, APLOG_WARNING
| APLOG_STARTUP
, 0, NULL
,
1169 " but this may not be what you want.");
1171 ap_log_error(APLOG_MARK
, APLOG_WARNING
, 0, s
,
1172 "MaxRequestsPerThread of %d not allowed, "
1173 "increasing to 0", ap_max_requests_per_thread
);
1175 ap_max_requests_per_thread
= 0;
1181 static void beos_hooks(apr_pool_t
*p
)
1185 ap_hook_pre_config(beos_pre_config
, NULL
, NULL
, APR_HOOK_MIDDLE
);
1186 ap_hook_check_config(beos_check_config
, NULL
, NULL
, APR_HOOK_MIDDLE
);
1189 static const char *set_threads_to_start(cmd_parms
*cmd
, void *dummy
, const char *arg
)
1191 const char *err
= ap_check_cmd_context(cmd
, GLOBAL_ONLY
);
1196 ap_threads_to_start
= atoi(arg
);
1200 static const char *set_min_spare_threads(cmd_parms
*cmd
, void *dummy
, const char *arg
)
1202 const char *err
= ap_check_cmd_context(cmd
, GLOBAL_ONLY
);
1207 min_spare_threads
= atoi(arg
);
1211 static const char *set_max_spare_threads(cmd_parms
*cmd
, void *dummy
, const char *arg
)
1213 const char *err
= ap_check_cmd_context(cmd
, GLOBAL_ONLY
);
1218 max_spare_threads
= atoi(arg
);
1222 static const char *set_threads_limit (cmd_parms
*cmd
, void *dummy
, const char *arg
)
1224 const char *err
= ap_check_cmd_context(cmd
, GLOBAL_ONLY
);
1229 ap_thread_limit
= atoi(arg
);
1233 static const char *set_max_requests_per_thread (cmd_parms
*cmd
, void *dummy
, const char *arg
)
1235 const char *err
= ap_check_cmd_context(cmd
, GLOBAL_ONLY
);
1240 ap_max_requests_per_thread
= atoi(arg
);
1244 static const command_rec beos_cmds
[] = {
1245 BEOS_DAEMON_COMMANDS
,
1247 AP_INIT_TAKE1( "StartThreads", set_threads_to_start
, NULL
, RSRC_CONF
,
1248 "Number of threads to launch at server startup"),
1249 AP_INIT_TAKE1( "MinSpareThreads", set_min_spare_threads
, NULL
, RSRC_CONF
,
1250 "Minimum number of idle children, to handle request spikes"),
1251 AP_INIT_TAKE1( "MaxSpareThreads", set_max_spare_threads
, NULL
, RSRC_CONF
,
1252 "Maximum number of idle children" ),
1253 AP_INIT_TAKE1( "MaxClients", set_threads_limit
, NULL
, RSRC_CONF
,
1254 "Maximum number of children alive at the same time (max threads)" ),
1255 AP_INIT_TAKE1( "MaxRequestsPerThread", set_max_requests_per_thread
, NULL
, RSRC_CONF
,
1256 "Maximum number of requests served by a thread" ),
1260 module AP_MODULE_DECLARE_DATA mpm_beos_module
= {
1262 NULL
, /* hook to run before apache parses args */
1263 NULL
, /* create per-directory config structure */
1264 NULL
, /* merge per-directory config structures */
1265 NULL
, /* create per-server config structure */
1266 NULL
, /* merge per-server config structures */
1267 beos_cmds
, /* command apr_table_t */
1268 beos_hooks
/* register_hooks */