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
@@ -355,37 +355,21 @@ component_config_rollback (void) static int 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) { return safe_strcmp (a, b); } @@ -501,22 +485,18 @@ component_config_commit (void) comp = match; } comp_array[i] = comp; 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 */ component_build_depmap (); /* Register new progs */ @@ -2218,12 +2218,14 @@ main (int argc, char **argv) sysvinit_power (); pies_schedule_children (PIES_CHLD_WAKEUP); action = ACTION_CONT; } 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) progman_wake_sleeping (1); children_op = PIES_CHLD_NONE; } @@ -315,25 +315,25 @@ void free_redirector (struct redirector *rp); void pies_schedule_action (int act); 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); void register_prog (struct component *comp); int progman_waiting_p (void); void progman_start (void); void progman_wake_sleeping (int); void progman_stop (void); 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); struct component *progman_lookup_component (const char *tag); struct component *progman_lookup_tcpmux (const char *service, const char *master); @@ -48,14 +48,15 @@ struct prog int facility; union { 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 */ size_t failcount; /* Number of failed starts since timestamp */ enum prog_status status; /* Current component status */ /* If status == status_listener: */ diff --git a/src/progman.c b/src/progman.c index da5a970..52c875f 100644 --- a/src/progman.c +++ b/src/progman.c @@ -949,13 +949,12 @@ check_connection_rate (struct prog *prog) prog_tag (prog), SLEEPTIME / 60); return 1; } return 0; } - static int prog_open_socket (struct prog *prog) { prog->v.p.socket = create_socket (prog->v.p.comp->socket_url, prog->v.p.comp->socket_type, prog->v.p.comp->privs.user, @@ -1470,13 +1469,12 @@ prog_create_socket (struct prog *prog, void *data) void progman_create_sockets () { progman_foreach (prog_create_socket, NULL); } - void progman_recompute_alarm () { struct prog *prog; time_t now = time (NULL); time_t alarm_time = 0, x; @@ -1505,15 +1503,13 @@ progman_recompute_alarm () } } debug (2, ("alarm=%lu", (unsigned long)alarm_time)); if (alarm_time) alarm (alarm_time); } - - void progman_start () { struct prog *prog; if (progman_waiting_p ()) @@ -2312,12 +2308,13 @@ progman_cleanup (int expect_term) } prog->pid = 0; switch (prog->type) { 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; listener->v.p.num_instances--; if (prog->v.p.cclass) @@ -2415,37 +2412,44 @@ progman_stop_component (struct prog **progptr) break; case status_listener: 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; 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 logmsg (LOG_INFO, _("stopping component `%s': component not started"), prog_tag (prog)); } } } - + void prog_deactivate_listener (struct prog *prog) { logmsg (LOG_INFO, _("deactivating listener `%s'"), prog_tag (prog)); if (prog->v.p.socket != -1) { @@ -2475,15 +2479,86 @@ prog_activate_listener (struct prog *prog) } else prog->v.p.socket = fd; } 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 @@ -59,13 +59,12 @@ int runlevel = 0; int prevlevel = 'N'; int initdefault; /* Default runlevel */ int dfl_level; int emergency_shell; -#define DIAG_CON (DIAG_TO_STDERR|DIAG_REOPEN_LOG) int console_open (int mode) { int i, fd; @@ -279,17 +278,20 @@ runlevel_setup_prog (struct prog *prog, void *data) { if (IS_COMPONENT (prog) && !(prog->v.p.comp->flags & CF_DISABLED) && 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", prog->v.p.active && prog->v.p.wait ? " (wait)" : "")); } return 0; @@ -298,12 +300,13 @@ runlevel_setup_prog (struct prog *prog, void *data) void 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 demand_prog (struct prog *prog, void *data) { int *rl = data; @@ -760,32 +763,12 @@ sysvinit_begin () #define IS_RUNNING_DISABLED_PROG(prog) \ (IS_COMPONENT (prog) \ && 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 () { int n; int newlevel = 0; enum boot_state newstate; @@ -841,29 +824,14 @@ inittrans () runlevel = newlevel; trans = 1; } 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; } /* Return true if the progman should wait for the component to |