1 /* ====================================================================
2 * The Apache Software License, Version 1.1
4 * Copyright (c) 2000 The Apache Software Foundation. All rights
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
19 * 3. The end-user documentation included with the redistribution,
20 * if any, must include the following acknowledgment:
21 * "This product includes software developed by the
22 * Apache Software Foundation (http://www.apache.org/)."
23 * Alternately, this acknowledgment may appear in the software itself,
24 * if and wherever such third-party acknowledgments normally appear.
26 * 4. The names "Apache" and "Apache Software Foundation" must
27 * not be used to endorse or promote products derived from this
28 * software without prior written permission. For written
29 * permission, please contact apache@apache.org.
31 * 5. Products derived from this software may not be called "Apache",
32 * nor may "Apache" appear in their name, without prior written
33 * permission of the Apache Software Foundation.
35 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
36 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
37 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
38 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
39 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
42 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
43 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
44 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
45 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47 * ====================================================================
49 * This software consists of voluntary contributions made by many
50 * individuals on behalf of the Apache Software Foundation. For more
51 * information on the Apache Software Foundation, please see
52 * <http://www.apache.org/>.
54 * Portions of this software are based upon public domain software
55 * originally written at the National Center for Supercomputing Applications,
56 * University of Illinois, Urbana-Champaign.
60 * httpd.c: simple http daemon for answering WWW file requests
63 * 03-21-93 Rob McCool wrote original code (up to NCSA HTTPd 1.3)
66 * changed server number for child-alone processes to 0 and changed name
70 * Added numerous speed hacks proposed by Robert S. Thau (rst@ai.mit.edu)
71 * including set group before fork, and call gettime before to fork
72 * to set up libraries.
75 * Brandon's code snarfed from NCSA 1.4, but tinkered to work with the
76 * Apache server, and also to have child processes do accept() directly.
79 * Extensive rework for Apache.
82 /* TODO: this is a cobbled together prefork MPM example... it should mostly
83 * TODO: behave like apache-1.3... here's a short list of things I think
84 * TODO: need cleaning up still:
85 * TODO: - clean up scoreboard stuff when we figure out how to do it in 2.0
90 #include "ap_config.h"
91 #include "apr_portable.h"
92 #include "apr_strings.h"
93 #include "apr_thread_proc.h"
95 #include "mpm_default.h"
96 #include "mpm_status.h"
97 #include "http_main.h"
99 #include "http_config.h"
100 #include "http_core.h" /* for get_remote_host */
101 #include "http_connection.h"
102 #include "scoreboard.h"
105 #include "mpm_common.h"
107 #include "ap_listen.h"
109 #ifdef HAVE_SYS_TYPES_H
110 #include <sys/types.h>
112 #ifdef HAVE_SYS_WAIT_H
113 #include <sys/wait.h>
115 #ifdef HAVE_SYS_SOCKET_H
116 #include <sys/socket.h>
121 #ifdef HAVE_NETINET_TCP_H
122 #include <netinet/tcp.h> /* for TCP_NODELAY */
125 #ifdef HAVE_BSTRING_H
126 #include <bstring.h> /* for IRIX, FD_SET calls bzero() */
128 #ifdef HAVE_STRINGS_H
135 #include <sys/times.h>
139 static int ap_max_requests_per_child=0;
140 static const char *ap_pid_fname=NULL;
141 static apr_lock_t *accept_lock;
142 static const char *ap_scoreboard_fname=NULL;
143 static const char *ap_lock_fname;
144 static int ap_daemons_to_start=0;
145 static int ap_daemons_min_free=0;
146 static int ap_daemons_max_free=0;
147 static int ap_daemons_limit=0;
148 static time_t ap_restart_time=0;
149 static int ap_extended_status = 0;
150 static int maintain_connection_status = 1;
153 * The max child slot ever assigned, preserved across restarts. Necessary
154 * to deal with MaxClients changes across SIGUSR1 restarts. We use this
155 * value to optimize routines that have to scan the entire scoreboard.
157 int ap_max_daemons_limit = -1;
158 server_rec *ap_server_conf;
160 char ap_coredump_dir[MAX_STRING_LEN];
162 /* *Non*-shared http_main globals... */
164 static apr_socket_t *sd;
165 static fd_set listenfds;
166 static int listenmaxfd;
168 /* one_process --- debugging mode variable; can be set from the command line
169 * with the -X flag. If set, this gets you the child_main loop running
170 * in the process which originally started up (no detach, no make_child),
171 * which is a pretty nice debugging environment. (You'll get a SIGHUP
172 * early in standalone_main; just continue through. This is the server
173 * trying to kill off any child processes which it might have lying
174 * around --- Apache doesn't keep track of their pids, it just sends
175 * SIGHUP to the process group, ignoring it in the root process.
176 * Continue through and you'll be fine.).
179 static int one_process = 0;
181 static apr_pool_t *pconf; /* Pool for config stuff */
182 static apr_pool_t *pchild; /* Pool for httpd child stuff */
184 int ap_my_pid; /* it seems silly to call getpid all the time */
186 static int my_child_num;
191 char tpf_server_name[INETD_SERVNAME_LENGTH+1];
194 API_VAR_EXPORT scoreboard *ap_scoreboard_image = NULL;
195 static new_scoreboard *ap_new_scoreboard_image = NULL;
199 * change directory for gprof to plop the gmon.out file
200 * configure in httpd.conf:
201 * GprofDir logs/ -> $ServerRoot/logs/gmon.out
202 * GprofDir logs/% -> $ServerRoot/logs/gprof.$pid/gmon.out
204 static void chdir_for_gprof(void)
206 core_server_config *sconf =
207 ap_get_module_config(ap_server_conf->module_config, &core_module);
208 char *dir = sconf->gprof_dir;
212 int len = strlen(sconf->gprof_dir) - 1;
213 if(*(dir + len) == '%') {
215 apr_snprintf(buf, sizeof(buf), "%sgprof.%d", dir, (int)getpid());
217 dir = ap_server_root_relative(pconf, buf[0] ? buf : dir);
218 if(mkdir(dir, 0755) < 0 && errno != EEXIST) {
219 ap_log_error(APLOG_MARK, APLOG_ERR, errno, ap_server_conf,
220 "gprof: error creating directory %s", dir);
224 dir = ap_server_root_relative(pconf, "logs");
230 #define chdir_for_gprof()
233 /* XXX - I don't know if TPF will ever use this module or not, so leave
234 * the ap_check_signals calls in but disable them - manoj */
235 #define ap_check_signals()
237 /* a clean exit from a child with proper cleanup */
238 static void clean_child_exit(int code) __attribute__ ((noreturn));
239 static void clean_child_exit(int code)
242 apr_destroy_pool(pchild);
248 static void expand_lock_fname(apr_pool_t *p)
250 /* XXXX possibly bogus cast */
251 ap_lock_fname = apr_psprintf(p, "%s.%lu",
252 ap_server_root_relative(p, ap_lock_fname), (unsigned long)getpid());
255 /* Initialize mutex lock.
256 * Done by each child at its birth
258 static void accept_mutex_child_init(apr_pool_t *p)
262 rv = apr_child_init_lock(&accept_lock, ap_lock_fname, p);
264 ap_log_error(APLOG_MARK, APLOG_EMERG, rv, NULL,
265 "couldn't do child init for accept mutex");
266 clean_child_exit(APEXIT_CHILDINIT);
270 /* Initialize mutex lock.
271 * Must be safe to call this on a restart.
273 static void accept_mutex_init(apr_pool_t *p)
277 expand_lock_fname(p);
278 rv = apr_create_lock(&accept_lock, APR_MUTEX, APR_CROSS_PROCESS, ap_lock_fname, p);
280 ap_log_error(APLOG_MARK, APLOG_EMERG, rv, NULL, "couldn't create accept mutex");
285 static void accept_mutex_on(void)
287 apr_status_t rv = apr_lock(accept_lock);
291 static void accept_mutex_off(void)
293 apr_status_t rv = apr_unlock(accept_lock);
297 /* On some architectures it's safe to do unserialized accept()s in the single
298 * Listen case. But it's never safe to do it in the case where there's
299 * multiple Listen statements. Define SINGLE_LISTEN_UNSERIALIZED_ACCEPT
300 * when it's safe in the single Listen case.
302 #ifdef SINGLE_LISTEN_UNSERIALIZED_ACCEPT
303 #define SAFE_ACCEPT(stmt) do {if (ap_listeners->next) {stmt;}} while(0)
305 #define SAFE_ACCEPT(stmt) do {stmt;} while(0)
308 #if APR_HAS_SHARED_MEMORY
309 #include "apr_shmem.h"
311 static apr_shmem_t *scoreboard_shm = NULL;
313 static apr_status_t cleanup_shared_mem(void *d)
315 apr_shm_free(scoreboard_shm, ap_scoreboard_image);
316 ap_scoreboard_image = NULL;
317 apr_shm_destroy(scoreboard_shm);
321 static void setup_shared_mem(apr_pool_t *p)
326 fname = ap_server_root_relative(p, ap_scoreboard_fname);
327 if (apr_shm_init(&scoreboard_shm, SCOREBOARD_SIZE + NEW_SCOREBOARD_SIZE + 40, fname, p) != APR_SUCCESS) {
328 apr_snprintf(buf, sizeof(buf), "%s: could not open(create) scoreboard",
333 ap_scoreboard_image = apr_shm_malloc(scoreboard_shm, SCOREBOARD_SIZE);
334 ap_new_scoreboard_image = apr_shm_malloc(scoreboard_shm, NEW_SCOREBOARD_SIZE);
335 if (ap_scoreboard_image == NULL) {
336 apr_snprintf(buf, sizeof(buf), "%s: cannot allocate scoreboard",
339 apr_shm_destroy(scoreboard_shm);
342 apr_register_cleanup(p, NULL, cleanup_shared_mem, apr_null_cleanup);
343 ap_scoreboard_image->global.running_generation = 0;
346 static void reopen_scoreboard(apr_pool_t *p)
351 /* Called by parent process */
352 static void reinit_scoreboard(apr_pool_t *p)
355 if (ap_scoreboard_image)
356 running_gen = ap_scoreboard_image->global.running_generation;
358 if (ap_scoreboard_image == NULL) {
361 memset(ap_scoreboard_image, 0, SCOREBOARD_SIZE);
362 ap_scoreboard_image->global.running_generation = running_gen;
366 /* Routines called to deal with the scoreboard image
367 * --- note that we do *not* need write locks, since update_child_status
368 * only updates a *single* record in place, and only one process writes to
369 * a given scoreboard slot at a time (either the child process owning that
370 * slot, or the parent, noting that the child has died).
372 * As a final note --- setting the score entry to getpid() is always safe,
373 * since when the parent is writing an entry, it's only noting SERVER_DEAD
376 apr_inline void ap_sync_scoreboard_image(void)
378 #ifdef SCOREBOARD_FILE
379 lseek(scoreboard_fd, 0L, 0);
380 force_read(scoreboard_fd, ap_scoreboard_image, sizeof(*ap_scoreboard_image))
385 API_EXPORT(int) ap_exists_scoreboard_image(void)
387 return (ap_scoreboard_image ? 1 : 0);
390 API_EXPORT(int) ap_get_max_daemons(void)
392 return ap_max_daemons_limit;
395 static apr_inline void put_scoreboard_info(int child_num,
396 short_score *new_score_rec)
398 #ifdef SCOREBOARD_FILE
399 lseek(scoreboard_fd, (long) child_num * sizeof(short_score), 0);
400 force_write(scoreboard_fd, new_score_rec, sizeof(short_score));
404 int ap_update_child_status(int child_num, int status, request_rec *r)
414 ss = &ap_scoreboard_image->servers[child_num];
415 old_status = ss->status;
418 if (ap_extended_status) {
419 if (status == SERVER_READY || status == SERVER_DEAD) {
421 * Reset individual counters
423 if (status == SERVER_DEAD) {
424 ss->my_access_count = 0L;
425 ss->my_bytes_served = 0L;
427 ss->conn_count = (unsigned short) 0;
428 ss->conn_bytes = (unsigned long) 0;
431 conn_rec *c = r->connection;
432 apr_cpystrn(ss->client, ap_get_remote_host(c, r->per_dir_config,
433 REMOTE_NOLOOKUP), sizeof(ss->client));
434 if (r->the_request == NULL) {
435 apr_cpystrn(ss->request, "NULL", sizeof(ss->request));
436 } else if (r->parsed_uri.password == NULL) {
437 apr_cpystrn(ss->request, r->the_request, sizeof(ss->request));
439 /* Don't reveal the password in the server-status view */
440 apr_cpystrn(ss->request, apr_pstrcat(r->pool, r->method, " ",
441 ap_unparse_uri_components(r->pool, &r->parsed_uri, UNP_OMITPASSWORD),
442 r->assbackwards ? NULL : " ", r->protocol, NULL),
443 sizeof(ss->request));
445 ss->vhostrec = r->server;
448 if (status == SERVER_STARTING && r == NULL) {
449 /* clean up the slot's vhostrec pointer (maybe re-used)
450 * and mark the slot as belonging to a new generation.
453 ap_scoreboard_image->parent[child_num].generation = ap_my_generation;
454 #ifdef SCOREBOARD_FILE
455 lseek(scoreboard_fd, XtOffsetOf(scoreboard, parent[child_num]), 0);
456 force_write(scoreboard_fd, &ap_scoreboard_image->parent[child_num],
457 sizeof(parent_score));
460 put_scoreboard_info(child_num, ss);
465 static void update_scoreboard_global(void)
467 #ifdef SCOREBOARD_FILE
469 (char *) &ap_scoreboard_image->global -(char *) ap_scoreboard_image, 0);
470 force_write(scoreboard_fd, &ap_scoreboard_image->global,
471 sizeof ap_scoreboard_image->global);
475 void ap_time_process_request(int child_num, int status)
482 ap_sync_scoreboard_image();
483 ss = &ap_scoreboard_image->servers[child_num];
485 if (status == START_PREQUEST) {
486 ss->start_time = apr_now();
488 else if (status == STOP_PREQUEST) {
489 ss->stop_time = apr_now();
492 put_scoreboard_info(child_num, ss);
496 static void increment_counts(int child_num, request_rec *r)
501 ap_sync_scoreboard_image();
502 ss = &ap_scoreboard_image->servers[child_num];
505 ap_bgetopt(r->connection->client, BO_BYTECT, &bs);
511 ss->my_access_count++;
513 ss->bytes_served += (unsigned long) bs;
514 ss->my_bytes_served += (unsigned long) bs;
515 ss->conn_bytes += (unsigned long) bs;
517 put_scoreboard_info(child_num, ss);
521 static int find_child_by_pid(apr_proc_t *pid)
525 for (i = 0; i < ap_max_daemons_limit; ++i)
526 if (ap_scoreboard_image->parent[i].pid == pid->pid)
532 #if defined(NEED_WAITPID)
534 Systems without a real waitpid sometimes lose a child's exit while waiting
535 for another. Search through the scoreboard for missing children.
537 int reap_children(apr_wait_t *status)
541 for (n = 0; n < ap_max_daemons_limit; ++n) {
542 ap_sync_scoreboard_image();
543 if (ap_scoreboard_image->servers[n].status != SERVER_DEAD &&
544 kill((pid = ap_scoreboard_image->parent[n].pid), 0) == -1) {
545 ap_update_child_status(n, SERVER_DEAD, NULL);
546 /* just mark it as having a successful exit status */
547 bzero((char *) status, sizeof(apr_wait_t));
555 /* handle all varieties of core dumping signals */
556 static void sig_coredump(int sig)
558 chdir(ap_coredump_dir);
559 apr_signal(sig, SIG_DFL);
561 /* At this point we've got sig blocked, because we're still inside
562 * the signal handler. When we leave the signal handler it will
563 * be unblocked, and we'll take the signal... and coredump or whatever
564 * is appropriate for this particular Unix. In addition the parent
565 * will see the real signal we received -- whereas if we called
566 * abort() here, the parent would only see SIGABRT.
570 /*****************************************************************
571 * Connection structures and accounting...
574 static void just_die(int sig)
579 static int volatile deferred_die;
580 static int volatile usr1_just_die;
582 static void usr1_handler(int sig)
590 /* volatile just in case */
591 static int volatile shutdown_pending;
592 static int volatile restart_pending;
593 static int volatile is_graceful;
594 ap_generation_t volatile ap_my_generation=0;
596 static void sig_term(int sig)
598 if (shutdown_pending == 1) {
599 /* Um, is this _probably_ not an error, if the user has
600 * tried to do a shutdown twice quickly, so we won't
601 * worry about reporting it.
605 shutdown_pending = 1;
608 static void restart(int sig)
610 if (restart_pending == 1) {
611 /* Probably not an error - don't bother reporting it */
615 if ((is_graceful = (sig == SIGUSR1))) {
616 apr_kill_cleanup(pconf, NULL, cleanup_shared_mem);
620 static void set_signals(void)
622 #ifndef NO_USE_SIGACTION
625 sigemptyset(&sa.sa_mask);
629 sa.sa_handler = sig_coredump;
630 #if defined(SA_ONESHOT)
631 sa.sa_flags = SA_ONESHOT;
632 #elif defined(SA_RESETHAND)
633 sa.sa_flags = SA_RESETHAND;
635 if (sigaction(SIGSEGV, &sa, NULL) < 0)
636 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGSEGV)");
638 if (sigaction(SIGBUS, &sa, NULL) < 0)
639 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGBUS)");
642 if (sigaction(SIGABORT, &sa, NULL) < 0)
643 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGABORT)");
646 if (sigaction(SIGABRT, &sa, NULL) < 0)
647 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGABRT)");
650 if (sigaction(SIGILL, &sa, NULL) < 0)
651 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGILL)");
655 sa.sa_handler = sig_term;
656 if (sigaction(SIGTERM, &sa, NULL) < 0)
657 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGTERM)");
659 if (sigaction(SIGINT, &sa, NULL) < 0)
660 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGINT)");
663 sa.sa_handler = SIG_DFL;
664 if (sigaction(SIGXCPU, &sa, NULL) < 0)
665 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGXCPU)");
668 sa.sa_handler = SIG_DFL;
669 if (sigaction(SIGXFSZ, &sa, NULL) < 0)
670 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGXFSZ)");
673 sa.sa_handler = SIG_IGN;
674 if (sigaction(SIGPIPE, &sa, NULL) < 0)
675 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGPIPE)");
678 /* we want to ignore HUPs and USR1 while we're busy processing one */
679 sigaddset(&sa.sa_mask, SIGHUP);
680 sigaddset(&sa.sa_mask, SIGUSR1);
681 sa.sa_handler = restart;
682 if (sigaction(SIGHUP, &sa, NULL) < 0)
683 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGHUP)");
684 if (sigaction(SIGUSR1, &sa, NULL) < 0)
685 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGUSR1)");
688 apr_signal(SIGSEGV, sig_coredump);
690 apr_signal(SIGBUS, sig_coredump);
693 apr_signal(SIGABORT, sig_coredump);
694 #endif /* SIGABORT */
696 apr_signal(SIGABRT, sig_coredump);
699 apr_signal(SIGILL, sig_coredump);
702 apr_signal(SIGXCPU, SIG_DFL);
705 apr_signal(SIGXFSZ, SIG_DFL);
709 apr_signal(SIGTERM, sig_term);
711 apr_signal(SIGHUP, restart);
714 apr_signal(SIGUSR1, restart);
717 apr_signal(SIGPIPE, SIG_IGN);
723 /*****************************************************************
724 * Child process main loop.
725 * The following vars are static to avoid getting clobbered by longjmp();
726 * they are really private to child_main.
730 static apr_socket_t *csd;
731 static int requests_this_child;
732 static fd_set main_fds;
734 int ap_graceful_stop_signalled(void)
736 ap_sync_scoreboard_image();
738 ap_scoreboard_image->global.running_generation != ap_my_generation) {
744 static void child_main(int child_num_arg)
747 ap_listen_rec *last_lr;
748 ap_listen_rec *first_lr;
750 conn_rec *current_conn;
752 apr_status_t stat = APR_EINIT;
755 ap_my_pid = getpid();
757 my_child_num = child_num_arg;
758 requests_this_child = 0;
761 /* Get a sub context for global allocations in this child, so that
762 * we can have cleanups occur when the child exits.
764 apr_create_pool(&pchild, pconf);
766 apr_create_pool(&ptrans, pchild);
768 /* needs to be done before we switch UIDs so we have permissions */
769 reopen_scoreboard(pchild);
770 SAFE_ACCEPT(accept_mutex_child_init(pchild));
772 if (unixd_setup_child()) {
773 clean_child_exit(APEXIT_CHILDFATAL);
776 ap_child_init_hook(pchild, ap_server_conf);
778 (void) ap_update_child_status(my_child_num, SERVER_READY, (request_rec *) NULL);
780 apr_signal(SIGHUP, just_die);
781 apr_signal(SIGTERM, just_die);
784 /* Stop Ctrl-C/Ctrl-Break signals going to child processes */
786 unsigned long ulTimes;
787 DosSetSignalExceptionFocus(0, &ulTimes);
791 while (!ap_graceful_stop_signalled()) {
794 /* Prepare to receive a SIGUSR1 due to graceful restart so that
795 * we can exit cleanly.
798 apr_signal(SIGUSR1, usr1_handler);
801 * (Re)initialize this child to a pre-connection state.
806 apr_clear_pool(ptrans);
808 if ((ap_max_requests_per_child > 0
809 && requests_this_child++ >= ap_max_requests_per_child)) {
813 (void) ap_update_child_status(my_child_num, SERVER_READY, (request_rec *) NULL);
816 * Wait for an acceptable connection to arrive.
819 /* Lock around "accept", if necessary */
820 SAFE_ACCEPT(accept_mutex_on());
823 if (ap_listeners->next) {
824 /* more than one socket */
825 memcpy(&main_fds, &listenfds, sizeof(fd_set));
826 srv = select(listenmaxfd + 1, &main_fds, NULL, NULL, NULL);
828 if (srv < 0 && errno != EINTR) {
829 /* Single Unix documents select as returning errnos
830 * EBADF, EINTR, and EINVAL... and in none of those
831 * cases does it make sense to continue. In fact
832 * on Linux 2.0.x we seem to end up with EFAULT
833 * occasionally, and we'd loop forever due to it.
835 ap_log_error(APLOG_MARK, APLOG_ERR, errno, ap_server_conf, "select: (listen)");
842 /* we remember the last_lr we searched last time around so that
843 we don't end up starving any particular listening socket */
844 if (last_lr == NULL) {
854 apr_get_os_sock(&sockdes, lr->sd);
855 if (FD_ISSET(sockdes, &main_fds))
861 while (lr != first_lr);
862 /* FIXME: if we get here, something bad has happened, and we're
863 probably gonna spin forever.
871 /* only one socket, just pretend we did the other stuff */
872 sd = ap_listeners->sd;
875 /* if we accept() something we don't want to die, so we have to
881 /* we didn't get a socket, and we were told to die */
884 stat = apr_accept(&csd, sd, ptrans);
885 if (stat == APR_SUCCESS || stat != APR_EINTR)
889 if (stat == APR_SUCCESS)
890 break; /* We have a socket ready for reading */
893 /* TODO: this accept result handling stuff should be abstracted...
894 * it's already out of date between the various unix mpms
896 /* Our old behaviour here was to continue after accept()
897 * errors. But this leads us into lots of troubles
898 * because most of the errors are quite fatal. For
899 * example, EMFILE can be caused by slow descriptor
900 * leaks (say in a 3rd party module, or libc). It's
901 * foolish for us to continue after an EMFILE. We also
902 * seem to tickle kernel bugs on some platforms which
903 * lead to never-ending loops here. So it seems best
904 * to just exit in most cases.
908 /* EPROTO on certain older kernels really means
909 * ECONNABORTED, so we need to ignore it for them.
910 * See discussion in new-httpd archives nh.9701
913 * Also see nh.9603, search for EPROTO:
914 * There is potentially a bug in Solaris 2.x x<6,
915 * and other boxes that implement tcp sockets in
916 * userland (i.e. on top of STREAMS). On these
917 * systems, EPROTO can actually result in a fatal
918 * loop. See PR#981 for example. It's hard to
919 * handle both uses of EPROTO.
926 /* Linux generates the rest of these, other tcp
927 * stacks (i.e. bsd) tend to hide them behind
928 * getsockopt() interfaces. They occur when
929 * the net goes sour or the client disconnects
930 * after the three-way handshake has been done
931 * in the kernel but before userland has picked
950 * When the network layer has been shut down, there
951 * is not much use in simply exiting: the parent
952 * would simply re-create us (and we'd fail again).
953 * Use the CHILDFATAL code to tear the server down.
954 * @@@ Martin's idea for possible improvement:
955 * A different approach would be to define
956 * a new APEXIT_NETDOWN exit code, the reception
957 * of which would make the parent shutdown all
958 * children, then idle-loop until it detected that
959 * the network is up again, and restart the children.
960 * Ben Hyde noted that temporary ENETDOWN situations
961 * occur in mobile IP.
963 ap_log_error(APLOG_MARK, APLOG_EMERG, stat, ap_server_conf,
964 "apr_accept: giving up.");
965 clean_child_exit(APEXIT_CHILDFATAL);
970 ap_log_error(APLOG_MARK, APLOG_EMERG, stat, ap_server_conf,
971 "offload device inactive");
972 clean_child_exit(APEXIT_CHILDFATAL);
975 ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, ap_server_conf,
976 "select/accept error (%u)", stat);
977 clean_child_exit(APEXIT_CHILDFATAL);
980 ap_log_error(APLOG_MARK, APLOG_ERR, stat, ap_server_conf,
981 "apr_accept: (client socket)");
987 if (ap_graceful_stop_signalled()) {
993 SAFE_ACCEPT(accept_mutex_off()); /* unlock after "accept" */
995 /* We've got a socket, let's at least process one request off the
996 * socket before we accept a graceful restart request. We set
997 * the signal to ignore because we don't want to disturb any
1000 apr_signal(SIGUSR1, SIG_IGN);
1002 * We now have a connection, so set it up with the appropriate
1003 * socket options, file descriptors, and read/write buffers.
1006 apr_get_os_sock(&sockdes, csd);
1008 if (sockdes >= FD_SETSIZE) {
1009 ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, NULL,
1010 "new file descriptor %d is too large; you probably need "
1011 "to rebuild Apache with a larger FD_SETSIZE "
1013 sockdes, FD_SETSIZE);
1014 apr_close_socket(csd);
1019 if (sockdes == 0) /* 0 is invalid socket for TPF */
1023 ap_sock_disable_nagle(csd);
1025 iol = ap_iol_attach_socket(ptrans, csd);
1026 (void) ap_update_child_status(my_child_num, SERVER_BUSY_READ,
1027 (request_rec *) NULL);
1029 conn_io = ap_bcreate(ptrans, B_RDWR);
1031 ap_bpush_iol(conn_io, iol);
1033 current_conn = ap_new_apr_connection(ptrans, ap_server_conf, conn_io, csd,
1036 ap_process_connection(current_conn);
1037 ap_lingering_close(current_conn);
1042 static int make_child(server_rec *s, int slot, time_t now)
1046 if (slot + 1 > ap_max_daemons_limit) {
1047 ap_max_daemons_limit = slot + 1;
1051 apr_signal(SIGHUP, just_die);
1052 apr_signal(SIGINT, just_die);
1054 apr_signal(SIGQUIT, SIG_DFL);
1056 apr_signal(SIGTERM, just_die);
1060 (void) ap_update_child_status(slot, SERVER_STARTING, (request_rec *) NULL);
1064 /* BS2000 requires a "special" version of fork() before a setuid() call */
1065 if ((pid = os_fork(unixd_config.user_name)) == -1) {
1067 if ((pid = os_fork(s, slot)) == -1) {
1069 if ((pid = fork()) == -1) {
1071 ap_log_error(APLOG_MARK, APLOG_ERR, errno, s, "fork: Unable to fork new process");
1073 /* fork didn't succeed. Fix the scoreboard or else
1074 * it will say SERVER_STARTING forever and ever
1076 (void) ap_update_child_status(slot, SERVER_DEAD, (request_rec *) NULL);
1078 /* In case system resources are maxxed out, we don't want
1079 Apache running away with the CPU trying to fork over and
1080 over and over again. */
1087 #ifdef AIX_BIND_PROCESSOR
1088 /* by default AIX binds to a single processor
1089 * this bit unbinds children which will then bind to another cpu
1091 #include <sys/processor.h>
1092 int status = bindprocessor(BINDPROCESS, (int)getpid(),
1093 PROCESSOR_CLASS_ANY);
1095 ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, ap_server_conf,
1096 "processor unbind failed %d", status);
1099 RAISE_SIGSTOP(MAKE_CHILD);
1100 /* Disable the restart signal handlers and enable the just_die stuff.
1101 * Note that since restart() just notes that a restart has been
1102 * requested there's no race condition here.
1104 apr_signal(SIGHUP, just_die);
1105 apr_signal(SIGUSR1, just_die);
1106 apr_signal(SIGTERM, just_die);
1110 ap_scoreboard_image->parent[slot].pid = pid;
1111 #ifdef SCOREBOARD_FILE
1112 lseek(scoreboard_fd, XtOffsetOf(scoreboard, parent[slot]), 0);
1113 force_write(scoreboard_fd, &ap_scoreboard_image->parent[slot],
1114 sizeof(parent_score));
1121 /* start up a bunch of children */
1122 static void startup_children(int number_to_start)
1125 time_t now = time(0);
1127 for (i = 0; number_to_start && i < ap_daemons_limit; ++i) {
1128 if (ap_scoreboard_image->servers[i].status != SERVER_DEAD) {
1131 if (make_child(ap_server_conf, i, now) < 0) {
1140 * idle_spawn_rate is the number of children that will be spawned on the
1141 * next maintenance cycle if there aren't enough idle servers. It is
1142 * doubled up to MAX_SPAWN_RATE, and reset only when a cycle goes by
1143 * without the need to spawn.
1145 static int idle_spawn_rate = 1;
1146 #ifndef MAX_SPAWN_RATE
1147 #define MAX_SPAWN_RATE (32)
1149 static int hold_off_on_exponential_spawning;
1151 static void perform_idle_server_maintenance(void)
1157 time_t now = time(0);
1159 int free_slots[MAX_SPAWN_RATE];
1163 /* initialize the free_list */
1171 ap_sync_scoreboard_image();
1172 for (i = 0; i < ap_daemons_limit; ++i) {
1175 if (i >= ap_max_daemons_limit && free_length == idle_spawn_rate)
1177 ss = &ap_scoreboard_image->servers[i];
1178 status = ss->status;
1179 if (status == SERVER_DEAD) {
1180 /* try to keep children numbers as low as possible */
1181 if (free_length < idle_spawn_rate) {
1182 free_slots[free_length] = i;
1187 /* We consider a starting server as idle because we started it
1188 * at least a cycle ago, and if it still hasn't finished starting
1189 * then we're just going to swamp things worse by forking more.
1190 * So we hopefully won't need to fork more if we count it.
1191 * This depends on the ordering of SERVER_READY and SERVER_STARTING.
1193 if (status <= SERVER_READY) {
1195 /* always kill the highest numbered child if we have to...
1196 * no really well thought out reason ... other than observing
1197 * the server behaviour under linux where lower numbered children
1198 * tend to service more hits (and hence are more likely to have
1199 * their data in cpu caches).
1208 ap_max_daemons_limit = last_non_dead + 1;
1209 if (idle_count > ap_daemons_max_free) {
1210 /* kill off one child... we use SIGUSR1 because that'll cause it to
1211 * shut down gracefully, in case it happened to pick up a request
1212 * while we were counting
1214 kill(ap_scoreboard_image->parent[to_kill].pid, SIGUSR1);
1215 idle_spawn_rate = 1;
1217 else if (idle_count < ap_daemons_min_free) {
1218 /* terminate the free list */
1219 if (free_length == 0) {
1220 /* only report this condition once */
1221 static int reported = 0;
1224 ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, ap_server_conf,
1225 "server reached MaxClients setting, consider"
1226 " raising the MaxClients setting");
1229 idle_spawn_rate = 1;
1232 if (idle_spawn_rate >= 8) {
1233 ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0, ap_server_conf,
1234 "server seems busy, (you may need "
1235 "to increase StartServers, or Min/MaxSpareServers), "
1236 "spawning %d children, there are %d idle, and "
1237 "%d total children", idle_spawn_rate,
1238 idle_count, total_non_dead);
1240 for (i = 0; i < free_length; ++i) {
1242 if(make_child(ap_server_conf, free_slots[i], now) == -1) {
1243 if(free_length == 1) {
1244 shutdown_pending = 1;
1245 ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_EMERG, 0, ap_server_conf,
1246 "No active child processes: shutting down");
1250 make_child(ap_server_conf, free_slots[i], now);
1253 /* the next time around we want to spawn twice as many if this
1254 * wasn't good enough, but not if we've just done a graceful
1256 if (hold_off_on_exponential_spawning) {
1257 --hold_off_on_exponential_spawning;
1259 else if (idle_spawn_rate < MAX_SPAWN_RATE) {
1260 idle_spawn_rate *= 2;
1265 idle_spawn_rate = 1;
1269 static int setup_listeners(server_rec *s)
1274 if (ap_listen_open(s->process, s->port)) {
1275 ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ALERT, 0, s,
1276 "no listening sockets available, shutting down");
1281 FD_ZERO(&listenfds);
1282 for (lr = ap_listeners; lr; lr = lr->next) {
1283 apr_get_os_sock(&sockdes, lr->sd);
1284 FD_SET(sockdes, &listenfds);
1285 if (sockdes > listenmaxfd) {
1286 listenmaxfd = sockdes;
1292 /* Useful to erase the status of children that might be from previous
1294 static void ap_prefork_force_reset_connection_status(long conn_id)
1298 for (i = 0; i < STATUSES_PER_CONNECTION; i++) {
1299 ap_new_scoreboard_image->table[conn_id][i].key[0] = '\0';
1302 void ap_reset_connection_status(long conn_id)
1304 if (maintain_connection_status) {
1305 ap_prefork_force_reset_connection_status(conn_id);
1309 /*****************************************************************
1310 * Executive routines.
1313 int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
1315 int remaining_children_to_start;
1321 ap_log_pid(pconf, ap_pid_fname);
1323 if (setup_listeners(s)) {
1324 /* XXX: hey, what's the right way for the mpm to indicate a fatal error? */
1328 SAFE_ACCEPT(accept_mutex_init(pconf));
1330 reinit_scoreboard(pconf);
1332 #ifdef SCOREBOARD_FILE
1334 ap_scoreboard_fname = ap_server_root_relative(pconf, ap_scoreboard_fname);
1335 ap_note_cleanups_for_fd(pconf, scoreboard_fd);
1341 if (ap_daemons_max_free < ap_daemons_min_free + 1) /* Don't thrash... */
1342 ap_daemons_max_free = ap_daemons_min_free + 1;
1344 /* If we're doing a graceful_restart then we're going to see a lot
1345 * of children exiting immediately when we get into the main loop
1346 * below (because we just sent them SIGUSR1). This happens pretty
1347 * rapidly... and for each one that exits we'll start a new one until
1348 * we reach at least daemons_min_free. But we may be permitted to
1349 * start more than that, so we'll just keep track of how many we're
1350 * supposed to start up without the 1 second penalty between each fork.
1352 remaining_children_to_start = ap_daemons_to_start;
1353 if (remaining_children_to_start > ap_daemons_limit) {
1354 remaining_children_to_start = ap_daemons_limit;
1357 startup_children(remaining_children_to_start);
1358 remaining_children_to_start = 0;
1361 /* give the system some time to recover before kicking into
1362 * exponential mode */
1363 hold_off_on_exponential_spawning = 10;
1366 ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, ap_server_conf,
1367 "%s configured -- resuming normal operations",
1368 ap_get_server_version());
1369 ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0, ap_server_conf,
1370 "Server built: %s", ap_get_server_built());
1371 restart_pending = shutdown_pending = 0;
1373 while (!restart_pending && !shutdown_pending) {
1376 /* this is a memory leak, but I'll fix it later. */
1379 ap_wait_or_timeout(&status, &pid, pconf);
1381 /* XXX: if it takes longer than 1 second for all our children
1382 * to start up and get into IDLE state then we may spawn an
1385 if (pid.pid != -1) {
1386 ap_process_child_status(&pid, status);
1387 /* non-fatal death... note that it's gone in the scoreboard. */
1388 ap_sync_scoreboard_image();
1389 child_slot = find_child_by_pid(&pid);
1390 if (child_slot >= 0) {
1391 ap_prefork_force_reset_connection_status(child_slot);
1392 (void) ap_update_child_status(child_slot, SERVER_DEAD,
1393 (request_rec *) NULL);
1394 if (remaining_children_to_start
1395 && child_slot < ap_daemons_limit) {
1396 /* we're still doing a 1-for-1 replacement of dead
1397 * children with new children
1399 make_child(ap_server_conf, child_slot, time(0));
1400 --remaining_children_to_start;
1402 #if APR_HAS_OTHER_CHILD
1404 else if (apr_reap_other_child(&pid, status) == 0) {
1408 else if (is_graceful) {
1409 /* Great, we've probably just lost a slot in the
1410 * scoreboard. Somehow we don't know about this
1413 ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING,
1415 "long lost child came home! (pid %ld)", (long)pid.pid);
1417 /* Don't perform idle maintenance when a child dies,
1418 * only do it when there's a timeout. Remember only a
1419 * finite number of children can die, and it's pretty
1420 * pathological for a lot to die suddenly.
1424 else if (remaining_children_to_start) {
1425 /* we hit a 1 second timeout in which none of the previous
1426 * generation of children needed to be reaped... so assume
1427 * they're all done, and pick up the slack if any is left.
1429 startup_children(remaining_children_to_start);
1430 remaining_children_to_start = 0;
1431 /* In any event we really shouldn't do the code below because
1432 * few of the servers we just started are in the IDLE state
1433 * yet, so we'd mistakenly create an extra server.
1438 perform_idle_server_maintenance();
1440 shutdown_pending = os_check_server(tpf_server_name);
1446 if (shutdown_pending) {
1447 /* Time to gracefully shut down:
1448 * Kill child processes, tell them to call child_exit, etc...
1450 if (unixd_killpg(getpgrp(), SIGTERM) < 0) {
1451 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "killpg SIGTERM");
1453 ap_reclaim_child_processes(1); /* Start with SIGTERM */
1455 /* cleanup pid file on normal shutdown */
1457 const char *pidfile = NULL;
1458 pidfile = ap_server_root_relative (pconf, ap_pid_fname);
1459 if ( pidfile != NULL && unlink(pidfile) == 0)
1460 ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO,
1462 "removed PID file %s (pid=%ld)",
1463 pidfile, (long)getpid());
1466 ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, ap_server_conf,
1467 "caught SIGTERM, shutting down");
1471 /* we've been told to restart */
1472 apr_signal(SIGHUP, SIG_IGN);
1473 apr_signal(SIGUSR1, SIG_IGN);
1475 /* not worth thinking about */
1479 /* advance to the next generation */
1480 /* XXX: we really need to make sure this new generation number isn't in
1481 * use by any of the children.
1484 ap_scoreboard_image->global.running_generation = ap_my_generation;
1485 update_scoreboard_global();
1488 #ifndef SCOREBOARD_FILE
1491 ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, ap_server_conf,
1492 "SIGUSR1 received. Doing graceful restart");
1494 /* kill off the idle ones */
1495 if (unixd_killpg(getpgrp(), SIGUSR1) < 0) {
1496 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "killpg SIGUSR1");
1498 #ifndef SCOREBOARD_FILE
1499 /* This is mostly for debugging... so that we know what is still
1500 * gracefully dealing with existing request. But we can't really
1501 * do it if we're in a SCOREBOARD_FILE because it'll cause
1502 * corruption too easily.
1504 ap_sync_scoreboard_image();
1505 for (i = 0; i < ap_daemons_limit; ++i) {
1506 if (ap_scoreboard_image->servers[i].status != SERVER_DEAD) {
1507 ap_scoreboard_image->servers[i].status = SERVER_GRACEFUL;
1514 if (unixd_killpg(getpgrp(), SIGHUP) < 0) {
1515 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "killpg SIGHUP");
1517 ap_reclaim_child_processes(0); /* Not when just starting up */
1518 ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, ap_server_conf,
1519 "SIGHUP received. Attempting to restart");
1523 ap_restart_time = time(NULL);
1529 static void prefork_pre_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp)
1531 static int restart_num = 0;
1534 one_process = !!getenv("ONE_PROCESS");
1535 no_detach = !!getenv("NO_DETACH");
1537 /* sigh, want this only the second time around */
1538 if (restart_num++ == 1) {
1541 if (!one_process && !no_detach) {
1545 ap_my_pid = getpid();
1549 ap_listen_pre_config();
1550 ap_daemons_to_start = DEFAULT_START_DAEMON;
1551 ap_daemons_min_free = DEFAULT_MIN_FREE_DAEMON;
1552 ap_daemons_max_free = DEFAULT_MAX_FREE_DAEMON;
1553 ap_daemons_limit = HARD_SERVER_LIMIT;
1554 ap_pid_fname = DEFAULT_PIDLOG;
1555 ap_scoreboard_fname = DEFAULT_SCOREBOARD;
1556 ap_lock_fname = DEFAULT_LOCKFILE;
1557 ap_max_requests_per_child = DEFAULT_MAX_REQUESTS_PER_CHILD;
1558 ap_extended_status = 0;
1560 apr_cpystrn(ap_coredump_dir, ap_server_root, sizeof(ap_coredump_dir));
1563 static void prefork_hooks(void)
1569 /* TODO: set one_process properly */ one_process = 0;
1571 ap_hook_pre_config(prefork_pre_config, NULL, NULL, AP_HOOK_MIDDLE);
1574 static const char *set_pidfile(cmd_parms *cmd, void *dummy, const char *arg)
1576 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
1581 if (cmd->server->is_virtual) {
1582 return "PidFile directive not allowed in <VirtualHost>";
1588 static const char *set_scoreboard(cmd_parms *cmd, void *dummy, const char *arg)
1590 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
1595 ap_scoreboard_fname = arg;
1599 static const char *set_lockfile(cmd_parms *cmd, void *dummy, const char *arg)
1601 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
1606 ap_lock_fname = arg;
1610 static const char *set_daemons_to_start(cmd_parms *cmd, void *dummy, const char *arg)
1612 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
1617 ap_daemons_to_start = atoi(arg);
1621 static const char *set_min_free_servers(cmd_parms *cmd, void *dummy, const char *arg)
1623 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
1628 ap_daemons_min_free = atoi(arg);
1629 if (ap_daemons_min_free <= 0) {
1630 ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
1631 "WARNING: detected MinSpareServers set to non-positive.");
1632 ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
1633 "Resetting to 1 to avoid almost certain Apache failure.");
1634 ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
1635 "Please read the documentation.");
1636 ap_daemons_min_free = 1;
1642 static const char *set_max_free_servers(cmd_parms *cmd, void *dummy, const char *arg)
1644 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
1649 ap_daemons_max_free = atoi(arg);
1653 static const char *set_server_limit (cmd_parms *cmd, void *dummy, const char *arg)
1655 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
1660 ap_daemons_limit = atoi(arg);
1661 if (ap_daemons_limit > HARD_SERVER_LIMIT) {
1662 ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
1663 "WARNING: MaxClients of %d exceeds compile time limit "
1664 "of %d servers,", ap_daemons_limit, HARD_SERVER_LIMIT);
1665 ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
1666 " lowering MaxClients to %d. To increase, please "
1667 "see the", HARD_SERVER_LIMIT);
1668 ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
1669 " HARD_SERVER_LIMIT define in %s.",
1670 AP_MPM_HARD_LIMITS_FILE);
1671 ap_daemons_limit = HARD_SERVER_LIMIT;
1673 else if (ap_daemons_limit < 1) {
1674 ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
1675 "WARNING: Require MaxClients > 0, setting to 1");
1676 ap_daemons_limit = 1;
1681 static const char *set_max_requests(cmd_parms *cmd, void *dummy, const char *arg)
1683 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
1688 ap_max_requests_per_child = atoi(arg);
1693 static const char *set_coredumpdir (cmd_parms *cmd, void *dummy, const char *arg)
1697 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
1702 fname = ap_server_root_relative(cmd->pool, arg);
1703 if ((apr_stat(&finfo, fname, cmd->pool) != APR_SUCCESS) ||
1704 (finfo.filetype != APR_DIR)) {
1705 return apr_pstrcat(cmd->pool, "CoreDumpDirectory ", fname,
1706 " does not exist or is not a directory", NULL);
1708 apr_cpystrn(ap_coredump_dir, fname, sizeof(ap_coredump_dir));
1712 /* Stub functions until this MPM supports the connection status API */
1713 /* Don't mess with the string you get back from this function */
1714 const char *ap_get_connection_status(long conn_id, const char *key)
1717 status_table_entry *ss;
1719 if (!maintain_connection_status) return "";
1720 while (i < STATUSES_PER_CONNECTION) {
1721 ss = &(ap_new_scoreboard_image->table[conn_id][i]);
1722 if (ss->key[0] == '\0') {
1725 if (0 == strcmp(ss->key, key)) {
1733 apr_array_header_t *ap_get_connections(apr_pool_t *p)
1736 apr_array_header_t *connection_list;
1739 connection_list = apr_make_array(p, 0, sizeof(long));
1740 /* We assume that there is a connection iff it has an entry in the status
1741 * table. Connections without any status sound problematic to me, so this
1742 * is probably for the best. - manoj */
1743 for (i = 0; i < ap_max_daemons_limit; i++) {
1744 if (ap_new_scoreboard_image->table[i][0].key[0] != '\0') {
1745 array_slot = apr_push_array(connection_list);
1749 return connection_list;
1752 apr_array_header_t *ap_get_connection_keys(apr_pool_t *p, long conn_id)
1755 status_table_entry *ss;
1756 apr_array_header_t *key_list;
1759 key_list = apr_make_array(p, 0, KEY_LENGTH * sizeof(char));
1760 while (i < STATUSES_PER_CONNECTION) {
1761 ss = &(ap_new_scoreboard_image->table[conn_id][i]);
1762 if (ss->key[0] == '\0') {
1765 array_slot = apr_push_array(key_list);
1766 *array_slot = apr_pstrdup(p, ss->key);
1772 /* Note: no effort is made here to prevent multiple threads from messing with
1773 * a single connection at the same time. ap_update_connection_status should
1774 * only be called by the thread that owns the connection */
1776 void ap_update_connection_status(long conn_id, const char *key,
1780 status_table_entry *ss;
1782 if (!maintain_connection_status) return;
1783 while (i < STATUSES_PER_CONNECTION) {
1784 ss = &(ap_new_scoreboard_image->table[conn_id][i]);
1785 if (ss->key[0] == '\0') {
1788 if (0 == strcmp(ss->key, key)) {
1789 apr_cpystrn(ss->value, value, VALUE_LENGTH);
1794 /* Not found. Add an entry for this value */
1795 if (i >= STATUSES_PER_CONNECTION) {
1796 /* No room. Oh well, not much anyone can do about it. */
1799 apr_cpystrn(ss->key, key, KEY_LENGTH);
1800 apr_cpystrn(ss->value, value, VALUE_LENGTH);
1804 apr_array_header_t *ap_get_status_table(apr_pool_t *p)
1807 apr_array_header_t *server_status;
1808 ap_status_table_row_t *array_slot;
1809 status_table_entry *ss;
1811 server_status = apr_make_array(p, 0, sizeof(ap_status_table_row_t));
1813 /* Go ahead and return what's in the connection status table even if we
1814 * aren't maintaining it. We can at least look at what children from
1815 * previous generations are up to. */
1817 for (i = 0; i < ap_max_daemons_limit; i++) {
1818 if (ap_new_scoreboard_image->table[i][0].key[0] == '\0')
1820 array_slot = apr_push_array(server_status);
1821 array_slot->data = apr_make_table(p, 0);
1822 array_slot->conn_id = i;
1824 for (j = 0; j < STATUSES_PER_CONNECTION; j++) {
1825 ss = &(ap_new_scoreboard_image->table[i][j]);
1826 if (ss->key[0] != '\0') {
1827 apr_table_add(array_slot->data, ss->key, ss->value);
1834 return server_status;
1837 static const command_rec prefork_cmds[] = {
1838 UNIX_DAEMON_COMMANDS
1840 AP_INIT_TAKE1("PidFile", set_pidfile, NULL, RSRC_CONF,
1841 "A file for logging the server process ID"),
1842 AP_INIT_TAKE1("ScoreBoardFile", set_scoreboard, NULL, RSRC_CONF,
1843 "A file for Apache to maintain runtime process management information"),
1844 AP_INIT_TAKE1("LockFile", set_lockfile, NULL, RSRC_CONF,
1845 "The lockfile used when Apache needs to lock the accept() call"),
1846 AP_INIT_TAKE1("StartServers", set_daemons_to_start, NULL, RSRC_CONF,
1847 "Number of child processes launched at server startup"),
1848 AP_INIT_TAKE1("MinSpareServers", set_min_free_servers, NULL, RSRC_CONF,
1849 "Minimum number of idle children, to handle request spikes"),
1850 AP_INIT_TAKE1("MaxSpareServers", set_max_free_servers, NULL, RSRC_CONF,
1851 "Maximum number of idle children"),
1852 AP_INIT_TAKE1("MaxClients", set_server_limit, NULL, RSRC_CONF,
1853 "Maximum number of children alive at the same time"),
1854 AP_INIT_TAKE1("MaxRequestsPerChild", set_max_requests, NULL, RSRC_CONF,
1855 "Maximum number of requests a particular child serves before dying."),
1856 AP_INIT_TAKE1("CoreDumpDirectory", set_coredumpdir, NULL, RSRC_CONF,
1857 "The location of the directory Apache changes to before dumping core"),
1861 module MODULE_VAR_EXPORT mpm_prefork_module = {
1863 NULL, /* hook to run before apache parses args */
1864 NULL, /* create per-directory config structure */
1865 NULL, /* merge per-directory config structures */
1866 NULL, /* create per-server config structure */
1867 NULL, /* merge per-server config structures */
1868 prefork_cmds, /* command apr_table_t */
1869 NULL, /* handlers */
1870 prefork_hooks, /* register hooks */