static void scan_errorlist()

in modules/fcgid/fcgid_pm_main.c [269:365]


static void scan_errorlist(server_rec * main_server)
{
    /*
       kill() and wait() every node in error list
       put them back to free list after that
     */
    void *dummy;
    fcgid_procnode *previous_node, *current_node, *next_node;
    apr_time_t now = apr_time_now();
    fcgid_procnode *error_list_header = proctable_get_error_list();
    fcgid_procnode *free_list_header = proctable_get_free_list();
    fcgid_procnode *proc_table = proctable_get_table_array();
    fcgid_procnode temp_error_header;
    fcgid_server_conf *sconf =
        ap_get_module_config(main_server->module_config,
                             &fcgid_module);
    int graceful_terminations = 0;

    /* Should I check the busy list? */
    if (procmgr_must_exit()
        || apr_time_sec(now) - apr_time_sec(lasterrorscan) <=
        sconf->error_scan_interval)
        return;
    lasterrorscan = now;

    /* Try wait dead processes, restore to free list */
    /* Note: I can't keep the lock during the scan */
    proctable_pm_lock(main_server);
    temp_error_header.next_index = error_list_header->next_index;
    error_list_header->next_index = 0;
    proctable_pm_unlock(main_server);

    previous_node = &temp_error_header;
    current_node = &proc_table[previous_node->next_index];
    while (current_node != proc_table) {
        next_node = &proc_table[current_node->next_index];

        if (proc_wait_process(main_server, current_node) != APR_CHILD_NOTDONE) {
            /* Unlink from error list */
            previous_node->next_index = current_node->next_index;

            /* Link to free list */
            current_node->next_index = free_list_header->next_index;
            free_list_header->next_index = current_node - proc_table;
        }
        else
            previous_node = current_node;

        current_node = next_node;
    }

    /* Kill the left processes, wait() them in the next round */
    for (current_node = &proc_table[temp_error_header.next_index];
         current_node != proc_table;
         current_node = &proc_table[current_node->next_index]) {
        /* Try gracefully first */
        dummy = NULL;
        apr_pool_userdata_get(&dummy, HAS_GRACEFUL_KILL,
                              current_node->proc_pool);
        if (!dummy) {
            proc_kill_gracefully(current_node, main_server);
            ++graceful_terminations;
            apr_pool_userdata_set("set", HAS_GRACEFUL_KILL,
                                  apr_pool_cleanup_null,
                                  current_node->proc_pool);
        }
        else {
#ifndef WIN32
            ap_log_error(APLOG_MARK, APLOG_WARNING, 0, main_server,
#else
            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, main_server,
#endif
                         "mod_fcgid: process %" APR_PID_T_FMT
                         " graceful kill fail, sending SIGKILL",
                         current_node->proc_id.pid);
            proc_kill_force(current_node, main_server);
        }
    }

    /* Link the temp error list back */
    proctable_pm_lock(main_server);
    /* Find the tail of error list */
    previous_node = error_list_header;
    current_node = &proc_table[previous_node->next_index];
    while (current_node != proc_table) {
        previous_node = current_node;
        current_node = &proc_table[current_node->next_index];
    }
    previous_node->next_index = temp_error_header.next_index;
    proctable_pm_unlock(main_server);

    if (graceful_terminations) {
        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, main_server,
                     "mod_fcgid: gracefully terminated %d processes",
                     graceful_terminations);
    }
}