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 /src | |
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.
Diffstat (limited to 'src')
-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
@@ -358,31 +358,15 @@ prog_is_leftover (struct prog *prog) return IS_COMPONENT (prog) && !component_is_active (prog->v.p.comp); } -/* 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) { @@ -504,16 +488,12 @@ component_config_commit (void) comp->arridx = i; } - /* 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); } /* Build dependency map */ @@ -2221,6 +2221,8 @@ 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); if (children_op & PIES_CHLD_WAKEUP) @@ -318,6 +318,7 @@ void free_action (struct action *act); #define PIES_CHLD_NONE 0 #define PIES_CHLD_CLEANUP 0x01 #define PIES_CHLD_WAKEUP 0x02 +#define PIES_CHLD_GC 0x04 void pies_schedule_children (int op); @@ -330,7 +331,6 @@ void progman_cleanup (int expect_term); 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); void progman_create_sockets (void); @@ -51,8 +51,9 @@ struct prog struct { 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 */ time_t timestamp; /* Time of last startup */ 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 */ diff --git a/src/sysvinit.c b/src/sysvinit.c index 6276228..41d5b9d 100644 --- a/src/sysvinit.c +++ b/src/sysvinit.c @@ -62,7 +62,6 @@ int initdefault; /* Default runlevel */ int dfl_level; int emergency_shell; -#define DIAG_CON (DIAG_TO_STDERR|DIAG_REOPEN_LOG) int console_open (int mode) @@ -282,11 +281,14 @@ runlevel_setup_prog (struct prog *prog, void *data) && is_sysvinit (prog->v.p.comp)) { 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 ? "enabled" : "disabled", @@ -301,6 +303,7 @@ sysvinit_runlevel_setup (int mask) struct enstate s; s.mask = mask; progman_foreach (runlevel_setup_prog, &s); + pies_schedule_children (PIES_CHLD_GC); } static int @@ -763,26 +766,6 @@ sysvinit_begin () && prog->v.p.status == status_running \ && !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 () { @@ -844,23 +827,8 @@ 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); } return trans; |