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

📄 leader.c

📁 apache的软件linux版本
💻 C
📖 第 1 页 / 共 5 页
字号:
                /* find a listener */                lr = last_lr;                do {                    lr = lr->next;                    if (lr == NULL) {                        lr = ap_listeners;                    }                    /* XXX: Should we check for POLLERR? */                    apr_poll_revents_get(&event, lr->sd, pollset);                    if (event & APR_POLLIN) {                        last_lr = lr;                        goto got_fd;                    }                } while (lr != last_lr);            }        }    got_fd:        if (!workers_may_exit) {            rv = lr->accept_func(&csd, lr, ptrans);            /* later we trash rv and rely on csd to indicate success/failure */            AP_DEBUG_ASSERT(rv == APR_SUCCESS || !csd);            if (rv == APR_EGENERAL) {                /* E[NM]FILE, ENOMEM, etc */                resource_shortage = 1;                signal_threads(ST_GRACEFUL);            }            if ((rv = SAFE_ACCEPT(apr_proc_mutex_unlock(accept_mutex)))                != APR_SUCCESS) {                int level = APLOG_EMERG;                if (workers_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_unlock failed. Attempting to "                             "shutdown process gracefully.");                signal_threads(ST_GRACEFUL);            }            if (csd != NULL) {                is_listener = 0;                worker_stack_awaken_next(idle_worker_stack);                process_socket(ptrans, csd, process_slot,                               thread_slot, bucket_alloc);                apr_pool_clear(ptrans);                requests_this_child--;            }            if ((ap_mpm_pod_check(pod) == APR_SUCCESS) ||                (ap_my_generation !=                 ap_scoreboard_image->global->running_generation)) {                signal_threads(ST_GRACEFUL);                break;            }        }        else {            if ((rv = SAFE_ACCEPT(apr_proc_mutex_unlock(accept_mutex)))                != APR_SUCCESS) {                ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,                             "apr_proc_mutex_unlock failed. Attempting to "                             "shutdown process gracefully.");                signal_threads(ST_GRACEFUL);            }            break;        }    }    dying = 1;    ap_scoreboard_image->parent[process_slot].quiescing = 1;    worker_stack_term(idle_worker_stack);    ap_update_child_status_from_indexes(process_slot, thread_slot,        (dying) ? SERVER_DEAD : SERVER_GRACEFUL, (request_rec *) NULL);    apr_bucket_alloc_destroy(bucket_alloc);    apr_thread_exit(thd, APR_SUCCESS);    return NULL;}static int check_signal(int signum){    switch (signum) {    case SIGTERM:    case SIGINT:        return 1;    }    return 0;}/* XXX under some circumstances not understood, children can get stuck *     in start_threads forever trying to take over slots which will *     never be cleaned up; for now there is an APLOG_DEBUG message issued *     every so often when this condition occurs */static void * APR_THREAD_FUNC start_threads(apr_thread_t *thd, void *dummy){    thread_starter *ts = dummy;    apr_thread_t **threads = ts->threads;    apr_threadattr_t *thread_attr = ts->threadattr;    int child_num_arg = ts->child_num_arg;    int my_child_num = child_num_arg;    proc_info *my_info;    apr_status_t rv;    int i;    int threads_created = 0;    int loops;    int prev_threads_created;    idle_worker_stack = worker_stack_create(pchild, ap_threads_per_child);    if (idle_worker_stack == NULL) {        ap_log_error(APLOG_MARK, APLOG_ALERT, 0, ap_server_conf,                     "worker_stack_create() failed");        clean_child_exit(APEXIT_CHILDFATAL);    }    worker_wakeups = (worker_wakeup_info **)        apr_palloc(pchild, sizeof(worker_wakeup_info *) *                   ap_threads_per_child);    loops = prev_threads_created = 0;    while (1) {        for (i = 0; i < ap_threads_per_child; i++) {            int status = ap_scoreboard_image->servers[child_num_arg][i].status;            worker_wakeup_info *wakeup;            if (status != SERVER_GRACEFUL && status != SERVER_DEAD) {                continue;            }            wakeup = worker_wakeup_create(pchild);            if (wakeup == NULL) {                ap_log_error(APLOG_MARK, APLOG_ALERT|APLOG_NOERRNO, 0,                             ap_server_conf, "worker_wakeup_create failed");                clean_child_exit(APEXIT_CHILDFATAL);            }            worker_wakeups[threads_created] = wakeup;            my_info = (proc_info *)malloc(sizeof(proc_info));            if (my_info == NULL) {                ap_log_error(APLOG_MARK, APLOG_ALERT, errno, ap_server_conf,                             "malloc: out of memory");                clean_child_exit(APEXIT_CHILDFATAL);            }            my_info->pid = my_child_num;            my_info->tid = i;            my_info->sd = 0;                    /* We are creating threads right now */            ap_update_child_status_from_indexes(my_child_num, i,                                                SERVER_STARTING, NULL);            /* We let each thread update its own scoreboard entry.  This is             * done because it lets us deal with tid better.             */            rv = apr_thread_create(&threads[i], thread_attr,                                    worker_thread, my_info, pchild);            if (rv != APR_SUCCESS) {                ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,                    "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. */                apr_sleep(10 * APR_USEC_PER_SEC);                clean_child_exit(APEXIT_CHILDFATAL);            }            threads_created++;        }        if (start_thread_may_exit || threads_created == ap_threads_per_child) {            break;        }        /* wait for previous generation to clean up an entry */        apr_sleep(1 * APR_USEC_PER_SEC);        ++loops;        if (loops % 120 == 0) { /* every couple of minutes */            if (prev_threads_created == threads_created) {                ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,                             "child %" APR_PID_T_FMT " isn't taking over "                             "slots very quickly (%d of %d)",                             ap_my_pid, threads_created, ap_threads_per_child);            }            prev_threads_created = threads_created;        }    }        /* What state should this child_main process be listed as in the      * scoreboard...?     *  ap_update_child_status_from_indexes(my_child_num, i, SERVER_STARTING,      *                                      (request_rec *) NULL);     *      *  This state should be listed separately in the scoreboard, in some kind     *  of process_status, not mixed in with the worker threads' status.        *  "life_status" is almost right, but it's in the worker's structure, and      *  the name could be clearer.   gla     */    apr_thread_exit(thd, APR_SUCCESS);    return NULL;}static void join_workers(apr_thread_t **threads){    int i;    apr_status_t rv, thread_rv;    for (i = 0; i < ap_threads_per_child; i++) {        if (threads[i]) { /* if we ever created this thread */            rv = apr_thread_join(&thread_rv, threads[i]);            if (rv != APR_SUCCESS) {                ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,                             "apr_thread_join: unable to join worker "                             "thread %d",                             i);            }        }    }}static void join_start_thread(apr_thread_t *start_thread_id){    apr_status_t rv, thread_rv;    start_thread_may_exit = 1; /* tell it to give up in case it is still                                 * trying to take over slots from a                                 * previous generation                                */    rv = apr_thread_join(&thread_rv, start_thread_id);    if (rv != APR_SUCCESS) {        ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,                     "apr_thread_join: unable to join the start "                     "thread");    }}static void child_main(int child_num_arg){    apr_thread_t **threads;    apr_status_t rv;    thread_starter *ts;    apr_threadattr_t *thread_attr;    apr_thread_t *start_thread_id;    mpm_state = AP_MPMQ_STARTING; /* for benefit of any hooks that run as this                                  * child initializes                                  */    ap_my_pid = getpid();    ap_fatal_signal_child_setup(ap_server_conf);    apr_pool_create(&pchild, pconf);    /*stuff to do before we switch id's, so we have permissions.*/    ap_reopen_scoreboard(pchild, NULL, 0);    rv = SAFE_ACCEPT(apr_proc_mutex_child_init(&accept_mutex, ap_lock_fname,                                               pchild));    if (rv != APR_SUCCESS) {        ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,                     "Couldn't initialize cross-process lock in child");        clean_child_exit(APEXIT_CHILDFATAL);    }    if (unixd_setup_child()) {        clean_child_exit(APEXIT_CHILDFATAL);    }    ap_run_child_init(pchild, ap_server_conf);    /* done with init critical section */    /* Just use the standard apr_setup_signal_thread to block all signals     * from being received.  The child processes no longer use signals for     * any communication with the parent process.     */    rv = apr_setup_signal_thread();    if (rv != APR_SUCCESS) {        ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,                     "Couldn't initialize signal thread");        clean_child_exit(APEXIT_CHILDFATAL);    }    if (ap_max_requests_per_child) {        requests_this_child = ap_max_requests_per_child;    }    else {        /* coding a value of zero means infinity */        requests_this_child = INT_MAX;    }        /* Setup worker threads */    /* clear the storage; we may not create all our threads immediately,      * and we want a 0 entry to indicate a thread which was not created     */    threads = (apr_thread_t **)calloc(1,                                 sizeof(apr_thread_t *) * ap_threads_per_child);    if (threads == NULL) {        ap_log_error(APLOG_MARK, APLOG_ALERT, errno, ap_server_conf,                     "malloc: out of memory");        clean_child_exit(APEXIT_CHILDFATAL);    }    ts = (thread_starter *)apr_palloc(pchild, sizeof(*ts));    apr_threadattr_create(&thread_attr, pchild);    /* 0 means PTHREAD_CREATE_JOINABLE */    apr_threadattr_detach_set(thread_attr, 0);    ts->threads = threads;    ts->child_num_arg = child_num_arg;    ts->threadattr = thread_attr;    rv = apr_thread_create(&start_thread_id, thread_attr, start_threads,                           ts, pchild);    if (rv != APR_SUCCESS) {        ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,                     "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. */        apr_sleep(10 * APR_USEC_PER_SEC);        clean_child_exit(APEXIT_CHILDFATAL);    }    mpm_state = AP_MPMQ_RUNNING;    /* If we are only running in one_process mode, we will want to     * still handle signals. */    if (one_process) {        /* Block until we get a terminating signal. */        apr_signal_thread(check_signal);        /* make sure the start thread has finished; signal_threads()          * and join_workers() depend on that         */        /* XXX join_start_thread() won't be awakened if one of our         *     threads encounters a critical error and attempts to         *     shutdown this child         */        join_start_thread(start_thread_id);        signal_threads(ST_UNGRACEFUL); /* helps us terminate a little more                           * quickly than the dispatch of the signal thread                           * beats the Pipe of Death and the browsers                           */        /* A terminating signal was received. Now join each of the         * workers to clean them up.         *   If the worker already exited, then the join frees         *   their resources and returns.         *   If the worker hasn't exited, then this blocks until         *   they have (then cleans up).         */        join_workers(threads);    }    else { /* !one_process */        /* remove SIGTERM from the set of blocked signals...  if one of         * the other threads in the process needs to take us down         * (e.g., for MaxRequestsPerChild) it will send us SIGTERM         */        unblock_signal(SIGTERM);        join_start_thread(start_thread_id);        join_workers(threads);    }    free(threads);    clean_child_exit(resource_shortage ? APEXIT_CHILDSICK : 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) {

⌨️ 快捷键说明

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