in modules/fcgid/fcgid_pm_main.c [159:266]
static void scan_idlelist_zombie(server_rec * main_server)
{
/*
Scan the idle list
1. pick up the node for scan(now-last_activ>g_zombie_scan_interval)
2. check if it's zombie process
3. if it's zombie process, wait() and return to free list
4. return to idle list if it's not zombie process
*/
pid_t thepid;
fcgid_procnode *previous_node, *current_node, *next_node;
fcgid_procnode *check_list_header;
fcgid_procnode *proc_table;
apr_time_t last_active_time;
apr_time_t now = apr_time_now();
fcgid_procnode temp_header;
fcgid_server_conf *sconf =
ap_get_module_config(main_server->module_config,
&fcgid_module);
memset(&temp_header, 0, sizeof(temp_header));
/* Should I check zombie processes in idle list now? */
if (procmgr_must_exit()
|| apr_time_sec(now) - apr_time_sec(lastzombiescan) <=
sconf->zombie_scan_interval)
return;
lastzombiescan = now;
/*
Check the list
*/
proc_table = proctable_get_table_array();
previous_node = proctable_get_idle_list();
check_list_header = &temp_header;
proctable_pm_lock(main_server);
current_node = &proc_table[previous_node->next_index];
while (current_node != proc_table) {
next_node = &proc_table[current_node->next_index];
/* Is it time for zombie check? */
last_active_time = current_node->last_active_time;
if (apr_time_sec(now) - apr_time_sec(last_active_time) >
sconf->zombie_scan_interval) {
/* Unlink from idle list */
previous_node->next_index = current_node->next_index;
/* Link to check list */
current_node->next_index = check_list_header->next_index;
check_list_header->next_index = current_node - proc_table;
}
else
previous_node = current_node;
current_node = next_node;
}
proctable_pm_unlock(main_server);
/*
Now check every node in check list
1) If it's zombie process, wait() and return to free list
2) If it's not zombie process, link it to the tail of idle list
*/
previous_node = check_list_header;
current_node = &proc_table[previous_node->next_index];
while (current_node != proc_table) {
next_node = &proc_table[current_node->next_index];
/* Is it zombie process? */
thepid = current_node->proc_id.pid;
if (proc_wait_process(main_server, current_node) == APR_CHILD_DONE) {
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, main_server,
"mod_fcgid: cleanup zombie process %"
APR_PID_T_FMT, thepid);
/* Unlink from check list */
previous_node->next_index = current_node->next_index;
/* Link to free list */
link_node_to_list(main_server, proctable_get_free_list(),
current_node, proc_table);
}
else
previous_node = current_node;
current_node = next_node;
}
/*
Now link the check list back to the tail of idle list
*/
if (check_list_header->next_index) {
proctable_pm_lock(main_server);
previous_node = proctable_get_idle_list();
current_node = &proc_table[previous_node->next_index];
/* Find the tail of idle list */
while (current_node != proc_table) {
previous_node = current_node;
current_node = &proc_table[current_node->next_index];
}
/* Link check list to the tail of idle list */
previous_node->next_index = check_list_header->next_index;
proctable_pm_unlock(main_server);
}
}