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

📄 event.c

📁 Apache官方在今天放出产品系列2.2的最新版本2.2.11的源码包 最流行的HTTP服务器软件之一
💻 C
📖 第 1 页 / 共 5 页
字号:
static void just_die(int sig){    clean_child_exit(0);}/***************************************************************** * Connection structures and accounting... *//* volatile just in case */static int volatile shutdown_pending;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 int process_socket(apr_pool_t * p, apr_socket_t * sock,                          conn_state_t * cs, int my_child_num,                          int my_thread_num){    conn_rec *c;    listener_poll_type *pt;    long conn_id = ID_FROM_CHILD_THREAD(my_child_num, my_thread_num);    int csd;    int rc;    apr_time_t time_now = 0;    ap_sb_handle_t *sbh;    ap_create_sb_handle(&sbh, p, my_child_num, my_thread_num);    apr_os_sock_get(&csd, sock);    time_now = apr_time_now();    if (cs == NULL) {           /* This is a new connection */        cs = apr_pcalloc(p, sizeof(conn_state_t));        pt = apr_pcalloc(p, sizeof(*pt));        cs->bucket_alloc = apr_bucket_alloc_create(p);        c = ap_run_create_connection(p, ap_server_conf, sock,                                     conn_id, sbh, cs->bucket_alloc);        cs->c = c;        c->cs = cs;        cs->p = p;        cs->pfd.desc_type = APR_POLL_SOCKET;        cs->pfd.reqevents = APR_POLLIN;        cs->pfd.desc.s = sock;        pt->type = PT_CSD;        pt->status = 1;        pt->baton = cs;        cs->pfd.client_data = pt;        ap_update_vhost_given_ip(c);        rc = ap_run_pre_connection(c, sock);        if (rc != OK && rc != DONE) {            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,                         "process_socket: connection aborted");            c->aborted = 1;        }        /**         * XXX If the platform does not have a usable way of bundling         * accept() with a socket readability check, like Win32,         * and there are measurable delays before the         * socket is readable due to the first data packet arriving,         * it might be better to create the cs on the listener thread         * with the state set to CONN_STATE_CHECK_REQUEST_LINE_READABLE         *         * FreeBSD users will want to enable the HTTP accept filter         * module in their kernel for the highest performance         * When the accept filter is active, sockets are kept in the         * kernel until a HTTP request is received.         */        cs->state = CONN_STATE_READ_REQUEST_LINE;    }    else {        c = cs->c;        c->sbh = sbh;    }    if (c->clogging_input_filters && !c->aborted) {        /* Since we have an input filter which 'cloggs' the input stream,         * like mod_ssl, lets just do the normal read from input filters,         * like the Worker MPM does.         */        ap_run_process_connection(c);        cs->state = CONN_STATE_LINGER;    }    if (cs->state == CONN_STATE_READ_REQUEST_LINE) {        if (!c->aborted) {            ap_run_process_connection(c);            /* state will be updated upon return             * fall thru to either wait for readability/timeout or             * do lingering close             */        }        else {            cs->state = CONN_STATE_LINGER;        }    }    if (cs->state == CONN_STATE_LINGER) {        ap_lingering_close(c);        apr_pool_clear(p);        ap_push_pool(worker_queue_info, p);        return 0;    }    else if (cs->state == CONN_STATE_CHECK_REQUEST_LINE_READABLE) {        apr_status_t rc;        listener_poll_type *pt = (listener_poll_type *) cs->pfd.client_data;        /* It greatly simplifies the logic to use a single timeout value here         * because the new element can just be added to the end of the list and         * it will stay sorted in expiration time sequence.  If brand new         * sockets are sent to the event thread for a readability check, this         * will be a slight behavior change - they use the non-keepalive         * timeout today.  With a normal client, the socket will be readable in         * a few milliseconds anyway.         */        cs->expiration_time = ap_server_conf->keep_alive_timeout + time_now;        apr_thread_mutex_lock(timeout_mutex);        APR_RING_INSERT_TAIL(&timeout_head, cs, conn_state_t, timeout_list);        pt->status = 0;        /* Add work to pollset. These are always read events */        rc = apr_pollset_add(event_pollset, &cs->pfd);        apr_thread_mutex_unlock(timeout_mutex);        if (rc != APR_SUCCESS) {            ap_log_error(APLOG_MARK, APLOG_ERR, rc, ap_server_conf,                         "process_socket: apr_pollset_add failure");            AP_DEBUG_ASSERT(rc == APR_SUCCESS);        }    }    return 1;}/* 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 apr_status_t push2worker(const apr_pollfd_t * pfd,                                apr_pollset_t * pollset){    listener_poll_type *pt = (listener_poll_type *) pfd->client_data;    conn_state_t *cs = (conn_state_t *) pt->baton;    apr_status_t rc;    if (pt->status == 1) {        return 0;    }    pt->status = 1;    rc = apr_pollset_remove(pollset, pfd);    /*     * Some of the pollset backends, like KQueue or Epoll     * automagically remove the FD if the socket is closed,     * therefore, we can accept _SUCCESS or _NOTFOUND,     * and we still want to keep going     */    if (rc != APR_SUCCESS && rc != APR_NOTFOUND) {        cs->state = CONN_STATE_LINGER;    }    rc = ap_queue_push(worker_queue, cs->pfd.desc.s, cs, cs->p);    if (rc != APR_SUCCESS) {        /* trash the connection; we couldn't queue the connected         * socket to a worker         */        apr_bucket_alloc_destroy(cs->bucket_alloc);        apr_socket_close(cs->pfd.desc.s);        ap_log_error(APLOG_MARK, APLOG_CRIT, rc,                     ap_server_conf, "push2worker: ap_queue_push failed");        apr_pool_clear(cs->p);

⌨️ 快捷键说明

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