mpmt_pthread.c revision cb5a017cbad1e36dc501d8afc65636b8c2edf2d8
842ae4bd224140319ae7feec1872b93dfd491143fielding/* ====================================================================
842ae4bd224140319ae7feec1872b93dfd491143fielding * Copyright (c) 1995-1999 The Apache Group. All rights reserved.
842ae4bd224140319ae7feec1872b93dfd491143fielding * Redistribution and use in source and binary forms, with or without
842ae4bd224140319ae7feec1872b93dfd491143fielding * modification, are permitted provided that the following conditions
71da3cca78eea6010f89b139ecadb79e6d213c4fnd * 1. Redistributions of source code must retain the above copyright
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * notice, this list of conditions and the following disclaimer.
71da3cca78eea6010f89b139ecadb79e6d213c4fnd * 2. Redistributions in binary form must reproduce the above copyright
71da3cca78eea6010f89b139ecadb79e6d213c4fnd * notice, this list of conditions and the following disclaimer in
71da3cca78eea6010f89b139ecadb79e6d213c4fnd * the documentation and/or other materials provided with the
71da3cca78eea6010f89b139ecadb79e6d213c4fnd * distribution.
f4c310fd2555c6faca1f980f00b161eadb089023gstein * 3. All advertising materials mentioning features or use of this
f4c310fd2555c6faca1f980f00b161eadb089023gstein * software must display the following acknowledgment:
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * "This product includes software developed by the Apache Group
f4c310fd2555c6faca1f980f00b161eadb089023gstein * for use in the Apache HTTP server project (http://www.apache.org/)."
f4c310fd2555c6faca1f980f00b161eadb089023gstein * 4. The names "Apache Server" and "Apache Group" must not be used to
1b21d7b3d97def358b2e923655edeb16613a1c31gstein * endorse or promote products derived from this software without
952023a04a2f9d51553babd9094fb857f1c97548trawick * prior written permission. For written permission, please contact
1b21d7b3d97def358b2e923655edeb16613a1c31gstein * apache@apache.org.
1b21d7b3d97def358b2e923655edeb16613a1c31gstein * 5. Products derived from this software may not be called "Apache"
1b21d7b3d97def358b2e923655edeb16613a1c31gstein * nor may "Apache" appear in their names without prior written
f4c310fd2555c6faca1f980f00b161eadb089023gstein * permission of the Apache Group.
f4c310fd2555c6faca1f980f00b161eadb089023gstein * 6. Redistributions of any form whatsoever must retain the following
f4c310fd2555c6faca1f980f00b161eadb089023gstein * acknowledgment:
f4c310fd2555c6faca1f980f00b161eadb089023gstein * "This product includes software developed by the Apache Group
f4c310fd2555c6faca1f980f00b161eadb089023gstein * for use in the Apache HTTP server project (http://www.apache.org/)."
f4c310fd2555c6faca1f980f00b161eadb089023gstein * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
99d46a23c6eac800f327b29f8009f7d7da986230trawick * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
99d46a23c6eac800f327b29f8009f7d7da986230trawick * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
f4c310fd2555c6faca1f980f00b161eadb089023gstein * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
f4c310fd2555c6faca1f980f00b161eadb089023gstein * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
f4c310fd2555c6faca1f980f00b161eadb089023gstein * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
f4c310fd2555c6faca1f980f00b161eadb089023gstein * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
f4c310fd2555c6faca1f980f00b161eadb089023gstein * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
f4c310fd2555c6faca1f980f00b161eadb089023gstein * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
f4c310fd2555c6faca1f980f00b161eadb089023gstein * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
99d46a23c6eac800f327b29f8009f7d7da986230trawick * OF THE POSSIBILITY OF SUCH DAMAGE.
f4c310fd2555c6faca1f980f00b161eadb089023gstein * ====================================================================
f4c310fd2555c6faca1f980f00b161eadb089023gstein * This software consists of voluntary contributions made by many
f4c310fd2555c6faca1f980f00b161eadb089023gstein * individuals on behalf of the Apache Group and was originally based
e8f95a682820a599fe41b22977010636be5c2717jim * on public domain software written at the National Center for
99d46a23c6eac800f327b29f8009f7d7da986230trawick * Supercomputing Applications, University of Illinois, Urbana-Champaign.
99d46a23c6eac800f327b29f8009f7d7da986230trawick * For more information on the Apache Group and the Apache HTTP server
5b03ba47ff7225cacb131f14b019332af27da960gstein * project, please see <http://www.apache.org/>.
f4c310fd2555c6faca1f980f00b161eadb089023gstein * Actual definitions of config globals
691db92094897494d6c31326108da20088bc175etrawickint ap_threads_per_child=0; /* Worker threads per child */
691db92094897494d6c31326108da20088bc175etrawickstatic int workers_may_exit = 0;
691db92094897494d6c31326108da20088bc175etrawickstatic int num_listensocks = 0;
691db92094897494d6c31326108da20088bc175etrawick/* The structure used to pass unique initialization info to each thread */
691db92094897494d6c31326108da20088bc175etrawicktypedef struct {
691db92094897494d6c31326108da20088bc175etrawick ap_context_t *tpool; /* "pthread" would be confusing */
e8f95a682820a599fe41b22977010636be5c2717jim * The max child slot ever assigned, preserved across restarts. Necessary
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe * to deal with MaxClients changes across SIGWINCH restarts. We use this
f4c310fd2555c6faca1f980f00b161eadb089023gstein * value to optimize routines that have to scan the entire scoreboard.
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* *Non*-shared http_main globals... */
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe/* one_process --- debugging mode variable; can be set from the command line
f4c310fd2555c6faca1f980f00b161eadb089023gstein * with the -X flag. If set, this gets you the child_main loop running
f4c310fd2555c6faca1f980f00b161eadb089023gstein * in the process which originally started up (no detach, no make_child),
f4c310fd2555c6faca1f980f00b161eadb089023gstein * which is a pretty nice debugging environment. (You'll get a SIGHUP
f4c310fd2555c6faca1f980f00b161eadb089023gstein * early in standalone_main; just continue through. This is the server
f4c310fd2555c6faca1f980f00b161eadb089023gstein * trying to kill off any child processes which it might have lying
f4c310fd2555c6faca1f980f00b161eadb089023gstein * around --- Apache doesn't keep track of their pids, it just sends
f4c310fd2555c6faca1f980f00b161eadb089023gstein * SIGHUP to the process group, ignoring it in the root process.
f4c310fd2555c6faca1f980f00b161eadb089023gstein * Continue through and you'll be fine.).
6f15570e3adc0faf87bf55f70857028276fc9e32wrowestatic int one_process = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* used to maintain list of children which aren't part of the scoreboard */
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowestatic ap_context_t *pconf; /* Pool for config stuff */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic ap_context_t *pchild; /* Pool for httpd child stuff */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int my_pid; /* Linux getpid() doesn't work except in main thread. Use
f4c310fd2555c6faca1f980f00b161eadb089023gstein this instead */
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* Keep track of the number of worker threads currently active */
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* Locks for accept serialization */
e8f95a682820a599fe41b22977010636be5c2717jimstatic pthread_mutex_t thread_accept_mutex = PTHREAD_MUTEX_INITIALIZER;
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic char *lock_fname;
e8f95a682820a599fe41b22977010636be5c2717jim/* Global, alas, so http_core can talk to us */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinAPI_EXPORT(const server_rec *) ap_get_server_conf(void)
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* a clean exit from a child with proper cleanup
f4c310fd2555c6faca1f980f00b161eadb089023gstein static void clean_child_exit(int code) __attribute__ ((noreturn)); */
8b99f2a316c5e2fa6ab208206fdd7fc2bfc4a921dougm/*****************************************************************
f4c310fd2555c6faca1f980f00b161eadb089023gstein * dealing with other children
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe void (*maintenance) (int reason, void *, ap_wait_t status),
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe/* note that since this can be called by a maintenance function while we're
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * scanning the other_children list, all scanners should protect themself
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * by loading ocr->next before calling any maintenance function.
48f35e10f195dd594d75738fc536bb885eda537cgstein for (pocr = &other_children; *pocr; pocr = &(*pocr)->next) {
48f35e10f195dd594d75738fc536bb885eda537cgstein (*(*pocr)->maintenance) (OC_REASON_UNREGISTER, (*pocr)->data, -1);
48f35e10f195dd594d75738fc536bb885eda537cgstein /* XXX: um, well we've just wasted some space in pconf ? */
48f35e10f195dd594d75738fc536bb885eda537cgstein/* test to ensure that the write_fds are all still writable, otherwise
7b6ba9c468f26bdb3492d5e8cb79628a3b04e8c8wrowe * invoke the maintenance functions as appropriate */
48f35e10f195dd594d75738fc536bb885eda537cgsteinstatic void probe_writable_fds(void)
f4c310fd2555c6faca1f980f00b161eadb089023gstein rc = ap_select(fd_max + 1, NULL, &writable_fds, NULL, &tv);
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* XXX: uhh this could be really bad, we could have a bad file
f4c310fd2555c6faca1f980f00b161eadb089023gstein * descriptor due to a bug in one of the maintenance routines */
f4c310fd2555c6faca1f980f00b161eadb089023gstein (*ocr->maintenance) (OC_REASON_UNWRITABLE, ocr->data, -1);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe/* possibly reap an other_child, return 0 if yes, -1 if not */
8b99f2a316c5e2fa6ab208206fdd7fc2bfc4a921dougm (*ocr->maintenance) (OC_REASON_DEATH, ocr->data, status);
f4c310fd2555c6faca1f980f00b161eadb089023gstein for (tries = terminate ? 4 : 1; tries <= 9; ++tries) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* don't want to hold up progress any more than
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * necessary, but we need to allow children a few moments to exit.
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * Set delay with an exponential backoff.
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe /* now see who is done */
f4c310fd2555c6faca1f980f00b161eadb089023gstein for (i = 0; i < max_daemons_limit; ++i) {
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein /* ok, now it's being annoying */
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING,
f39230a531b23d94f86a087963299bbe2e431a4agstein "child process %d still did not exit, sending a SIGTERM",
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein /* die child scum */
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, server_conf,
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein "child process %d still did not exit, sending a SIGKILL",
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein /* gave it our best shot, but alas... If this really
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein * is a child we are trying to kill and it really hasn't
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein * exited, we will likely fail to bind to the port
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein * after the restart.
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, server_conf,
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein "could not make child process %d exit, "
f39230a531b23d94f86a087963299bbe2e431a4agstein (*ocr->maintenance) (OC_REASON_DEATH, ocr->data, status);
f39230a531b23d94f86a087963299bbe2e431a4agstein else if (waitret == 0) {
f39230a531b23d94f86a087963299bbe2e431a4agstein (*ocr->maintenance) (OC_REASON_RESTART, ocr->data, -1);
f39230a531b23d94f86a087963299bbe2e431a4agstein /* uh what the heck? they didn't call unregister? */
f39230a531b23d94f86a087963299bbe2e431a4agstein /* nothing left to wait for */
f39230a531b23d94f86a087963299bbe2e431a4agstein/* Finally, this routine is used by the caretaker process to wait for
f39230a531b23d94f86a087963299bbe2e431a4agstein * a while...
f39230a531b23d94f86a087963299bbe2e431a4agstein/* number of calls to wait_or_timeout between writable probes */
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein if (wait_or_timeout_counter == INTERVAL_OF_WRITABLE_PROBES) {
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein tv.tv_sec = SCOREBOARD_MAINTENANCE_INTERVAL / 1000000;
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein tv.tv_usec = SCOREBOARD_MAINTENANCE_INTERVAL % 1000000;
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein/* handle all varieties of core dumping signals */
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein /* At this point we've got sig blocked, because we're still inside
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein * the signal handler. When we leave the signal handler it will
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein * be unblocked, and we'll take the signal... and coredump or whatever
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein * is appropriate for this particular Unix. In addition the parent
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein * will see the real signal we received -- whereas if we called
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein * abort() here, the parent would only see SIGABRT.
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein/*****************************************************************
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein * Connection structures and accounting...
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein/* volatile just in case */
b5989e567e4fac5b3ab1252024ae19b0a54893a7gsteinstatic int volatile shutdown_pending;
b5989e567e4fac5b3ab1252024ae19b0a54893a7gsteinstatic int volatile restart_pending;
b5989e567e4fac5b3ab1252024ae19b0a54893a7gsteinstatic int volatile is_graceful;
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein * ap_start_shutdown() and ap_start_restart(), below, are a first stab at
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein * functions to initiate shutdown or restart without relying on signals.
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe * Previously this was initiated in sig_term() and restart() signal handlers,
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein * but we want to be able to start a shutdown/restart from other sources --
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein * e.g. on Win32, from the service manager. Now the service manager can
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein * call ap_start_shutdown() or ap_start_restart() as appropiate. Note that
f4c310fd2555c6faca1f980f00b161eadb089023gstein * these functions can also be called by the child processes, since global
f4c310fd2555c6faca1f980f00b161eadb089023gstein * variables are no longer used to pass on the required action to the parent.
f4c310fd2555c6faca1f980f00b161eadb089023gstein * These should only be called from the parent process itself, since the
f4c310fd2555c6faca1f980f00b161eadb089023gstein * parent process will use the shutdown_pending and restart_pending variables
f4c310fd2555c6faca1f980f00b161eadb089023gstein * to determine whether to shutdown or restart. The child process should
f4c310fd2555c6faca1f980f00b161eadb089023gstein * call signal_parent() directly to tell the parent to die -- this will
f4c310fd2555c6faca1f980f00b161eadb089023gstein * cause neither of those variable to be set, which the parent will
f4c310fd2555c6faca1f980f00b161eadb089023gstein * assume means something serious is wrong (which it will be, for the
f4c310fd2555c6faca1f980f00b161eadb089023gstein * child to force an exit) and so do an exit anyway.
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Um, is this _probably_ not an error, if the user has
f4c310fd2555c6faca1f980f00b161eadb089023gstein * tried to do a shutdown twice quickly, so we won't
f4c310fd2555c6faca1f980f00b161eadb089023gstein * worry about reporting it.
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* do a graceful restart if graceful == 1 */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* Probably not an error - don't bother reporting it */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic void set_signals(void)
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGSEGV)");
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGBUS)");
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGABORT)");
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGABRT)");
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGILL)");
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGTERM)");
42f2b4b0e9b84dfd8acbb9c0da18a07c664e30a1jorton ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGINT)");
5a8f3bcf803321e69b226d3b98314305a68a586cjerenkrantz ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGXCPU)");
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGXFSZ)");
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGPIPE)");
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* we want to ignore HUPs and WINCH while we're busy processing one */
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGHUP)");
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "sigaction(SIGWINCH)");
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif /* SIGBUS */
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif /* SIGABORT */
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif /* SIGABRT */
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif /* SIGILL */
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif /* SIGXCPU */
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif /* SIGXFSZ */
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif /* SIGHUP */
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif /* SIGWINCH */
58fd79b56eb624bf011772994e9761d3c2e228c1orlikowski#endif /* SIGPIPE */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic void process_child_status(int pid, ap_wait_t status)
e8f95a682820a599fe41b22977010636be5c2717jim /* Child died... if it died due to a fatal error,
f4c310fd2555c6faca1f980f00b161eadb089023gstein * we should simply bail out.
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_ALERT|APLOG_NOERRNO, 0, server_conf,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Child %d returned a Fatal error... \n"
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "Apache is exiting!",
f4c310fd2555c6faca1f980f00b161eadb089023gstein "child pid %d exit signal %s (%d), "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "possible coredump in %s",
1aac1c71105133d669960501bdf2274e63561054minfrin ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "child pid %d exit signal %d",
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe/*****************************************************************
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * Here follows a long bunch of generic server bookkeeping stuff...
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe#if defined(TCP_NODELAY) && !defined(MPE) && !defined(TPF)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowestatic void sock_disable_nagle(int s)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* The Nagle algorithm says that we should delay sending partial
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * packets in hopes of getting more data. We don't want to do
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * this; we are not telnet. There are bad interactions between
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * persistent connections and Nagle's algorithm that have very severe
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * performance penalties. (Failing to disable Nagle is not much of a
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * problem with simple HTTP.)
99d46a23c6eac800f327b29f8009f7d7da986230trawick * In spite of these problems, failure here is not a shooting offense.
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (char *) &just_say_no,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe sizeof(int)) < 0) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "setsockopt: (TCP_NODELAY)");
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* XXX - Does this really work? - Manoj */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe/*****************************************************************
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * Child process main loop.
6f15570e3adc0faf87bf55f70857028276fc9e32wrowestatic void process_socket(ap_context_t *p, ap_socket_t *sock, int my_child_num, int my_thread_num)
99d46a23c6eac800f327b29f8009f7d7da986230trawick long conn_id = my_child_num * HARD_THREAD_LIMIT + my_thread_num;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, NULL,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "filedescriptor (%u) larger than FD_SETSIZE (%u) "
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "found, you probably need to rebuild Apache with a "
99d46a23c6eac800f327b29f8009f7d7da986230trawick ap_log_error(APLOG_MARK, APLOG_WARNING, errno, NULL,
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm "error attaching to socket");
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe (void) ap_update_child_status(my_child_num, my_thread_num,
f4c310fd2555c6faca1f980f00b161eadb089023gstein current_conn = ap_new_apr_connection(p, server_conf, conn_io, sock,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe/* Sets workers_may_exit if we received a character on the pipe_of_death */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowestatic void check_pipe_of_death(void)
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* It lost the lottery. It must continue to suffer
f4c310fd2555c6faca1f980f00b161eadb089023gstein * through a life of servitude. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* It won the lottery (or something else is very
f4c310fd2555c6faca1f980f00b161eadb089023gstein * wrong). Embrace death with open arms. */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_context_t *ptrans; /* Pool for per-transaction stuff */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe for(n=0 ; n <= num_listensocks ; ++n)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_add_poll_socket(pollset, listensocks[n], APR_POLLIN);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* TODO: Switch to a system where threads reuse the results from earlier
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe poll calls - manoj */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe workers_may_exit |= (ap_max_requests_per_child != 0) && (requests_this_child <= 0);
f4c310fd2555c6faca1f980f00b161eadb089023gstein (void) ap_update_child_status(process_slot, thread_slot, SERVER_READY,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_log_error(APLOG_MARK, APLOG_EMERG, rv, server_conf,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "ap_lock failed. Attempting to shutdown "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "process gracefully.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* poll() will only return errors in catastrophic
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe * circumstances. Let's try exiting gracefully, for now. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_ERR, errno, (const server_rec *)
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* A process got a signal on the shutdown pipe. Check if we're
f4c310fd2555c6faca1f980f00b161eadb089023gstein * the lucky process to die. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* find a listener */
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* XXX: Should we check for POLLERR? */
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_get_revents(&event, listensocks[curr_pollfd], pollset);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if ((rv = SAFE_ACCEPT(ap_unlock(process_accept_mutex)))
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_log_error(APLOG_MARK, APLOG_EMERG, rv, server_conf,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "ap_unlock failed. Attempting to shutdown "
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "process gracefully.");
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe process_socket(ptrans, csd, process_slot, thread_slot);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if ((rv = SAFE_ACCEPT(ap_unlock(process_accept_mutex)))
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_log_error(APLOG_MARK, APLOG_EMERG, rv, server_conf,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "ap_unlock failed. Attempting to shutdown "
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "process gracefully.");
99d46a23c6eac800f327b29f8009f7d7da986230trawick ap_update_child_status(process_slot, thread_slot, SERVER_DEAD,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* All the threads have exited, now finish the shutdown process
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * by signalling the sigwait thread */
f4c310fd2555c6faca1f980f00b161eadb089023gstein /*stuff to do before we switch id's, so we have permissions.*/
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe rv = SAFE_ACCEPT(ap_child_init_lock(&process_accept_mutex, lock_fname,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_log_error(APLOG_MARK, APLOG_EMERG, rv, server_conf,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "Couldn't initialize cross-process lock in child");
f4c310fd2555c6faca1f980f00b161eadb089023gstein /*done with init critical section */
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* All threads should mask signals out, accoring to sigwait(2) man page */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (pthread_sigmask(SIG_SETMASK, &sig_mask, NULL) != 0) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_log_error(APLOG_MARK, APLOG_ALERT, errno, server_conf, "pthread_sigmask");
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* Set up the pollfd array */
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_put_os_sock(&listensocks[0], &pipe_of_death[0], pchild);
f4c310fd2555c6faca1f980f00b161eadb089023gstein for (lr = ap_listeners, i = 1; i <= num_listensocks; lr = lr->next, ++i)
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Setup worker threads */
f4c310fd2555c6faca1f980f00b161eadb089023gstein pthread_mutex_init(&worker_thread_count_mutex, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
f4c310fd2555c6faca1f980f00b161eadb089023gstein for (i=0; i < ap_threads_per_child; i++) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_ALERT, errno, server_conf,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "malloc: out of memory");
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* We are creating threads right now */
f4c310fd2555c6faca1f980f00b161eadb089023gstein (void) ap_update_child_status(my_child_num, i, SERVER_STARTING,
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (pthread_create(&thread, &thread_attr, worker_thread, my_info)) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_ALERT, errno, server_conf,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "pthread_create: unable to create worker thread");
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* In case system resources are maxxed out, we don't want
f4c310fd2555c6faca1f980f00b161eadb089023gstein Apache running away with the CPU trying to fork over and
f4c310fd2555c6faca1f980f00b161eadb089023gstein over and over again if we exit. */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* The SIGTERM shouldn't let us reach this point, but just in case... */
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* We let each thread update it's own scoreboard entry. This is done
f4c310fd2555c6faca1f980f00b161eadb089023gstein * because it let's us deal with tid better.
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* This thread will be the one responsible for handling signals */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_log_error(APLOG_MARK, APLOG_ALERT, errno, server_conf,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowestatic int make_child(server_rec *s, int slot, time_t now)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* Tag this slot as occupied so that perform_idle_server_maintenance
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * doesn't try to steal it */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe (void) ap_update_child_status(slot, 0, SERVER_STARTING, (request_rec *) NULL);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_log_error(APLOG_MARK, APLOG_ERR, errno, s, "fork: Unable to fork new process");
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* fork didn't succeed. Fix the scoreboard or else
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * it will say SERVER_STARTING forever and ever
3ded62d7f2c9b12616d718b8c97d3044baa9ecdbjerenkrantz (void) ap_update_child_status(slot, 0, SERVER_DEAD, (request_rec *) NULL);
3ded62d7f2c9b12616d718b8c97d3044baa9ecdbjerenkrantz /* In case system resources are maxxed out, we don't want
3ded62d7f2c9b12616d718b8c97d3044baa9ecdbjerenkrantz Apache running away with the CPU trying to fork over and
3ded62d7f2c9b12616d718b8c97d3044baa9ecdbjerenkrantz over and over again. */
3ded62d7f2c9b12616d718b8c97d3044baa9ecdbjerenkrantz /* By default, AIX binds to a single processor. This bit unbinds
0fad1368edb71b1411d6d00684900e5d2a6e6b78jerenkrantz children which will then bind to another CPU.
3ded62d7f2c9b12616d718b8c97d3044baa9ecdbjerenkrantz int status = bindprocessor(BINDPROCESS, (int)getpid(),
3ded62d7f2c9b12616d718b8c97d3044baa9ecdbjerenkrantz ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, server_conf,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe/* start up a bunch of children */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe for (i = 0; number_to_start && i < ap_daemons_limit; ++i) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * idle_spawn_rate is the number of children that will be spawned on the
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * next maintenance cycle if there aren't enough idle servers. It is
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * doubled up to MAX_SPAWN_RATE, and reset only when a cycle goes by
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * without the need to spawn.
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* initialize the free_list */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe for (i = 0; i < ap_daemons_limit; ++i) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* Initialization to satisfy the compiler. It doesn't know
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * that ap_threads_per_child is always > 0 */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (i >= max_daemons_limit && free_length == idle_spawn_rate)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe for (j = 0; j < ap_threads_per_child; j++) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe any_dying_threads = any_dying_threads || (status == SERVER_DEAD)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe all_dead_threads = all_dead_threads && (status == SERVER_DEAD);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* We consider a starting server as idle because we started it
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * at least a cycle ago, and if it still hasn't finished starting
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * then we're just going to swamp things worse by forking more.
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * So we hopefully won't need to fork more if we count it.
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * This depends on the ordering of SERVER_READY and SERVER_STARTING.
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (all_dead_threads && free_length < idle_spawn_rate) {
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm /* Kill off one child */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (write(pipe_of_death[1], &char_of_death, 1) == -1) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "write pipe_of_death");
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* terminate the free list */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* only report this condition once */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe static int reported = 0;
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, server_conf,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "server reached MaxClients setting, consider"
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe " raising the MaxClients setting");
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0, server_conf,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "server seems busy, (you may need "
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "to increase StartServers, ThreadsPerChild "
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "spawning %d children, there are around %d idle "
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe for (i = 0; i < free_length; ++i) {
42f2b4b0e9b84dfd8acbb9c0da18a07c664e30a1jorton /* the next time around we want to spawn twice as many if this
42f2b4b0e9b84dfd8acbb9c0da18a07c664e30a1jorton * wasn't good enough, but not if we've just done a graceful
6f15570e3adc0faf87bf55f70857028276fc9e32wrowestatic void server_main_loop(int remaining_children_to_start)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (pid >= 0) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* non-fatal death... note that it's gone in the scoreboard. */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe for (i = 0; i < ap_threads_per_child; i++)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_update_child_status(child_slot, i, SERVER_DEAD, (request_rec *) NULL);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* we're still doing a 1-for-1 replacement of dead
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * children with new children
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* handled */
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Great, we've probably just lost a slot in the
f4c310fd2555c6faca1f980f00b161eadb089023gstein * scoreboard. Somehow we don't know about this
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, server_conf,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* Don't perform idle maintenance when a child dies,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * only do it when there's a timeout. Remember only a
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * finite number of children can die, and it's pretty
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * pathological for a lot to die suddenly.
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* we hit a 1 second timeout in which none of the previous
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * generation of children needed to be reaped... so assume
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * they're all done, and pick up the slack if any is left.
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* In any event we really shouldn't do the code below because
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * few of the servers we just started are in the IDLE state
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * yet, so we'd mistakenly create an extra server.
6f15570e3adc0faf87bf55f70857028276fc9e32wroweint ap_mpm_run(ap_context_t *_pconf, ap_context_t *plog, server_rec *s)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "pipe: (pipe_of_death)");
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe/* XXXXXX Removed because these functions don't exist anymore. When
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe These pipes are changed to apr_types, these functions won't be needed
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_note_cleanups_for_fd(pconf, pipe_of_death[0]);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_note_cleanups_for_fd(pconf, pipe_of_death[1]);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (fcntl(pipe_of_death[0], F_SETFD, O_NONBLOCK) == -1) {
99d46a23c6eac800f327b29f8009f7d7da986230trawick "fcntl: O_NONBLOCKing (pipe_of_death)");
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if ((num_listensocks = setup_listeners(server_conf)) < 1) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* XXX: hey, what's the right way for the mpm to indicate a fatal error? */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ALERT, 0, s,
99d46a23c6eac800f327b29f8009f7d7da986230trawick "no listening sockets available, shutting down");
99d46a23c6eac800f327b29f8009f7d7da986230trawick /* Initialize cross-process accept lock */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe rv = ap_create_lock(&process_accept_mutex, APR_MUTEX, APR_CROSS_PROCESS,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Couldn't create cross-process lock");
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Don't thrash... */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (max_spare_threads < min_spare_threads + ap_threads_per_child)
f4c310fd2555c6faca1f980f00b161eadb089023gstein max_spare_threads = min_spare_threads + ap_threads_per_child;
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* If we're doing a graceful_restart then we're going to see a lot
f4c310fd2555c6faca1f980f00b161eadb089023gstein * of children exiting immediately when we get into the main loop
f4c310fd2555c6faca1f980f00b161eadb089023gstein * below (because we just sent them SIGWINCH). This happens pretty
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * rapidly... and for each one that exits we'll start a new one until
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * we reach at least daemons_min_free. But we may be permitted to
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * start more than that, so we'll just keep track of how many we're
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * supposed to start up without the 1 second penalty between each fork.
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (remaining_children_to_start > ap_daemons_limit) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* give the system some time to recover before kicking into
f4c310fd2555c6faca1f980f00b161eadb089023gstein * exponential mode */
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, server_conf,
99d46a23c6eac800f327b29f8009f7d7da986230trawick "%s configured -- resuming normal operations",
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0, server_conf,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* Time to gracefully shut down:
f4c310fd2555c6faca1f980f00b161eadb089023gstein * Kill child processes, tell them to call child_exit, etc...
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "killpg SIGTERM");
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* cleanup pid file on normal shutdown */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe pidfile = ap_server_root_relative (pconf, ap_pid_fname);
f4c310fd2555c6faca1f980f00b161eadb089023gstein "removed PID file %s (pid=%ld)",
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, server_conf,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "caught SIGTERM, shutting down");
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* we've been told to restart */
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein /* not worth thinking about */
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* advance to the next generation */
ef1ab47476366272bf32be1439057f972bfe86edniq /* XXX: we really need to make sure this new generation number isn't in
ef1ab47476366272bf32be1439057f972bfe86edniq * use by any of the children.
ef1ab47476366272bf32be1439057f972bfe86edniq ap_scoreboard_image->global.running_generation = ap_my_generation;
ef1ab47476366272bf32be1439057f972bfe86edniq ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, server_conf,
ef1ab47476366272bf32be1439057f972bfe86edniq "SIGWINCH received. Doing graceful restart");
ef1ab47476366272bf32be1439057f972bfe86edniq /* give the children the signal to die */
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim for (i = 0; i < ap_daemons_limit;) {
ef1ab47476366272bf32be1439057f972bfe86edniq ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "write pipe_of_death");
5d760c4a4841be07965080c4cec527d8f5172ef5rpluem /* This is mostly for debugging... so that we know what is still
5d760c4a4841be07965080c4cec527d8f5172ef5rpluem * gracefully dealing with existing request.
ef1ab47476366272bf32be1439057f972bfe86edniq for (i = 0; i < ap_daemons_limit; ++i) {
ef1ab47476366272bf32be1439057f972bfe86edniq for (j = 0; j < ap_threads_per_child; j++) {
ef1ab47476366272bf32be1439057f972bfe86edniq if (ap_scoreboard_image->servers[i][j].status != SERVER_DEAD) {
ef1ab47476366272bf32be1439057f972bfe86edniq ap_scoreboard_image->servers[i][j].status = SERVER_GRACEFUL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Kill 'em all. Since the child acts the same on the parents SIGTERM
f4c310fd2555c6faca1f980f00b161eadb089023gstein * and a SIGHUP, we may as well use the same signal, because some user
f4c310fd2555c6faca1f980f00b161eadb089023gstein * pthreads are stealing signals from us left and right.
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf, "killpg SIGTERM");
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, server_conf,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "SIGHUP received. Attempting to restart");
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic void mpmt_pthread_pre_config(ap_context_t *pconf, ap_context_t *plog, ap_context_t *ptemp)
f4c310fd2555c6faca1f980f00b161eadb089023gstein static int restart_num = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* sigh, want this only the second time around */
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe min_spare_threads = DEFAULT_MIN_FREE_DAEMON * DEFAULT_THREADS_PER_CHILD;
f4c310fd2555c6faca1f980f00b161eadb089023gstein max_spare_threads = DEFAULT_MAX_FREE_DAEMON * DEFAULT_THREADS_PER_CHILD;
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_max_requests_per_child = DEFAULT_MAX_REQUESTS_PER_CHILD;
d64231e66711504d8e33d594fc5c27ae86e7b629rpluem ap_cpystrn(ap_coredump_dir, ap_server_root, sizeof(ap_coredump_dir));
d64231e66711504d8e33d594fc5c27ae86e7b629rpluemstatic void mpmt_pthread_hooks(void)
d64231e66711504d8e33d594fc5c27ae86e7b629rpluem ap_hook_pre_config(mpmt_pthread_pre_config,NULL,NULL,HOOK_MIDDLE);
d64231e66711504d8e33d594fc5c27ae86e7b629rpluemstatic const char *set_pidfile(cmd_parms *cmd, void *dummy, char *arg)
d64231e66711504d8e33d594fc5c27ae86e7b629rpluem const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
d64231e66711504d8e33d594fc5c27ae86e7b629rpluem return "PidFile directive not allowed in <VirtualHost>";
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic const char *set_scoreboard(cmd_parms *cmd, void *dummy, char *arg)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowestatic const char *set_lockfile(cmd_parms *cmd, void *dummy, char *arg)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic const char *set_daemons_to_start(cmd_parms *cmd, void *dummy, char *arg)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic const char *set_min_spare_threads(cmd_parms *cmd, void *dummy, char *arg)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "WARNING: detected MinSpareThreads set to non-positive.");
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
f94aab38f6ee899f463f0118ea395291f7c5b4cegstein "Resetting to 1 to avoid almost certain Apache failure.");
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "Please read the documentation.");
6f15570e3adc0faf87bf55f70857028276fc9e32wrowestatic const char *set_max_spare_threads(cmd_parms *cmd, void *dummy, char *arg)
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowestatic const char *set_server_limit (cmd_parms *cmd, void *dummy, char *arg)
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein "WARNING: MaxClients of %d exceeds compile time limit "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "of %d servers,", ap_daemons_limit, HARD_SERVER_LIMIT);
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein " lowering MaxClients to %d. To increase, please "
99d46a23c6eac800f327b29f8009f7d7da986230trawick ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe " HARD_SERVER_LIMIT define in src/include/httpd.h.");
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, "WARNING: Require MaxClients > 0, setting to 1\n");
6f15570e3adc0faf87bf55f70857028276fc9e32wrowestatic const char *set_threads_per_child (cmd_parms *cmd, void *dummy, char *arg)
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "WARNING: ThreadsPerChild of %d exceeds compile time"
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm " lowering ThreadsPerChild to %d. To increase, please"
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
f4c310fd2555c6faca1f980f00b161eadb089023gstein " HARD_THREAD_LIMIT define in src/include/httpd.h.");
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "WARNING: Require ThreadsPerChild > 0, setting to 1");
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic const char *set_max_requests(cmd_parms *cmd, void *dummy, char *arg)
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic const char *set_coredumpdir (cmd_parms *cmd, void *dummy, char *arg)
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *fname;
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((stat(fname, &finfo) == -1) || !S_ISDIR(finfo.st_mode)) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return ap_pstrcat(cmd->pool, "CoreDumpDirectory ", fname,
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_cpystrn(ap_coredump_dir, fname, sizeof(ap_coredump_dir));
f4c310fd2555c6faca1f980f00b161eadb089023gstein "A file for logging the server process ID"},
f4c310fd2555c6faca1f980f00b161eadb089023gstein{ "ScoreBoardFile", set_scoreboard, NULL, RSRC_CONF, TAKE1,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "A file for Apache to maintain runtime process management information"},
f4c310fd2555c6faca1f980f00b161eadb089023gstein "The lockfile used when Apache needs to lock the accept() call"},
f4c310fd2555c6faca1f980f00b161eadb089023gstein{ "StartServers", set_daemons_to_start, NULL, RSRC_CONF, TAKE1,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Number of child processes launched at server startup" },
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm{ "MinSpareThreads", set_min_spare_threads, NULL, RSRC_CONF, TAKE1,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Minimum number of idle children, to handle request spikes" },
f4c310fd2555c6faca1f980f00b161eadb089023gstein{ "MaxSpareThreads", set_max_spare_threads, NULL, RSRC_CONF, TAKE1,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Maximum number of idle children" },
f4c310fd2555c6faca1f980f00b161eadb089023gstein{ "MaxClients", set_server_limit, NULL, RSRC_CONF, TAKE1,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Maximum number of children alive at the same time" },
f4c310fd2555c6faca1f980f00b161eadb089023gstein{ "ThreadsPerChild", set_threads_per_child, NULL, RSRC_CONF, TAKE1,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Number of threads each child creates" },
f4c310fd2555c6faca1f980f00b161eadb089023gstein{ "MaxRequestsPerChild", set_max_requests, NULL, RSRC_CONF, TAKE1,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Maximum number of requests a particular child serves before dying." },
f4c310fd2555c6faca1f980f00b161eadb089023gstein{ "CoreDumpDirectory", set_coredumpdir, NULL, RSRC_CONF, TAKE1,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "The location of the directory Apache changes to before dumping core" },