diff options
Diffstat (limited to 'src/progman.c')
-rw-r--r-- | src/progman.c | 95 |
1 files changed, 85 insertions, 10 deletions
diff --git a/src/progman.c b/src/progman.c index da5a970..52c875f 100644 --- a/src/progman.c +++ b/src/progman.c @@ -952,7 +952,6 @@ check_connection_rate (struct prog *prog) return 0; } - static int prog_open_socket (struct prog *prog) { @@ -1473,7 +1472,6 @@ progman_create_sockets () progman_foreach (prog_create_socket, NULL); } - void progman_recompute_alarm () { @@ -1508,9 +1506,7 @@ progman_recompute_alarm () if (alarm_time) alarm (alarm_time); } - - void progman_start () { @@ -2315,6 +2311,7 @@ progman_cleanup (int expect_term) { case TYPE_COMPONENT: print_status (prog_tag (prog), pid, status, expect_term); + prog->v.p.stop = 0; if (prog->v.p.comp->mode == pies_comp_inetd) { struct prog *listener = prog->v.p.listener; @@ -2418,6 +2415,7 @@ progman_stop_component (struct prog **progptr) prog_deactivate_listener (prog); /* fall through */ case status_stopped: + prog->v.p.stop = 0; if (!component_is_active (prog->v.p.comp)) destroy_prog (progptr); break; @@ -2425,14 +2423,20 @@ progman_stop_component (struct prog **progptr) case status_sleeping: if (!component_is_active (prog->v.p.comp)) destroy_prog (progptr); + else if (prog->v.p.stop) + prog->v.p.stop = 0; else { logmsg (LOG_INFO, _("waking up component `%s'"), prog_tag (prog)); prog->v.p.failcount = 0; } break; + + case status_stopping: + break; - default: + case status_finished: + prog->v.p.stop = 0; if (!component_is_active (prog->v.p.comp)) destroy_prog (progptr); else @@ -2442,7 +2446,7 @@ progman_stop_component (struct prog **progptr) } } } - + void prog_deactivate_listener (struct prog *prog) { @@ -2478,12 +2482,83 @@ prog_activate_listener (struct prog *prog) } return 0; } + +/* Starting at PROG, find first program component marked for termination. */ +static struct prog * +prog_to_stop (struct prog *prog) +{ + for (; prog; prog = prog->next) + if (IS_COMPONENT (prog) && prog->v.p.stop) + break; + return prog; +} + +#define DIAG_CON \ + (init_process ? (DIAG_TO_STDERR|DIAG_REOPEN_LOG) : diag_output) +/* Stop all program components marked for termination. Wait at most + 2*shutdown_timeout seconds. */ void -progman_stop_tag (const char *name) +progman_gc () { - struct prog *prog = progman_locate (name); - progman_stop_component (&prog); -} + time_t start; + struct prog *prog, *next; + + /* Find first marked prog */ + prog = prog_to_stop (proghead); + if (!prog) + return; + + /* First round: */ + /* Gracefully stop it and all marked programs that follow */ + diagmsg (DIAG_CON, LOG_INFO, "Sending processes the TERM signal"); + start = time (NULL); + do + { + next = prog->next; + progman_stop_component (&prog); + } + while ((prog = prog_to_stop (next))); + + /* Wait for them to terminate */ + while (1) + { + progman_cleanup (1); + prog = prog_to_stop (proghead); + if (!prog) + return; + if (time (NULL) - start < shutdown_timeout) + sleep (1); + else + break; + } + + /* Second round: */ + /* Kill the remaining programs with SIGKILL */ + diagmsg (DIAG_CON, LOG_INFO, "Sending processes the KILL signal"); + start = time (NULL); + do + { + next = prog->next; + prog_stop (prog, SIGKILL); + } + while ((prog = prog_to_stop (next))); + /* Wait for them to terminate */ + while (1) + { + progman_cleanup (1); + prog = prog_to_stop (proghead); + if (!prog) + return; + if (time (NULL) - start < shutdown_timeout) + sleep (1); + else + break; + } + + /* FIXME: Report remaining programs */ + +} + /* EOF */ |