Lines 401-464
Link Here
|
401 |
return 0; |
401 |
return 0; |
402 |
} |
402 |
} |
403 |
|
403 |
|
404 |
static void kill_all_subprocess(server_rec *main_server) |
404 |
static void kill_all_subprocess(server_rec * main_server, int graceful) |
405 |
{ |
405 |
{ |
406 |
apr_time_t waittime = 1024 * 16; |
406 |
int wait_attempts = 0; |
407 |
size_t i, table_size = proctable_get_table_size(); |
|
|
408 |
int not_dead_yet; |
409 |
int cur_action, next_action; |
410 |
apr_time_t starttime = apr_time_now(); |
411 |
struct { |
412 |
action_t action; |
413 |
apr_time_t action_time; |
414 |
} action_table[] = { |
415 |
{DO_NOTHING, 0}, /* dummy entry for iterations where |
416 |
* we reap children but take no action |
417 |
* against stragglers |
418 |
*/ |
419 |
{KILL_GRACEFULLY, apr_time_from_sec(0)}, |
420 |
{KILL_GRACEFULLY, apr_time_from_sec(1)}, |
421 |
{KILL_FORCEFULLY, apr_time_from_sec(8)}, |
422 |
{HARD_WAIT, apr_time_from_sec(8)} |
423 |
}; |
424 |
fcgid_procnode *proc_table = proctable_get_table_array(); |
407 |
fcgid_procnode *proc_table = proctable_get_table_array(); |
|
|
408 |
fcgid_procnode *free_list_header = proctable_get_free_list(); |
409 |
fcgid_procnode *busy_list_header = proctable_get_busy_list(); |
410 |
fcgid_procnode *idle_list_header = proctable_get_idle_list(); |
411 |
fcgid_procnode *error_list_header = proctable_get_error_list(); |
412 |
fcgid_procnode *previous_node, *current_node, *next_node; |
425 |
|
413 |
|
426 |
next_action = 1; |
414 |
/* We'll scan the idle and busy lists signaling each process to shut down |
427 |
do { |
415 |
The processes in the idle list will be moved to the error list |
428 |
apr_sleep(waittime); |
416 |
Processes in the busy list will be moved to the error list only during a hard shutdown/restart. |
429 |
/* don't let waittime get longer than 1 second; otherwise, we don't |
417 |
After we've moved everything to the error list that needs to die, we walk it until everything is cleaned up */ |
430 |
* react quickly to the last child exiting, and taking action can |
|
|
431 |
* be delayed |
432 |
*/ |
433 |
waittime = waittime * 4; |
434 |
if (waittime > apr_time_from_sec(1)) { |
435 |
waittime = apr_time_from_sec(1); |
436 |
} |
437 |
|
418 |
|
438 |
/* see what action to take, if any */ |
419 |
proctable_pm_lock(main_server); |
439 |
if (action_table[next_action].action_time <= apr_time_now() - starttime) { |
420 |
|
440 |
cur_action = next_action; |
421 |
/* signal all processes in the error list once */ |
441 |
++next_action; |
422 |
previous_node = error_list_header; |
|
|
423 |
current_node = &proc_table[previous_node->next_index]; |
424 |
while (current_node != proc_table) { |
425 |
proc_kill_gracefully(current_node, main_server); |
426 |
previous_node = current_node; |
427 |
current_node = &proc_table[current_node->next_index]; |
428 |
} |
429 |
|
430 |
/* Previous node is going to be the tail end of the error list. Attach all the idle list to it and signal those processes to exit */ |
431 |
current_node = &proc_table[idle_list_header->next_index]; |
432 |
if (current_node != proc_table) { |
433 |
previous_node->next_index = (current_node - proc_table); |
434 |
idle_list_header->next_index = 0; |
435 |
while ( current_node != proc_table ) { |
436 |
proc_kill_gracefully( current_node, main_server ); |
437 |
current_node->diewhy = FCGID_DIE_SHUTDOWN; |
438 |
previous_node = current_node; |
439 |
current_node = &proc_table[ current_node->next_index ]; |
442 |
} |
440 |
} |
443 |
else { |
441 |
} |
444 |
cur_action = 0; /* index of DO_NOTHING entry */ |
|
|
445 |
} |
446 |
|
442 |
|
447 |
/* now see who is done */ |
443 |
/* If this is a forced shutdown, link the busy list to the error list */ |
448 |
not_dead_yet = 0; |
444 |
current_node = &proc_table[busy_list_header->next_index]; |
449 |
for (i = 0; i < table_size; i++) { |
445 |
if (!graceful && current_node != proc_table) { |
450 |
if (!proc_table[i].proc_pool) { |
446 |
previous_node->next_index = (current_node - proc_table); |
451 |
continue; /* unused */ |
447 |
busy_list_header->next_index = 0; |
452 |
} |
448 |
} |
|
|
449 |
|
450 |
/* Signal processes in the busy list */ |
451 |
while (current_node != proc_table) { |
452 |
proc_kill_gracefully( current_node, main_server ); |
453 |
current_node->diewhy = FCGID_DIE_SHUTDOWN; |
454 |
current_node = &proc_table[ current_node->next_index ]; |
455 |
} |
453 |
|
456 |
|
454 |
if (!reclaim_one_pid(main_server, &proc_table[i], |
457 |
/* Now clear the error list into the free list... |
455 |
action_table[cur_action].action)) { |
458 |
We are blocking all the bridged processes from completing during this timeframe |
456 |
++not_dead_yet; |
459 |
since they can't aquire the mutex to check the process tables. This should be |
|
|
460 |
acceptable for both graceful and hard restarts. This loop should end rapidly |
461 |
with graceful restarts and connection interruptions are going to happen regardless |
462 |
with hard restarts. */ |
463 |
while (error_list_header->next_index != 0) { |
464 |
apr_sleep(apr_time_from_sec(1)); |
465 |
wait_attempts++; |
466 |
previous_node = error_list_header; |
467 |
current_node = &proc_table[previous_node->next_index]; |
468 |
while (current_node != proc_table) { |
469 |
next_node = &proc_table[current_node->next_index]; |
470 |
if (proc_wait_process(main_server, current_node) == APR_CHILD_NOTDONE |
471 |
&& wait_attempts < FCGID_PM_MAX_SHUTDOWN_WAIT_ATTEMPTS ) { |
472 |
/* kill it hard and check again in 1 second */ |
473 |
proc_kill_force( current_node, main_server ); |
474 |
previous_node = current_node; |
475 |
}else { |
476 |
/* Unlink from error list */ |
477 |
previous_node->next_index = current_node->next_index; |
478 |
|
479 |
/* Link to free list */ |
480 |
current_node->next_index = free_list_header->next_index; |
481 |
free_list_header->next_index = current_node - proc_table; |
457 |
} |
482 |
} |
|
|
483 |
current_node = next_node; |
458 |
} |
484 |
} |
|
|
485 |
} |
486 |
|
487 |
/* At this point in a graceful restart, the busy and free lists have all the process nodes */ |
488 |
/* In a forced restart, all nodes are in the free list */ |
459 |
|
489 |
|
460 |
} while (not_dead_yet && |
490 |
proctable_pm_unlock(main_server); |
461 |
action_table[cur_action].action != HARD_WAIT); |
|
|
462 |
} |
491 |
} |
463 |
|
492 |
|
464 |
/* This should be proposed as a stand-alone improvement to the httpd module, |
493 |
/* This should be proposed as a stand-alone improvement to the httpd module, |
Lines 578-584
Link Here
|
578 |
procinfo.gid = command->gid; |
607 |
procinfo.gid = command->gid; |
579 |
procinfo.userdir = command->userdir; |
608 |
procinfo.userdir = command->userdir; |
580 |
if ((rv = |
609 |
if ((rv = |
581 |
apr_pool_create(&procnode->proc_pool, configpool)) != APR_SUCCESS |
610 |
apr_pool_create(&procnode->proc_pool, main_server->process->pool)) != APR_SUCCESS |
582 |
|| (procinfo.proc_environ = |
611 |
|| (procinfo.proc_environ = |
583 |
apr_table_make(procnode->proc_pool, INITENV_CNT)) == NULL) { |
612 |
apr_table_make(procnode->proc_pool, INITENV_CNT)) == NULL) { |
584 |
/* Link the node back to free list in this case */ |
613 |
/* Link the node back to free list in this case */ |
Lines 591-596
Link Here
|
591 |
"mod_fcgid: can't create pool for process"); |
620 |
"mod_fcgid: can't create pool for process"); |
592 |
return; |
621 |
return; |
593 |
} |
622 |
} |
|
|
623 |
|
594 |
/* Set up longer, system defaults before falling into parsing fixed-limit |
624 |
/* Set up longer, system defaults before falling into parsing fixed-limit |
595 |
* request-by-request variables, so if any are overriden, they preempt |
625 |
* request-by-request variables, so if any are overriden, they preempt |
596 |
* any system default assumptions |
626 |
* any system default assumptions |
Lines 633-638
Link Here
|
633 |
apr_status_t pm_main(server_rec * main_server, apr_pool_t * configpool) |
663 |
apr_status_t pm_main(server_rec * main_server, apr_pool_t * configpool) |
634 |
{ |
664 |
{ |
635 |
fcgid_command command; |
665 |
fcgid_command command; |
|
|
666 |
apr_status_t rv; |
636 |
|
667 |
|
637 |
while (1) { |
668 |
while (1) { |
638 |
if (procmgr_must_exit()) |
669 |
if (procmgr_must_exit()) |
Lines 656-662
Link Here
|
656 |
} |
687 |
} |
657 |
|
688 |
|
658 |
/* Stop all processes */ |
689 |
/* Stop all processes */ |
659 |
kill_all_subprocess(main_server); |
690 |
kill_all_subprocess(main_server, procmgr_graceful_restart()); |
660 |
|
691 |
|
661 |
return APR_SUCCESS; |
692 |
return APR_SUCCESS; |
662 |
} |
693 |
} |