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);
}
}