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

📄 worker.c

📁 linux网络服务器工具
💻 C
📖 第 1 页 / 共 5 页
字号:
static int volatile restart_pending;static int volatile is_graceful;static volatile int child_fatal;ap_generation_t volatile ap_my_generation;/* * 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, * but we want to be able to start a shutdown/restart from other sources -- * 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. */static void ap_start_shutdown(int graceful){    mpm_state = AP_MPMQ_STOPPING;    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;    is_graceful = graceful;}/* do a graceful restart if graceful == 1 */static void ap_start_restart(int graceful){    mpm_state = AP_MPMQ_STOPPING;    if (restart_pending == 1) {        /* Probably not an error - don't bother reporting it */        return;    }    restart_pending = 1;    is_graceful = graceful;}static void sig_term(int sig){    ap_start_shutdown(sig == AP_SIG_GRACEFUL_STOP);}static void restart(int sig){    ap_start_restart(sig == AP_SIG_GRACEFUL);}static void set_signals(void){#ifndef NO_USE_SIGACTION    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_STOP */#ifdef SIGPIPE    apr_signal(SIGPIPE, SIG_IGN);#endif /* SIGPIPE */#endif}/***************************************************************** * Here follows a long bunch of generic server bookkeeping stuff... */int ap_graceful_stop_signalled(void)    /* XXX this is really a bad confusing obsolete name     * maybe it should be ap_mpm_process_exiting?     */{    /* note: for a graceful termination, listener_may_exit will be set before     *       workers_may_exit, so check listener_may_exit     */    return listener_may_exit;}/***************************************************************** * Child process main loop. */static void process_socket(apr_pool_t *p, apr_socket_t *sock, int my_child_num,                           int my_thread_num, apr_bucket_alloc_t *bucket_alloc){    conn_rec *current_conn;    long conn_id = ID_FROM_CHILD_THREAD(my_child_num, my_thread_num);    int csd;    ap_sb_handle_t *sbh;    ap_create_sb_handle(&sbh, p, my_child_num, my_thread_num);    apr_os_sock_get(&csd, sock);    current_conn = ap_run_create_connection(p, ap_server_conf, sock,                                            conn_id, sbh, bucket_alloc);    if (current_conn) {        ap_process_connection(current_conn, sock);        ap_lingering_close(current_conn);    }}/* requests_this_child has gone to zero or below.  See if the admin coded   "MaxRequestsPerChild 0", and keep going in that case.  Doing it this way   simplifies the hot path in worker_thread */static void check_infinite_requests(void){    if (ap_max_requests_per_child) {        signal_threads(ST_GRACEFUL);    }    else {        /* wow! if you're executing this code, you may have set a record.         * either this child process has served over 2 billion requests, or         * you're running a threaded 2.0 on a 16 bit machine.         *         * I'll buy pizza and beers at Apachecon for the first person to do         * the former without cheating (dorking with INT_MAX, or running with         * uncommitted performance patches, for example).         *         * for the latter case, you probably deserve a beer too.   Greg Ames         */        requests_this_child = INT_MAX;      /* keep going */    }}static void unblock_signal(int sig){    sigset_t sig_mask;    sigemptyset(&sig_mask);    sigaddset(&sig_mask, sig);#if defined(SIGPROCMASK_SETS_THREAD_MASK)    sigprocmask(SIG_UNBLOCK, &sig_mask, NULL);#else    pthread_sigmask(SIG_UNBLOCK, &sig_mask, NULL);#endif}static void dummy_signal_handler(int sig){    /* XXX If specifying SIG_IGN is guaranteed to unblock a syscall,     *     then we don't need this goofy function.     */}static void *listener_thread(apr_thread_t *thd, void * dummy){    proc_info * ti = dummy;    int process_slot = ti->pid;    apr_pool_t *tpool = apr_thread_pool_get(thd);    void *csd = NULL;    apr_pool_t *ptrans = NULL;            /* Pool for per-transaction stuff */    apr_pollset_t *pollset;    apr_status_t rv;    ap_listen_rec *lr;    int have_idle_worker = 0;    int last_poll_idx = 0;    free(ti);    /* ### check the status */    (void) apr_pollset_create(&pollset, num_listensocks, tpool, 0);    for (lr = ap_listeners; lr != NULL; 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);    }    /* Unblock the signal used to wake this thread up, and set a handler for     * it.     */    unblock_signal(LISTENER_SIGNAL);    apr_signal(LISTENER_SIGNAL, dummy_signal_handler);    /* TODO: Switch to a system where threads reuse the results from earlier       poll calls - manoj */    while (1) {        /* TODO: requests_this_child should be synchronized - aaron */        if (requests_this_child <= 0) {            check_infinite_requests();        }        if (listener_may_exit) break;        if (!have_idle_worker) {            /* the following pops a recycled ptrans pool off a stack             * if there is one, in addition to reserving a worker thread             */            rv = ap_queue_info_wait_for_idler(worker_queue_info,                                              &ptrans);            if (APR_STATUS_IS_EOF(rv)) {                break; /* we've been signaled to die now */            }            else if (rv != APR_SUCCESS) {                ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,                             "apr_queue_info_wait failed. Attempting to "                             " shutdown process gracefully.");                signal_threads(ST_GRACEFUL);                break;            }            have_idle_worker = 1;        }        /* We've already decremented the idle worker count inside         * ap_queue_info_wait_for_idler. */        if ((rv = SAFE_ACCEPT(apr_proc_mutex_lock(accept_mutex)))            != APR_SUCCESS) {            int level = APLOG_EMERG;            if (listener_may_exit) {                break;            }            if (ap_scoreboard_image->parent[process_slot].generation !=                ap_scoreboard_image->global->running_generation) {                level = APLOG_DEBUG; /* common to get these at restart time */            }            ap_log_error(APLOG_MARK, level, rv, ap_server_conf,                         "apr_proc_mutex_lock failed. Attempting to shutdown "                         "process gracefully.");            signal_threads(ST_GRACEFUL);            break;                    /* skip the lock release */        }        if (!ap_listeners->next) {            /* Only one listener, so skip the poll */            lr = ap_listeners;        }        else {            while (!listener_may_exit) {                apr_int32_t numdesc;                const apr_pollfd_t *pdesc;                rv = apr_pollset_poll(pollset, -1, &numdesc, &pdesc);                if (rv != APR_SUCCESS) {                    if (APR_STATUS_IS_EINTR(rv)) {                        continue;                    }                    /* apr_pollset_poll() will only return errors in catastrophic                     * circumstances. Let's try exiting gracefully, for now. */                    ap_log_error(APLOG_MARK, APLOG_ERR, rv,                                 (const server_rec *) ap_server_conf,                                 "apr_pollset_poll: (listen)");                    signal_threads(ST_GRACEFUL);                }                if (listener_may_exit) break;                /* 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;                break;            } /* while */        } /* if/else */        if (!listener_may_exit) {

⌨️ 快捷键说明

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