diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2016-02-19 08:41:12 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2016-02-19 08:41:12 +0200 |
commit | e6902abfddb4d7b16dc9a4231a3781f354a08cd5 (patch) | |
tree | c634621af2ae765460e010ce83c8492ed4e859bc | |
parent | 51a797445a4bfc34ad1ae7ea91e12486d823abda (diff) | |
download | pies-e6902abfddb4d7b16dc9a4231a3781f354a08cd5.tar.gz pies-e6902abfddb4d7b16dc9a4231a3781f354a08cd5.tar.bz2 |
Revamp program termination after reconfiguring.
* src/pies.h (PIES_CHLD_GC): New op.
(progman_stop_tag): Remove proto.
* src/pies.c (main): Handle PIES_CHLD_GC: stop all programs marked
for termination.
* src/comp.c (component_config_commit): Mark leftover components
for termination, instead of waiting for them to terminate.
* src/sysvinit.c (runlevel_setup_prog): Skip prog if its
active status didn't change.
Mark inactivated progs for termination.
(sysvinit_runlevel_setup): Schedule PIES_CHLD_GC.
(inittrans): Don't wait for programs to terminate. That will be done
in the main loop.
* src/prog.h (prog)<stop>: New boolean member.
* src/progman.c (progman_cleanup)
(progman_stop_component): Clear the stop flag.
(progman_gc): New function.
(progman_stop_tag): Remove.
-rw-r--r-- | src/comp.c | 32 | ||||
-rw-r--r-- | src/pies.c | 2 | ||||
-rw-r--r-- | src/pies.h | 2 | ||||
-rw-r--r-- | src/prog.h | 5 | ||||
-rw-r--r-- | src/progman.c | 95 | ||||
-rw-r--r-- | src/sysvinit.c | 42 |
6 files changed, 102 insertions, 76 deletions
@@ -359,29 +359,13 @@ prog_is_leftover (struct prog *prog) } -/* If PROG is a leftover, gracefully stop it and mark as disabled */ +/* If PROG is a leftover, mark it for termination */ static int -cb_terminate_prog (struct prog *prog, void *data) +mark_prog (struct prog *prog, void *data) { if (prog_is_leftover (prog)) - progman_stop_component (&prog); + prog->v.p.stop = 1; return 0; } -/* If PROG is a leftover, slay it with SIGKILL */ -static int -cb_kill_prog (struct prog *prog, void *data) -{ - if (prog_is_leftover (prog)) - prog_stop (prog, SIGKILL); - return 0; -} - -static int -list_is_empty (void *p) -{ - struct complist *list = p; - return list->head == NULL; -} - static int list_str_cmp (const void *a, const void *b) @@ -505,14 +489,10 @@ component_config_commit (void) } - /* Terminate orphaned progs */ + /* Mark orphaned progs for termination */ list = &comp_list[prev]; if (list->head) { - progman_foreach (cb_terminate_prog, NULL); - if (progman_wait_until (list_is_empty, list)) - { - progman_foreach (cb_kill_prog, NULL); - progman_wait_until (list_is_empty, list); - } + progman_foreach (mark_prog, NULL); + pies_schedule_children (PIES_CHLD_GC); } @@ -2222,4 +2222,6 @@ main (int argc, char **argv) if (action == ACTION_CONT) { + if (children_op & PIES_CHLD_GC) + progman_gc (); if (children_op & PIES_CHLD_CLEANUP) progman_cleanup (0); @@ -319,4 +319,5 @@ void free_action (struct action *act); #define PIES_CHLD_CLEANUP 0x01 #define PIES_CHLD_WAKEUP 0x02 +#define PIES_CHLD_GC 0x04 void pies_schedule_children (int op); @@ -331,5 +332,4 @@ void progman_filter (int (*filter) (struct component *, void *data), void *data); int progman_wait_until (int (*cond) (void *), void *data); -void progman_stop_tag (const char *name); int progman_accept (int socket, void *data); @@ -52,6 +52,7 @@ struct prog { struct component *comp; - int wait :1; - int active :1; + int active :1; /* The prog is active */ + int wait :1; /* Wait for this prog to terminate */ + int stop :1; /* Stop this prog */ int socket; struct prog *redir[2]; /* Pointers to redirectors */ diff --git a/src/progman.c b/src/progman.c index da5a970..52c875f 100644 --- a/src/progman.c +++ b/src/progman.c @@ -953,5 +953,4 @@ check_connection_rate (struct prog *prog) } - static int prog_open_socket (struct prog *prog) @@ -1474,5 +1473,4 @@ progman_create_sockets () } - void progman_recompute_alarm () @@ -1509,7 +1507,5 @@ progman_recompute_alarm () alarm (alarm_time); } - - void progman_start () @@ -2316,4 +2312,5 @@ 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) { @@ -2419,4 +2416,5 @@ progman_stop_component (struct prog **progptr) /* fall through */ case status_stopped: + prog->v.p.stop = 0; if (!component_is_active (prog->v.p.comp)) destroy_prog (progptr); @@ -2426,4 +2424,6 @@ progman_stop_component (struct prog **progptr) if (!component_is_active (prog->v.p.comp)) destroy_prog (progptr); + else if (prog->v.p.stop) + prog->v.p.stop = 0; else { @@ -2432,6 +2432,10 @@ progman_stop_component (struct prog **progptr) } 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); @@ -2443,5 +2447,5 @@ progman_stop_component (struct prog **progptr) } } - + void prog_deactivate_listener (struct prog *prog) @@ -2479,11 +2483,82 @@ 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 */ diff --git a/src/sysvinit.c b/src/sysvinit.c index 6276228..41d5b9d 100644 --- a/src/sysvinit.c +++ b/src/sysvinit.c @@ -63,5 +63,4 @@ int dfl_level; int emergency_shell; -#define DIAG_CON (DIAG_TO_STDERR|DIAG_REOPEN_LOG) int @@ -283,9 +282,12 @@ runlevel_setup_prog (struct prog *prog, void *data) { int rc = enablecomp (prog, data); - if (rc < 0) + if (rc < 0 || prog->v.p.active == rc) return 0; prog->v.p.active = rc; if (rc) prog->v.p.wait = is_comp_wait (prog->v.p.comp); + else if (prog->v.p.status != status_stopped + && prog->v.p.status != status_finished) + prog->v.p.stop = 1; debug (2, ("%s: %s%s", prog_tag (prog), prog->v.p.active ? @@ -302,4 +304,5 @@ sysvinit_runlevel_setup (int mask) s.mask = mask; progman_foreach (runlevel_setup_prog, &s); + pies_schedule_children (PIES_CHLD_GC); } @@ -764,24 +767,4 @@ sysvinit_begin () && !prog->v.p.active) -static int -cond_running_disabled (struct prog *prog, void *data) -{ - return IS_RUNNING_DISABLED_PROG (prog); -} - -static int -no_disabled_running (void *data) -{ - return !progman_foreach (cond_running_disabled, NULL); -} - -static int -terminate_disabled (struct prog *prog, void *data) -{ - if (IS_RUNNING_DISABLED_PROG (prog)) - prog_stop (prog, *(int*)data); - return 0; -} - int inittrans () @@ -845,21 +828,6 @@ inittrans () if (trans) { - int sig; - envsetup (); sysvinit_runlevel_setup (PIES_COMP_DEFAULT); - - /* Stop disabled programs */ - sig = SIGTERM; - diagmsg (DIAG_CON, LOG_INFO, "Sending processes the TERM signal"); - progman_foreach (terminate_disabled, &sig); - if (progman_wait_until (no_disabled_running, NULL)) - { - sig = SIGKILL; - diagmsg (DIAG_CON, LOG_INFO, "Sending processes the KILL signal"); - progman_foreach (terminate_disabled, &sig); - progman_wait_until (no_disabled_running, NULL); - } - pies_schedule_children (PIES_CHLD_WAKEUP); } |