mpmt_pthread.c revision 856cd04dde6122606dffc1c3c11200cdb1ea146e
6201N/A/* ==================================================================== 6201N/A * Copyright (c) 1995-1999 The Apache Group. All rights reserved. 6201N/A * Redistribution and use in source and binary forms, with or without 6201N/A * modification, are permitted provided that the following conditions 6201N/A * 1. Redistributions of source code must retain the above copyright 6201N/A * notice, this list of conditions and the following disclaimer. 6201N/A * 2. Redistributions in binary form must reproduce the above copyright 6201N/A * notice, this list of conditions and the following disclaimer in 6201N/A * the documentation and/or other materials provided with the 6201N/A * 3. All advertising materials mentioning features or use of this 6201N/A * software must display the following acknowledgment: 6201N/A * "This product includes software developed by the Apache Group 6201N/A * 4. The names "Apache Server" and "Apache Group" must not be used to 6201N/A * endorse or promote products derived from this software without 6201N/A * prior written permission. For written permission, please contact 6201N/A * 5. Products derived from this software may not be called "Apache" 6201N/A * nor may "Apache" appear in their names without prior written 6201N/A * permission of the Apache Group. 6201N/A * 6. Redistributions of any form whatsoever must retain the following 6201N/A * "This product includes software developed by the Apache Group 6201N/A * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY 6201N/A * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 6201N/A * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 6201N/A * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR 6201N/A * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 6201N/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 6201N/A * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 6201N/A * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 6201N/A * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 7291N/A * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 7291N/A * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 6201N/A * OF THE POSSIBILITY OF SUCH DAMAGE. 6201N/A * ==================================================================== 6201N/A * This software consists of voluntary contributions made by many 6201N/A * individuals on behalf of the Apache Group and was originally based 6201N/A * on public domain software written at the National Center for 6201N/A * Supercomputing Applications, University of Illinois, Urbana-Champaign. 6201N/A * For more information on the Apache Group and the Apache HTTP server * Actual definitions of config globals /* The structure used to pass unique initialization info to each thread */ * The max child slot ever assigned, preserved across restarts. Necessary * to deal with MaxClients changes across SIGWINCH restarts. We use this * value to optimize routines that have to scan the entire scoreboard. /* *Non*-shared http_main globals... */ /* one_process --- debugging mode variable; can be set from the command line * with the -X flag. If set, this gets you the child_main loop running * in the process which originally started up (no detach, no make_child), * which is a pretty nice debugging environment. (You'll get a SIGHUP * early in standalone_main; just continue through. This is the server * trying to kill off any child processes which it might have lying * around --- Apache doesn't keep track of their pids, it just sends * SIGHUP to the process group, ignoring it in the root process. * Continue through and you'll be fine.). /* used to maintain list of children which aren't part of the scoreboard */ static int my_pid;
/* Linux getpid() doesn't work except in main thread. Use /* Keep track of the number of worker threads currently active */ /* Global, alas, so http_core can talk to us */ /* a clean exit from a child with proper cleanup static void clean_child_exit(int code) __attribute__ ((noreturn)); */ /***************************************************************** * dealing with other children /* note that since this can be called by a maintenance function while we're * scanning the other_children list, all scanners should protect themself * by loading ocr->next before calling any maintenance function. /* XXX: um, well we've just wasted some space in pconf ? */ /* test to ensure that the write_fds are all still writable, otherwise * invoke the maintenance functions as appropriate */ /* XXX: uhh this could be really bad, we could have a bad file * descriptor due to a bug in one of the maintenance routines */ /* possibly reap an other_child, return 0 if yes, -1 if not */ long int waittime =
1024 *
16;
/* in usecs */ /* don't want to hold up progress any more than * necessary, but we need to allow children a few moments to exit. * Set delay with an exponential backoff. /* now see who is done */ /* ok, now it's being annoying */ "child process %d still did not exit, sending a SIGTERM",
"child process %d still did not exit, sending a SIGKILL",
/* gave it our best shot, but alas... If this really * is a child we are trying to kill and it really hasn't * exited, we will likely fail to bind to the port "could not make child process %d exit, " "attempting to continue anyway",
pid);
/* uh what the heck? they didn't call unregister? */ /* nothing left to wait for */ /* Finally, this routine is used by the caretaker process to wait for /* number of calls to wait_or_timeout between writable probes */ /* handle all varieties of core dumping signals */ /* At this point we've got sig blocked, because we're still inside * the signal handler. When we leave the signal handler it will * be unblocked, and we'll take the signal... and coredump or whatever * is appropriate for this particular Unix. In addition the parent * will see the real signal we received -- whereas if we called * abort() here, the parent would only see SIGABRT. /***************************************************************** * Connection structures and accounting... /* volatile just in case */ * ap_start_shutdown() and ap_start_restart(), below, are a first stab at * functions to initiate shutdown or restart without relying on signals. * Previously this was initiated in sig_term() and restart() signal handlers, * e.g. on Win32, from the service manager. Now the service manager can * call ap_start_shutdown() or ap_start_restart() as appropiate. Note that * these functions can also be called by the child processes, since global * variables are no longer used to pass on the required action to the parent. * These should only be called from the parent process itself, since the * parent process will use the shutdown_pending and restart_pending variables * to determine whether to shutdown or restart. The child process should * call signal_parent() directly to tell the parent to die -- this will * cause neither of those variable to be set, which the parent will * assume means something serious is wrong (which it will be, for the * child to force an exit) and so do an exit anyway. /* Um, is this _probably_ not an error, if the user has * tried to do a shutdown twice quickly, so we won't * worry about reporting it. /* do a graceful restart if graceful == 1 */ /* Probably not an error - don't bother reporting it */ /* we want to ignore HUPs and WINCH while we're busy processing one */ /* Child died... if it died due to a fatal error, * we should simply bail out. "Child %d returned a Fatal error... \n" "child pid %d exit signal %s (%d), " "possible coredump in %s",
"child pid %d exit signal %s (%d)",
pid,
"child pid %d exit signal %d",
/***************************************************************** * Here follows a long bunch of generic server bookkeeping stuff... /* The Nagle algorithm says that we should delay sending partial * packets in hopes of getting more data. We don't want to do * this; we are not telnet. There are bad interactions between * persistent connections and Nagle's algorithm that have very severe * performance penalties. (Failing to disable Nagle is not much of a * problem with simple HTTP.) * In spite of these problems, failure here is not a shooting offense. "setsockopt: (TCP_NODELAY)");
/* XXX - Does this really work? - Manoj */ /***************************************************************** * Child process main loop. "filedescriptor (%u) larger than FD_SETSIZE (%u) " "found, you probably need to rebuild Apache with a " "error attaching to socket");
/* Sets workers_may_exit if we received a character on the pipe_of_death */ /* It lost the lottery. It must continue to suffer * through a life of servitude. */ /* It won the lottery (or something else is very * wrong). Embrace death with open arms. */ /* TODO: Switch to a system where threads reuse the results from earlier /* poll() will only return errors in catastrophic * circumstances. Let's try exiting gracefully, for now. */ /* A process got a signal on the shutdown pipe. Check if we're * the lucky process to die. */ /* XXX: Should we check for POLLERR? */ /* All the threads have exited, now finish the shutdown process * by signalling the sigwait thread */ /*stuff to do before we switch id's, so we have permissions.*/ /*done with init critical section */ /* All threads should mask signals out, accoring to sigwait(2) man page */ /* Set up the pollfd array */ /* Setup worker threads */ "malloc: out of memory");
/* We are creating threads right now */ "pthread_create: unable to create worker thread");
/* In case system resources are maxxed out, we don't want Apache running away with the CPU trying to fork over and over and over again if we exit. */ /* The SIGTERM shouldn't let us reach this point, but just in case... */ /* We let each thread update it's own scoreboard entry. This is done * because it let's us deal with tid better. /* This thread will be the one responsible for handling signals */ /* In case system resources are maxxed out, we don't want Apache running away with the CPU trying to fork over and /* By default, AIX binds to a single processor. This bit unbinds children which will then bind to another CPU. "processor unbind failed %d",
status);
/* start up a bunch of children */ * idle_spawn_rate is the number of children that will be spawned on the * next maintenance cycle if there aren't enough idle servers. It is * doubled up to MAX_SPAWN_RATE, and reset only when a cycle goes by * without the need to spawn. /* initialize the free_list */ /* Initialization to satisfy the compiler. It doesn't know * that ap_threads_per_child is always > 0 */ /* We consider a starting server as idle because we started it * at least a cycle ago, and if it still hasn't finished starting * then we're just going to swamp things worse by forking more. * So we hopefully won't need to fork more if we count it. * This depends on the ordering of SERVER_READY and SERVER_STARTING. /* terminate the free list */ /* only report this condition once */ "server reached MaxClients setting, consider" " raising the MaxClients setting");
"server seems busy, (you may need " "to increase StartServers, ThreadsPerChild " "spawning %d children, there are around %d idle " /* the next time around we want to spawn twice as many if this * wasn't good enough, but not if we've just done a graceful /* non-fatal death... note that it's gone in the scoreboard. */ /* we're still doing a 1-for-1 replacement of dead * children with new children /* ZZZ abstract out for AP funcs. */ /* Great, we've probably just lost a slot in the * scoreboard. Somehow we don't know about this "long lost child came home! (pid %d)",
pid);
/* Don't perform idle maintenance when a child dies, * only do it when there's a timeout. Remember only a * finite number of children can die, and it's pretty * pathological for a lot to die suddenly. /* we hit a 1 second timeout in which none of the previous * generation of children needed to be reaped... so assume * they're all done, and pick up the slack if any is left. /* In any event we really shouldn't do the code below because * few of the servers we just started are in the IDLE state * yet, so we'd mistakenly create an extra server. "pipe: (pipe_of_death)");
/* XXXXXX Removed because these functions don't exist anymore. When These pipes are changed to apr_types, these functions won't be needed ap_note_cleanups_for_fd(pconf, pipe_of_death[0]); ap_note_cleanups_for_fd(pconf, pipe_of_death[1]); "fcntl: O_NONBLOCKing (pipe_of_death)");
/* XXX: hey, what's the right way for the mpm to indicate a fatal error? */ "no listening sockets available, shutting down");
/* If we're doing a graceful_restart then we're going to see a lot * of children exiting immediately when we get into the main loop * below (because we just sent them SIGWINCH). This happens pretty * rapidly... and for each one that exits we'll start a new one until * we reach at least daemons_min_free. But we may be permitted to * start more than that, so we'll just keep track of how many we're * supposed to start up without the 1 second penalty between each fork. /* give the system some time to recover before kicking into "%s configured -- resuming normal operations",
/* Time to gracefully shut down: * Kill child processes, tell them to call child_exit, etc... /* cleanup pid file on normal shutdown */ "removed PID file %s (pid=%ld)",
"caught SIGTERM, shutting down");
/* we've been told to restart */ /* not worth thinking about */ /* advance to the next generation */ /* XXX: we really need to make sure this new generation number isn't in * use by any of the children. "SIGWINCH received. Doing graceful restart");
/* give the children the signal to die */ /* This is mostly for debugging... so that we know what is still * gracefully dealing with existing request. /* Kill 'em all. Since the child acts the same on the parents SIGTERM * and a SIGHUP, we may as well use the same signal, because some user * pthreads are stealing signals from us left and right. "SIGHUP received. Attempting to restart");
/* sigh, want this only the second time around */ return "PidFile directive not allowed in <VirtualHost>";
fprintf(
stderr,
"WARNING: detected MinSpareThreads set to non-positive.\n");
fprintf(
stderr,
"Resetting to 1 to avoid almost certain Apache failure.\n");
fprintf(
stderr,
"WARNING: MaxClients of %d exceeds compile time limit " fprintf(
stderr,
" lowering MaxClients to %d. To increase, please " fprintf(
stderr,
"WARNING: Require MaxClients > 0, setting to 1\n");
fprintf(
stderr,
"WARNING: ThreadsPerChild of %d exceeds compile time" fprintf(
stderr,
" lowering ThreadsPerChild to %d. To increase, please" fprintf(
stderr,
"WARNING: Require ThreadsPerChild > 0, setting to 1\n");
/* ZZZ change this to the AP func FileInfo*/ " does not exist or is not a directory",
NULL);
/* Ignoring error conditions here. :( */ "A file for logging the server process ID"},
"A file for Apache to maintain runtime process management information"},
"The lockfile used when Apache needs to lock the accept() call"},
"Number of child processes launched at server startup" },
"Minimum number of idle children, to handle request spikes" },
"Maximum number of idle children" },
"Maximum number of children alive at the same time" },
"Number of threads each child creates" },
"Maximum number of requests a particular child serves before dying." },
"The location of the directory Apache changes to before dumping core" },
NULL,
/* create per-directory config structure */ NULL,
/* merge per-directory config structures */ NULL,
/* create per-server config structure */ NULL,
/* merge per-server config structures */