⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 prefork.c

📁 Apache V2.0.15 Alpha For Linuxhttpd-2_0_15-alpha.tar.Z
💻 C
📖 第 1 页 / 共 3 页
字号:
/* ==================================================================== * The Apache Software License, Version 1.1 * * Copyright (c) 2000-2001 The Apache Software Foundation.  All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in *    the documentation and/or other materials provided with the *    distribution. * * 3. The end-user documentation included with the redistribution, *    if any, must include the following acknowledgment: *       "This product includes software developed by the *        Apache Software Foundation (http://www.apache.org/)." *    Alternately, this acknowledgment may appear in the software itself, *    if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" must *    not be used to endorse or promote products derived from this *    software without prior written permission. For written *    permission, please contact apache@apache.org. * * 5. Products derived from this software may not be called "Apache", *    nor may "Apache" appear in their name, without prior written *    permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation.  For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * * Portions of this software are based upon public domain software * originally written at the National Center for Supercomputing Applications, * University of Illinois, Urbana-Champaign. *//* * httpd.c: simple http daemon for answering WWW file requests * *  * 03-21-93  Rob McCool wrote original code (up to NCSA HTTPd 1.3) *  * 03-06-95  blong *  changed server number for child-alone processes to 0 and changed name *   of processes * * 03-10-95  blong *      Added numerous speed hacks proposed by Robert S. Thau (rst@ai.mit.edu)  *      including set group before fork, and call gettime before to fork *      to set up libraries. * * 04-14-95  rst / rh *      Brandon's code snarfed from NCSA 1.4, but tinkered to work with the *      Apache server, and also to have child processes do accept() directly. * * April-July '95 rst *      Extensive rework for Apache. *//* TODO: this is a cobbled together prefork MPM example... it should mostly * TODO: behave like apache-1.3... here's a short list of things I think * TODO: need cleaning up still: */#include "apr.h"#include "apr_portable.h"#include "apr_strings.h"#include "apr_thread_proc.h"#include "apr_signal.h"#define APR_WANT_STDIO#define APR_WANT_STRFUNC#include "apr_want.h"#if APR_HAVE_UNISTD_H#include <unistd.h>#endif#if APR_HAVE_SYS_TYPES_H#include <sys/types.h>#endif#define CORE_PRIVATE#include "ap_config.h"#include "httpd.h"#include "mpm_default.h"#include "http_main.h"#include "http_log.h"#include "http_config.h"#include "http_core.h"		/* for get_remote_host */#include "http_connection.h"#include "scoreboard.h"#include "ap_mpm.h"#include "unixd.h"#include "mpm_common.h"#include "ap_listen.h"#include "ap_mmn.h"#ifdef HAVE_BSTRING_H#include <bstring.h>		/* for IRIX, FD_SET calls bzero() */#endif#ifdef HAVE_TIME_H#include <time.h>#endif#include <signal.h>#include <sys/times.h>/* config globals */int ap_threads_per_child=0;         /* Worker threads per child */static int ap_max_requests_per_child=0;static const char *ap_pid_fname=NULL;static apr_lock_t *accept_lock;static const char *ap_lock_fname;static int ap_daemons_to_start=0;static int ap_daemons_min_free=0;static int ap_daemons_max_free=0;static int ap_daemons_limit=0;/* * 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. */int ap_max_daemons_limit = -1;server_rec *ap_server_conf;char ap_coredump_dir[MAX_STRING_LEN];/* *Non*-shared http_main globals... */static apr_socket_t *sd;static fd_set listenfds;static int listenmaxfd;/* 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 int one_process = 0;static apr_pool_t *pconf;		/* Pool for config stuff */static apr_pool_t *pchild;		/* Pool for httpd child stuff */static pid_t ap_my_pid;	/* it seems silly to call getpid all the time */#ifndef MULTITHREADstatic int my_child_num;#endif#ifdef TPFint tpf_child = 0;char tpf_server_name[INETD_SERVNAME_LENGTH+1];#endif /* TPF */#ifdef GPROF/*  * change directory for gprof to plop the gmon.out file * configure in httpd.conf: * GprofDir logs/   -> $ServerRoot/logs/gmon.out * GprofDir logs/%  -> $ServerRoot/logs/gprof.$pid/gmon.out */static void chdir_for_gprof(void){    core_server_config *sconf = 	ap_get_module_config(ap_server_conf->module_config, &core_module);        char *dir = sconf->gprof_dir;    const char *use_dir;    if(dir) {        apr_status_t res;	char buf[512];	int len = strlen(sconf->gprof_dir) - 1;	if(*(dir + len) == '%') {	    dir[len] = '\0';	    apr_snprintf(buf, sizeof(buf), "%sgprof.%d", dir, (int)getpid());	} 	use_dir = ap_server_root_relative(pconf, buf[0] ? buf : dir);	res = apr_dir_make(use_dir, 0755, pconf);	if(res != APR_SUCCESS && !APR_STATUS_IS_EEXIST(res)) {	    ap_log_error(APLOG_MARK, APLOG_ERR, errno, ap_server_conf,			 "gprof: error creating directory %s", dir);	}    }    else {	use_dir = ap_server_root_relative(pconf, "logs");    }    chdir(dir);}#else#define chdir_for_gprof()#endif/* XXX - I don't know if TPF will ever use this module or not, so leave * the ap_check_signals calls in but disable them - manoj */#define ap_check_signals() /* a clean exit from a child with proper cleanup */static void clean_child_exit(int code) __attribute__ ((noreturn));static void clean_child_exit(int code){    if (pchild) {	apr_pool_destroy(pchild);    }    chdir_for_gprof();    exit(code);}static void expand_lock_fname(apr_pool_t *p){    /* XXXX possibly bogus cast */    ap_lock_fname = apr_psprintf(p, "%s.%lu",	ap_server_root_relative(p, ap_lock_fname), (unsigned long)getpid());}/* Initialize mutex lock. * Done by each child at its birth */static void accept_mutex_child_init(apr_pool_t *p){    apr_status_t rv;    rv = apr_lock_child_init(&accept_lock, ap_lock_fname, p);    if (rv) {	ap_log_error(APLOG_MARK, APLOG_EMERG, rv, NULL,                      "couldn't do child init for accept mutex");        clean_child_exit(APEXIT_CHILDINIT);    }}/* Initialize mutex lock. * Must be safe to call this on a restart. */static void accept_mutex_init(apr_pool_t *p){    apr_status_t rv;    expand_lock_fname(p);    rv = apr_lock_create(&accept_lock, APR_MUTEX, APR_CROSS_PROCESS, ap_lock_fname, p);    if (rv) {	ap_log_error(APLOG_MARK, APLOG_EMERG, rv, NULL, "couldn't create accept mutex");        exit(APEXIT_INIT);    }}static void accept_mutex_on(void){    apr_status_t rv = apr_lock_acquire(accept_lock);    if (rv != APR_SUCCESS) {        ap_log_error(APLOG_MARK, APLOG_EMERG, rv, NULL, "couldn't grab the accept mutex");        exit(APEXIT_CHILDFATAL);    }}static void accept_mutex_off(void){    apr_status_t rv = apr_lock_release(accept_lock);    if (rv != APR_SUCCESS) {        ap_log_error(APLOG_MARK, APLOG_EMERG, rv, NULL, "couldn't release the accept mutex");        exit(APEXIT_CHILDFATAL);    }}/* On some architectures it's safe to do unserialized accept()s in the single * Listen case.  But it's never safe to do it in the case where there's * multiple Listen statements.  Define SINGLE_LISTEN_UNSERIALIZED_ACCEPT * when it's safe in the single Listen case. */#ifdef SINGLE_LISTEN_UNSERIALIZED_ACCEPT#define SAFE_ACCEPT(stmt) do {if (ap_listeners->next) {stmt;}} while(0)#else#define SAFE_ACCEPT(stmt) do {stmt;} while(0)#endifAP_DECLARE(apr_status_t) ap_mpm_query(int query_code, int *result){    switch(query_code){        case AP_MPMQ_MAX_DAEMONS:            *result = ap_daemons_limit;            return APR_SUCCESS;        case AP_MPMQ_IS_THREADED:            *result = 0;            return APR_SUCCESS;        case AP_MPMQ_IS_FORKED:            *result = 1;            return APR_SUCCESS;    }    return APR_ENOTIMPL;}#if defined(NEED_WAITPID)/*   Systems without a real waitpid sometimes lose a child's exit while waiting   for another.  Search through the scoreboard for missing children. */int reap_children(apr_wait_t *status){    int n, pid;    for (n = 0; n < ap_max_daemons_limit; ++n) {        ap_sync_scoreboard_image();	if (ap_scoreboard_image->servers[n][0].status != SERVER_DEAD &&		kill((pid = ap_scoreboard_image->parent[n].pid), 0) == -1) {	    ap_update_child_status(AP_CHILD_THREAD_FROM_ID(n), SERVER_DEAD, NULL);	    /* just mark it as having a successful exit status */	    memset(status, 0, sizeof(apr_wait_t));	    return(pid);	}    }    return 0;}#endif/* handle all varieties of core dumping signals */static void sig_coredump(int sig){    chdir(ap_coredump_dir);    apr_signal(sig, SIG_DFL);    kill(getpid(), sig);    /* 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... */static void just_die(int sig){    clean_child_exit(0);}static int volatile deferred_die;static int volatile usr1_just_die;static void usr1_handler(int sig){    if (usr1_just_die) {	just_die(sig);    }    deferred_die = 1;}/* volatile just in case */static int volatile shutdown_pending;static int volatile restart_pending;static int volatile is_graceful;ap_generation_t volatile ap_my_generation=0;static void sig_term(int sig){    if (shutdown_pending == 1) {	/* 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.	 */	return;    }    shutdown_pending = 1;}static void restart(int sig){    if (restart_pending == 1) {	/* Probably not an error - don't bother reporting it */	return;    }    restart_pending = 1;    if ((is_graceful = (sig == SIGWINCH))) {        apr_pool_cleanup_kill(pconf, NULL, ap_cleanup_scoreboard);    }}static void set_signals(void){#ifndef NO_USE_SIGACTION    struct sigaction sa;    sigemptyset(&sa.sa_mask);    sa.sa_flags = 0;    if (!one_process) {	sa.sa_handler = sig_coredump;#if defined(SA_ONESHOT)	sa.sa_flags = SA_ONESHOT;#elif defined(SA_RESETHAND)	sa.sa_flags = SA_RESETHAND;#endif	if (sigaction(SIGSEGV, &sa, NULL) < 0)	    ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGSEGV)");#ifdef SIGBUS	if (sigaction(SIGBUS, &sa, NULL) < 0)	    ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGBUS)");#endif#ifdef SIGABORT	if (sigaction(SIGABORT, &sa, NULL) < 0)	    ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGABORT)");#endif#ifdef SIGABRT	if (sigaction(SIGABRT, &sa, NULL) < 0)	    ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGABRT)");#endif#ifdef SIGILL	if (sigaction(SIGILL, &sa, NULL) < 0)	    ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGILL)");#endif	sa.sa_flags = 0;    }    sa.sa_handler = sig_term;    if (sigaction(SIGTERM, &sa, NULL) < 0)	ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGTERM)");#ifdef SIGINT    if (sigaction(SIGINT, &sa, NULL) < 0)        ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGINT)");#endif#ifdef SIGXCPU    sa.sa_handler = SIG_DFL;    if (sigaction(SIGXCPU, &sa, NULL) < 0)	ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGXCPU)");#endif#ifdef SIGXFSZ    sa.sa_handler = SIG_DFL;    if (sigaction(SIGXFSZ, &sa, NULL) < 0)	ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGXFSZ)");#endif#ifdef SIGPIPE    sa.sa_handler = SIG_IGN;    if (sigaction(SIGPIPE, &sa, NULL) < 0)	ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGPIPE)");#endif    /* we want to ignore HUPs and WINCH while we're busy processing one */    sigaddset(&sa.sa_mask, SIGHUP);    sigaddset(&sa.sa_mask, SIGWINCH);    sa.sa_handler = restart;    if (sigaction(SIGHUP, &sa, NULL) < 0)	ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGHUP)");    if (sigaction(SIGWINCH, &sa, NULL) < 0)	ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGWINCH)");#else    if (!one_process) {	apr_signal(SIGSEGV, sig_coredump);#ifdef SIGBUS	apr_signal(SIGBUS, sig_coredump);#endif /* SIGBUS */#ifdef SIGABORT	apr_signal(SIGABORT, sig_coredump);#endif /* SIGABORT */#ifdef SIGABRT	apr_signal(SIGABRT, sig_coredump);#endif /* SIGABRT */#ifdef SIGILL	apr_signal(SIGILL, sig_coredump);#endif /* SIGILL */#ifdef SIGXCPU	apr_signal(SIGXCPU, SIG_DFL);#endif /* SIGXCPU */#ifdef SIGXFSZ	apr_signal(SIGXFSZ, SIG_DFL);#endif /* SIGXFSZ */    }    apr_signal(SIGTERM, sig_term);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -