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

📄 prefork.c

📁 Apache官方在今天放出产品系列2.2的最新版本2.2.11的源码包 最流行的HTTP服务器软件之一
💻 C
📖 第 1 页 / 共 4 页
字号:
    struct sigaction sa;#endif    if (!one_process) {        ap_fatal_signal_setup(ap_server_conf, pconf);    }#ifndef NO_USE_SIGACTION    sigemptyset(&sa.sa_mask);    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 AP_SIG_GRACEFUL_STOP    if (sigaction(AP_SIG_GRACEFUL_STOP, &sa, NULL) < 0)        ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,                     "sigaction(" AP_SIG_GRACEFUL_STOP_STRING ")");#endif#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 AP_SIG_GRACEFUL while we're busy     * processing one     */    sigaddset(&sa.sa_mask, SIGHUP);    sigaddset(&sa.sa_mask, AP_SIG_GRACEFUL);    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(AP_SIG_GRACEFUL, &sa, NULL) < 0)        ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(" AP_SIG_GRACEFUL_STRING ")");#else    if (!one_process) {#ifdef SIGXCPU        apr_signal(SIGXCPU, SIG_DFL);#endif /* SIGXCPU */#ifdef SIGXFSZ        apr_signal(SIGXFSZ, SIG_DFL);#endif /* SIGXFSZ */    }    apr_signal(SIGTERM, sig_term);#ifdef SIGHUP    apr_signal(SIGHUP, restart);#endif /* SIGHUP */#ifdef AP_SIG_GRACEFUL    apr_signal(AP_SIG_GRACEFUL, restart);#endif /* AP_SIG_GRACEFUL */#ifdef AP_SIG_GRACEFUL_STOP    apr_signal(AP_SIG_GRACEFUL_STOP, sig_term);#endif /* AP_SIG_GRACEFUL */#ifdef SIGPIPE    apr_signal(SIGPIPE, SIG_IGN);#endif /* SIGPIPE */#endif}/***************************************************************** * Child process main loop. * The following vars are static to avoid getting clobbered by longjmp(); * they are really private to child_main. */static int requests_this_child;static int num_listensocks = 0;int ap_graceful_stop_signalled(void){    /* not ever called anymore... */    return 0;}static void child_main(int child_num_arg){    apr_pool_t *ptrans;    apr_allocator_t *allocator;    apr_status_t status;    int i;    ap_listen_rec *lr;    apr_pollset_t *pollset;    ap_sb_handle_t *sbh;    apr_bucket_alloc_t *bucket_alloc;    int last_poll_idx = 0;    mpm_state = AP_MPMQ_STARTING; /* for benefit of any hooks that run as this                                   * child initializes                                   */    my_child_num = child_num_arg;    ap_my_pid = getpid();    requests_this_child = 0;    ap_fatal_signal_child_setup(ap_server_conf);    /* Get a sub context for global allocations in this child, so that     * we can have cleanups occur when the child exits.     */    apr_allocator_create(&allocator);    apr_allocator_max_free_set(allocator, ap_max_mem_free);    apr_pool_create_ex(&pchild, pconf, NULL, allocator);    apr_allocator_owner_set(allocator, pchild);    apr_pool_create(&ptrans, pchild);    apr_pool_tag(ptrans, "transaction");    /* needs to be done before we switch UIDs so we have permissions */    ap_reopen_scoreboard(pchild, NULL, 0);    status = apr_proc_mutex_child_init(&accept_mutex, ap_lock_fname, pchild);    if (status != APR_SUCCESS) {        ap_log_error(APLOG_MARK, APLOG_EMERG, status, ap_server_conf,                     "Couldn't initialize cross-process lock in child "                     "(%s) (%d)", ap_lock_fname, ap_accept_lock_mech);        clean_child_exit(APEXIT_CHILDFATAL);    }    if (unixd_setup_child()) {        clean_child_exit(APEXIT_CHILDFATAL);    }    ap_run_child_init(pchild, ap_server_conf);    ap_create_sb_handle(&sbh, pchild, my_child_num, 0);    (void) ap_update_child_status(sbh, SERVER_READY, (request_rec *) NULL);    /* Set up the pollfd array */    /* ### check the status */    (void) apr_pollset_create(&pollset, num_listensocks, pchild, 0);    for (lr = ap_listeners, i = num_listensocks; i--; lr = lr->next) {        apr_pollfd_t pfd = { 0 };        pfd.desc_type = APR_POLL_SOCKET;        pfd.desc.s = lr->sd;        pfd.reqevents = APR_POLLIN;        pfd.client_data = lr;        /* ### check the status */        (void) apr_pollset_add(pollset, &pfd);    }    mpm_state = AP_MPMQ_RUNNING;    bucket_alloc = apr_bucket_alloc_create(pchild);    /* die_now is set when AP_SIG_GRACEFUL is received in the child;     * shutdown_pending is set when SIGTERM is received when running     * in single process mode.  */    while (!die_now && !shutdown_pending) {        conn_rec *current_conn;        void *csd;        /*         * (Re)initialize this child to a pre-connection state.         */        apr_pool_clear(ptrans);        if ((ap_max_requests_per_child > 0             && requests_this_child++ >= ap_max_requests_per_child)) {            clean_child_exit(0);        }        (void) ap_update_child_status(sbh, SERVER_READY, (request_rec *) NULL);        /*         * Wait for an acceptable connection to arrive.         */        /* Lock around "accept", if necessary */        SAFE_ACCEPT(accept_mutex_on());        if (num_listensocks == 1) {            /* There is only one listener record, so refer to that one. */            lr = ap_listeners;        }        else {            /* multiple listening sockets - need to poll */            for (;;) {                apr_int32_t numdesc;                const apr_pollfd_t *pdesc;                /* timeout == -1 == wait forever */                status = apr_pollset_poll(pollset, -1, &numdesc, &pdesc);                if (status != APR_SUCCESS) {                    if (APR_STATUS_IS_EINTR(status)) {                        if (one_process && shutdown_pending) {                            return;                        }                        else if (die_now) {                            /* In graceful stop/restart; drop the mutex                             * and terminate the child. */                            SAFE_ACCEPT(accept_mutex_off());                            clean_child_exit(0);                        }                        continue;                    }                    /* Single Unix documents select as returning errnos                     * EBADF, EINTR, and EINVAL... and in none of those                     * cases does it make sense to continue.  In fact                     * on Linux 2.0.x we seem to end up with EFAULT                     * occasionally, and we'd loop forever due to it.                     */                    ap_log_error(APLOG_MARK, APLOG_ERR, status,                                 ap_server_conf, "apr_pollset_poll: (listen)");                    SAFE_ACCEPT(accept_mutex_off());                    clean_child_exit(1);                }                /* We can always use pdesc[0], but sockets at position N                 * could end up completely starved of attention in a very                 * busy server. Therefore, we round-robin across the                 * returned set of descriptors. While it is possible that                 * the returned set of descriptors might flip around and                 * continue to starve some sockets, we happen to know the                 * internal pollset implementation retains ordering                 * stability of the sockets. Thus, the round-robin should                 * ensure that a socket will eventually be serviced.                 */                if (last_poll_idx >= numdesc)                    last_poll_idx = 0;                /* Grab a listener record from the client_data of the poll                 * descriptor, and advance our saved index to round-robin                 * the next fetch.                 *                 * ### hmm... this descriptor might have POLLERR rather                 * ### than POLLIN                 */                lr = pdesc[last_poll_idx++].client_data;                goto got_fd;            }        }    got_fd:        /* if we accept() something we don't want to die, so we have to         * defer the exit         */        status = lr->accept_func(&csd, lr, ptrans);        SAFE_ACCEPT(accept_mutex_off());      /* unlock after "accept" */        if (status == APR_EGENERAL) {            /* resource shortage or should-not-occur occured */            clean_child_exit(1);        }        else if (status != APR_SUCCESS) {            continue;        }        /*         * We now have a connection, so set it up with the appropriate         * socket options, file descriptors, and read/write buffers.         */        current_conn = ap_run_create_connection(ptrans, ap_server_conf, csd, my_child_num, sbh, bucket_alloc);        if (current_conn) {            ap_process_connection(current_conn, csd);            ap_lingering_close(current_conn);        }        /* Check the pod and the generation number after processing a         * connection so that we'll go away if a graceful restart occurred         * while we were processing the connection or we are the lucky         * idle server process that gets to die.         */        if (ap_mpm_pod_check(pod) == APR_SUCCESS) { /* selected as idle? */            die_now = 1;        }        else if (ap_my_generation !=                 ap_scoreboard_image->global->running_generation) { /* restart? */            /* yeah, this could be non-graceful restart, in which case the             * parent will kill us soon enough, but why bother checking?             */            die_now = 1;        }    }    clean_child_exit(0);}static int make_child(server_rec *s, int slot){    int pid;    if (slot + 1 > ap_max_daemons_limit) {        ap_max_daemons_limit = slot + 1;    }    if (one_process) {        apr_signal(SIGHUP, sig_term);        /* Don't catch AP_SIG_GRACEFUL in ONE_PROCESS mode :) */        apr_signal(SIGINT, sig_term);#ifdef SIGQUIT        apr_signal(SIGQUIT, SIG_DFL);#endif        apr_signal(SIGTERM, sig_term);        child_main(slot);        return 0;    }    (void) ap_update_child_status_from_indexes(slot, 0, SERVER_STARTING,                                               (request_rec *) NULL);#ifdef _OSD_POSIX    /* BS2000 requires a "special" version of fork() before a setuid() call */    if ((pid = os_fork(unixd_config.user_name)) == -1) {#elif defined(TPF)    if ((pid = os_fork(s, slot)) == -1) {#else    if ((pid = fork()) == -1) {#endif        ap_log_error(APLOG_MARK, APLOG_ERR, errno, s, "fork: Unable to fork new process");        /* fork didn't succeed. Fix the scoreboard or else         * it will say SERVER_STARTING forever and ever         */        (void) ap_update_child_status_from_indexes(slot, 0, SERVER_DEAD,                                                   (request_rec *) NULL);        /* 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.         */        sleep(10);        return -1;    }    if (!pid) {#ifdef HAVE_BINDPROCESSOR        /* by default AIX binds to a single processor         * this bit unbinds children which will then bind to another cpu         */        int status = bindprocessor(BINDPROCESS, (int)getpid(),                                   PROCESSOR_CLASS_ANY);        if (status != OK) {            ap_log_error(APLOG_MARK, APLOG_WARNING, errno,                         ap_server_conf, "processor unbind failed %d", status);        }#endif        RAISE_SIGSTOP(MAKE_CHILD);        AP_MONCONTROL(1);        /* Disable the parent's signal handlers and set up proper handling in         * the child.         */        apr_signal(SIGHUP, just_die);        apr_signal(SIGTERM, just_die);        /* The child process just closes listeners on AP_SIG_GRACEFUL.         * The pod is used for signalling the graceful restart.         */

⌨️ 快捷键说明

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