perchild.c revision f706ad4ddbeb3b9814f52e83006e505cbb2cf662
407N/A/* ==================================================================== 407N/A * The Apache Software License, Version 1.1 407N/A * Copyright (c) 2000-2002 The Apache Software Foundation. All rights 407N/A * Redistribution and use in source and binary forms, with or without 407N/A * modification, are permitted provided that the following conditions 407N/A * 1. Redistributions of source code must retain the above copyright 407N/A * notice, this list of conditions and the following disclaimer. 407N/A * 2. Redistributions in binary form must reproduce the above copyright 407N/A * notice, this list of conditions and the following disclaimer in 407N/A * the documentation and/or other materials provided with the 407N/A * 3. The end-user documentation included with the redistribution, 407N/A * if any, must include the following acknowledgment: 407N/A * "This product includes software developed by the 407N/A * Alternately, this acknowledgment may appear in the software itself, 407N/A * if and wherever such third-party acknowledgments normally appear. 407N/A * 4. The names "Apache" and "Apache Software Foundation" must 407N/A * not be used to endorse or promote products derived from this 407N/A * software without prior written permission. For written 407N/A * permission, please contact apache@apache.org. 407N/A * 5. Products derived from this software may not be called "Apache", 407N/A * nor may "Apache" appear in their name, without prior written 407N/A * permission of the Apache Software Foundation. 407N/A * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 407N/A * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 407N/A * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 407N/A * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR 407N/A * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 407N/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 407N/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 407N/A * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 407N/A * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 407N/A * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 407N/A * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 407N/A * ==================================================================== 407N/A * This software consists of voluntary contributions made by many 407N/A * individuals on behalf of the Apache Software Foundation. For more 407N/A * information on the Apache Software Foundation, please see * Portions of this software are based upon public domain software * originally written at the National Center for Supercomputing Applications, * University of Illinois, Urbana-Champaign. /* ### should be APR-ized */ * Define some magic numbers that we use for the state of the incomming * request. These must be < 0 so they don't collide with a file descriptor. /* Limit on the threads per process. Clients will be locked out if more than * this * server_limit are needed. * We keep this for one reason it keeps the size of the scoreboard file small * enough that we can read the whole thing without worrying too much about /* Admin can't tune ThreadLimit beyond MAX_THREAD_LIMIT. We want * some sort of compile-time limit to help catch typos. /* Limit on the total --- clients will be locked out if more servers than * this are needed. It is intended solely to keep the server from crashing * when things get out of hand. * We keep a hard maximum number of servers, for two reasons --- first off, * in case something goes seriously wrong, we want to stop the fork bomb * short of actually crashing the machine we're running on by filling some * kernel table. Secondly, it keeps the size of the scoreboard file small * enough that we can read the whole thing without worrying too much about /* Admin can't tune ServerLimit beyond MAX_SERVER_LIMIT. We want * some sort of compile-time limit to help catch typos. * Actual definitions of config globals const char *
sockname;
/* The base name for the socket */ const char *
fullsockname;
/* socket base name + extension */ int sd;
/* The socket descriptor */ int sd2;
/* The socket descriptor */ /* Tables used to determine the user and group each child process should * run as. The hash table is used to correlate a server name with a child * The max child slot ever assigned, preserved across restarts. Necessary * to deal with NumServers changes across AP_SIG_GRACEFUL restarts. We * use this value to optimize routines that have to scan the entire child * XXX - It might not be worth keeping this code in. There aren't very * many child processes in this MPM. /* *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.). static unsigned int my_pid;
/* Linux getpid() doesn't work except in main thread. Use this instead */ /* Keep track of the number of worker threads currently active */ /* Keep track of the number of idle worker threads */ /* Locks for accept serialization */ #
endif /* NO_SERIALIZED_ACCEPT *//* a clean exit from a child with proper cleanup */ /* 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 */ /* we don't currently track ap_my_generation, but mod_status * references it so it must be defined */ * 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 AP_SIG_GRACEFUL while we're busy #
endif /* AP_SIG_GRACEFUL *//***************************************************************** * Here follows a long bunch of generic server bookkeeping stuff... /* XXX - Does this really work? - Manoj */ /***************************************************************** * Child process main loop. "new file descriptor %d is too large; you probably need " "to rebuild Apache with a larger FD_SETSIZE " /* Starts a thread as long as we're below max_threads */ "apr_thread_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. */ "server reached MaxThreadsPerChild setting, " "consider raising the MaxThreadsPerChild or " /* 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. */ /* idle_thread_count should be incremented before starting a worker_thread */ "apr_proc_mutex_lock failed. Attempting to shutdown " /* apr_poll() will only return errors in catastrophic * circumstances. Let's try exiting gracefully, for now. */ /* XXX: Should we check for POLLERR? */ /* E[NM]FILE, ENOMEM, etc */ "apr_proc_mutex_unlock failed. Attempting to shutdown " "apr_proc_mutex_unlock failed. Attempting to shutdown " /* All the threads have exited, now finish the shutdown process * by signalling the sigwait thread */ * Note that we use the username as set in the config files, rather than * the lookup of to uid --- the same uid may have multiple passwd entries, * with different sets of groups for each. /* Get username if passed as a uid */ "getpwuid: couldn't determine user name from uid %u, " "you probably need to modify the User directive",
* Set the GID before initgroups(), since on some platforms * setgid() is known to zap the group list. "setgid: unable to set group id to Group %u",
/* Reset `groups' attributes. */ "initgroups: unable to set groups for User %s " "and Group %u",
name, (
unsigned)
gid);
/* Only try to switch if we're running as root */ "setuid: unable to change to uid: %ld",
/*stuff to do before we switch id's, so we have permissions.*/ "Couldn't initialize cross-process lock in child");
/*done with init critical section */ /* Setup worker threads */ /* We are creating worker threads right now */ /* start_thread shouldn't fail here */ "fork: Unable to fork new process");
/* 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. */ /* By default, AIX binds to a single processor. This bit unbinds * children which will then bind to another CPU. /* XXX - For an unthreaded server, a signal handler will be necessary * apr_signal(SIGTERM, just_die); /* start up a bunch of children */ * spawn_rate is the number of children that will be spawned on the * next maintenance cycle if there aren't enough 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 */ /* 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 child table and * clean out the status table. */ /* we're still doing a 1-for-1 replacement of dead * children with new children /* Great, we've probably just lost a slot in the * child table. Somehow we don't know about this "long lost child came home! (pid %ld)",
/* 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. "WARNING: Attempt to change ServerLimit or ThreadLimit " "ignored during restart");
/* Initialize cross-process accept lock */ "Couldn't create cross-process lock");
/* Initialize the child table */ /* We need to put the new listeners at the end of the ap_listeners * list. If we don't, then the pool will be cleared before the * open_logs phase is called for the second time, and ap_listeners * will have only invalid data. If that happens, then the sockets * that we opened using make_sock() will be lost, and the server /* 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 AP_SIG_GRACEFUL). 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",
"AcceptMutex: %s (default: %s)",
/* 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)",
/* we've been told to restart */ /* not worth thinking about */ "Doing graceful restart");
/* This is mostly for debugging... so that we know what is still * gracefully dealing with existing request. /* give the children the signal to die */ /* 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. /* This really should be a post_config hook, but the error log is already * redirected by that point, so we need to do this in the open_logs phase. NULL,
"no listening sockets available, shutting down");
"Could not open pipe-of-death.");
"apr_file_pipe_create (pipe_of_death)");
"apr_file_pipe_timeout_set (pipe_of_death)");
/* sigh, want this only the second time around */ "apr_proc_detach failed");
/* we need to know ServerLimit and ThreadLimit before we start processing * the tree because we need to already have allocated child_info_table /* ### this "read one line" doesn't seem right... shouldn't we be ### reading large chunks of data or something? /* sconf is the server config for this vhost, so if our socket * is not the same that was set in the config, then the request * needs to be passed to another child. */ "child, request will not be honored.");
/* The perchild open_logs phase must run before the core's, or stderr * will be redirected to a file, and the messages won't print to the /* This must be run absolutely first. If this request isn't for this * server then we need to forward it to the proper child. No sense * tying up this server running more post_read request hooks if it is * just going to be forwarded along. "WARNING: NumServers of %d exceeds ServerLimit value " " lowering NumServers to %d. To increase, please " " ServerLimit directive.");
"WARNING: Require NumServers > 0, setting to 1");
"WARNING: StartThreads of %d exceeds ThreadLimit value" " lowering StartThreads to %d. To increase, please" " ThreadLimit directive.");
"WARNING: Require StartThreads > 0, setting to 1");
"WARNING: detected MinSpareThreads set to non-positive.");
"Resetting to 1 to avoid almost certain Apache failure.");
"Please read the documentation.");
"WARNING: detected MinSpareThreads set higher than");
"WARNING: detected MaxThreadsPerChild set higher than");
const char *g,
const char *
num)
return "Trying to use more child ID's than NumServers. Increase " "NumServers in your config file.";
return "Assigning root user/group to a child.";
return "Unable to find process with matching uid/gid.";
/* you cannot change ServerLimit across a restart; ignore /* how do we log a message? the error log is a bit bucket at this * point; we'll just have to set a flag so that ap_mpm_run() "WARNING: ServerLimit of %d exceeds compile time limit " "WARNING: Require ServerLimit > 0, setting to 1");
/* you cannot change ThreadLimit across a restart; ignore /* how do we log a message? the error log is a bit bucket at this * point; we'll just have to set a flag so that ap_mpm_run() "WARNING: ThreadLimit of %d exceeds compile time limit " "WARNING: Require ThreadLimit > 0, setting to 1");
"Number of children alive at the same time"),
"Number of threads each child creates"),
"Minimum number of idle threads per child, to handle " "Maximum number of idle threads per child"),
"Maximum number of threads per child"),
"Specify a User and Group for a specific child process."),
"Tie a virtual host to a specific child process."),
"Maximum value of NumServers for this run of Apache"),
"Maximum worker threads in a server for this run of Apache"),
NULL,
/* create per-directory config structure */ NULL,
/* merge per-directory config structures */ NULL,
/* merge per-server config structures */