From c9581808b72ff25623c87cf49c471ce7f017985d Mon Sep 17 00:00:00 2001 From: Sergey Poznyakoff Date: Sat, 13 Feb 2016 21:27:11 +0200 Subject: Stop disabled components when switching runlevels. * src/prog.h (status_enabled, status_disabled): Remove. (status_stopped, status_running): New modes. All uses updated. * src/comp.c (component_finish): Disable ondemand component by default. * src/ctl.c (json_object_set_bool): New function. (pies_status_str): Update. (prog_serialize): Set "disabled" attribute. (fun_stop, fun_start): Use CF_DISABLED flag. (res_runlevel): Schedule ACTION_RELOAD. * src/pies.h (json_object_set_bool): New proto. * src/piesctl.c (status_trans): Reflect changes in modes. (print_comp): Check the "disabled" attribute. * src/progman.c (register_prog0) (prog_open_socket,prog_start,prog_stop) (progman_wake_sleeping) (prog_start_prerequisites) (react, progman_cleanup) (progman_stop_component): Update. (no_children_left): Fix. * src/sysvinit.c (enablecomp): Make CF_DISABLED flag persist for ondemand components. (runlevel_setup_prog): Use CF_DISABLED flag. (inittrans): Stop inactivated processes. * doc/pies.texi: Update. --- doc/pies.texi | 19 +++++++++++-- src/comp.c | 3 ++ src/ctl.c | 30 ++++++++++++++------ src/pies.h | 1 + src/piesctl.c | 20 +++++++++----- src/prog.h | 7 ++--- src/progman.c | 86 ++++++++++++++++++++++++++++++---------------------------- src/sysvinit.c | 66 ++++++++++++++++++++++++++++++++++++-------- 8 files changed, 156 insertions(+), 76 deletions(-) diff --git a/doc/pies.texi b/doc/pies.texi index 46bd837..39a2694 100644 --- a/doc/pies.texi +++ b/doc/pies.texi @@ -2437,24 +2437,37 @@ describes the type: @multitable @columnfractions 0.2 0.7 @headitem Flag @tab Meaning +@item 3 @tab SysV init @samp{ctrlaltdel} component @item A @tab Accept-style component +@item B @tab SysV init @samp{boot} component @item C @tab Init-style component +@item c @tab SysV init @samp{once} component +@item D @tab SysV init @samp{ondemand} component @item E @tab Command being executed +@item F @tab SysV init @samp{powerfail} component +@item f @tab SysV init @samp{powerwait} component @item I @tab Inetd-style component +@item i @tab SysV init @samp{sysinit} component +@item k @tab SysV init @samp{kbrequest} component +@item n @tab SysV init @samp{powerfailnow} component +@item o @tab SysV init @samp{powerokwait} component @item P @tab Pass-style component @item R @tab Output redirector +@item W @tab SysV init @samp{wait} component +@item w @tab SysV init @samp{bootwait} component @end multitable - The second flag is meaningful only for components, i.e. if the first -flag is one of @samp{CAIP}. Its values are: + The second flag is meaningful only for components. Its values are: @multitable @columnfractions 0.2 0.7 @headitem Flag @tab Meaning -@item D @tab Disabled component +@item - @tab Disabled component +@item f @tab A finished @samp{once} component @item L @tab Inetd listener @item R @tab Running component @item S @tab Component is stopping @item s @tab Component is sleeping +@item T @tab Component is stopped @end multitable The next column lists the PID (for running components) or socket address diff --git a/src/comp.c b/src/comp.c index 6a0e4ba..83818c2 100644 --- a/src/comp.c +++ b/src/comp.c @@ -729,6 +729,9 @@ component_finish (struct component *comp, grecs_locus_t *locus) comp->prereq = NULL; } } + + if (comp->mode == pies_comp_ondemand) + comp->flags |= CF_DISABLED; } } diff --git a/src/ctl.c b/src/ctl.c index 6f50246..f4154f6 100644 --- a/src/ctl.c +++ b/src/ctl.c @@ -463,6 +463,12 @@ json_object_set_number (struct json_value *obj, char const *name, double val) json_object_set (obj, name, json_new_number (val)); } +void +json_object_set_bool (struct json_value *obj, char const *name, int val) +{ + json_object_set (obj, name, json_new_bool (val)); +} + static struct json_value * json_error_reply_create (const char *msg) { @@ -1449,8 +1455,8 @@ static char * const pies_comp_mode_str[] = { }; static char * const pies_status_str[] = { - [status_enabled] = "enabled", - [status_disabled] = "disabled", + [status_stopped] = "stopped", + [status_running] = "running", [status_listener] = "listener", [status_sleeping] = "sleeping", [status_stopping] = "stopping", @@ -1822,6 +1828,9 @@ prog_serialize (struct json_value *ret, struct prog *prog) case TYPE_COMPONENT: FORMAT_IDX (ret, "mode", pies_comp_mode_str, prog->v.p.comp->mode); FORMAT_IDX (ret, "status", pies_status_str, prog->v.p.status); + + json_object_set_bool (ret, "disabled", + prog->v.p.comp->flags & CF_DISABLED); if (prog->pid) json_object_set_number (ret, "PID", prog->pid); @@ -1864,17 +1873,18 @@ fun_list (struct json_value *result, struct prog *prog) static int fun_stop (struct json_value *result, struct prog *prog) { - if (prog->v.p.status == status_disabled) + if (prog->v.p.comp->flags & CF_DISABLED + && prog->v.p.status == status_stopped) { + json_object_set_string (result, "status", "ER"); json_object_set_string (result, "error_message", "already stopped"); return 1; } else { + prog->v.p.comp->flags |= CF_DISABLED; progman_stop_component (&prog); - if (prog) - prog->v.p.comp->flags |= CF_DISABLED; json_object_set_string (result, "status", "OK"); } return 0; @@ -1885,15 +1895,14 @@ fun_start (struct json_value *result, struct prog *prog) { switch (prog->v.p.status) { - case status_disabled: + case status_stopped: prog->v.p.comp->flags &= ~CF_DISABLED; - prog->v.p.status = status_enabled; json_object_set_string (result, "status", "OK"); break; case status_sleeping: case status_finished: - prog->v.p.status = status_enabled; + prog->v.p.status = status_stopped; prog->v.p.failcount = 0; prog->v.p.timestamp = 0; json_object_set_string (result, "status", "OK"); @@ -2049,7 +2058,10 @@ res_runlevel (struct ctlio *io, enum http_method meth, io->code = 200; if (strlen (val->v.s) == 1 && sysvinit_set_runlevel (val->v.s[0]) == 0) - json_object_set_string (io->output.reply, "status", "OK"); + { + pies_schedule_action (ACTION_RELOAD); + json_object_set_string (io->output.reply, "status", "OK"); + } else { json_object_set_string (io->output.reply, "status", "ER"); diff --git a/src/pies.h b/src/pies.h index 9fb87c6..14ea7b7 100644 --- a/src/pies.h +++ b/src/pies.h @@ -587,3 +587,4 @@ void json_object_set_string (struct json_value *obj, char const *name, char const *fmt, ...); void json_object_set_number (struct json_value *obj, char const *name, double val); +void json_object_set_bool (struct json_value *obj, char const *name, int val); diff --git a/src/piesctl.c b/src/piesctl.c index d6a39a2..5f26aec 100644 --- a/src/piesctl.c +++ b/src/piesctl.c @@ -1075,8 +1075,8 @@ struct kwtrans mode_trans[] = { }; struct kwtrans status_trans[] = { - { "enabled", 'R' }, - { "disabled", 'D' }, + { "running", 'R' }, + { "stopped", 'T' }, { "listener", 'L' }, { "sleeping", 's' }, { "stopping", 'S' }, @@ -1159,15 +1159,21 @@ print_comp (FILE *fp, struct json_value *v, size_t n) if (strcmp (type, "component") == 0) { p = getval (v, "mode", json_string, 0); - if (v) + if (p) fbuf[fidx++] = kwtoc (p->v.s, mode_trans); else fbuf[fidx++] = '-'; - p = getval (v, "status", json_string, 0); - if (p) - fbuf[fidx++] = status = kwtoc (p->v.s, status_trans); - else + p = getval (v, "disabled", json_bool, 0); + if (p && p->v.b) fbuf[fidx++] = '-'; + else + { + p = getval (v, "status", json_string, 0); + if (p) + fbuf[fidx++] = status = kwtoc (p->v.s, status_trans); + else + fbuf[fidx++] = '-'; + } } else if (strcmp (type, "redirector") == 0) { diff --git a/src/prog.h b/src/prog.h index 2dc8591..1db2eee 100644 --- a/src/prog.h +++ b/src/prog.h @@ -23,9 +23,8 @@ enum prog_type enum prog_status { - status_enabled, /* Component enabled. prog->pid!=0 shows if it is - actually running */ - status_disabled, /* Component is disabled. */ + status_stopped, /* Component is stopped. */ + status_running, /* Component is running */ status_listener, /* Component is an inetd listener */ status_sleeping, /* Component is sleeping. An attempt to start it will be made at prog->v.p.timestamp + SLEEPTIME */ @@ -60,7 +59,7 @@ struct prog enum prog_status status; /* Current component status */ /* If status == status_listener: */ size_t num_instances; /* Number of running instances */ - /* If comp->type == pies_comp_inetd && status == status_enabled */ + /* If comp->type == pies_comp_inetd && status == status_running */ struct prog *listener; union pies_sockaddr_storage sa_storage; size_t sa_len; diff --git a/src/progman.c b/src/progman.c index 2c73b2b..29b5331 100644 --- a/src/progman.c +++ b/src/progman.c @@ -270,11 +270,11 @@ register_prog0 (struct component *comp) newp->facility = comp->facility; newp->v.p.comp = comp; newp->v.p.socket = -1; - if (comp->flags & CF_DISABLED) - newp->v.p.status = status_disabled; - else if (comp->mode == pies_comp_inetd) + if (comp->mode == pies_comp_inetd) newp->v.p.status = status_listener; - + else + newp->v.p.status = status_stopped; + if (comp->mode != pies_comp_exec) comp->redir[RETR_OUT].type = redir_null; @@ -938,7 +938,8 @@ prog_open_socket (struct prog *prog) prog->v.p.comp->umask); if (prog->v.p.socket == -1) { - prog->v.p.status = status_disabled; + prog->v.p.status = status_stopped; + prog->v.p.comp->flags |= CF_DISABLED; return 1; } if (listen (prog->v.p.socket, 8)) @@ -946,7 +947,8 @@ prog_open_socket (struct prog *prog) logmsg (LOG_ERR, "listen: %s", strerror (errno)); close (prog->v.p.socket); prog->v.p.socket = -1; - prog->v.p.status = status_disabled; + prog->v.p.status = status_stopped; + prog->v.p.comp->flags |= CF_DISABLED; return 1; } return 0; @@ -1039,16 +1041,16 @@ prog_start (struct prog *prog) { if (!init_process) { - if (prog->v.p.status != status_disabled) + if (!(prog->v.p.comp->flags & CF_DISABLED)) { logmsg (LOG_NOTICE, "disabling sysvinit component %s", prog_tag (prog)); - prog->v.p.status = status_disabled; + prog->v.p.status = status_stopped; + prog->v.p.comp->flags |= CF_DISABLED; } return; } prog->v.p.wait = is_comp_wait (prog->v.p.comp); - debug (1, ("ok to start %s", prog->v.p.comp->tag)); } /* This call returns 1 in two cases: Either prog is marked as disabled, @@ -1236,7 +1238,7 @@ prog_start (struct prog *prog) if (redir[RETR_ERR]) close (redir[RETR_ERR]); prog->pid = pid; - prog->v.p.status = status_enabled; + prog->v.p.status = status_running; debug (1, (_("%s started, pid=%lu"), prog_tag (prog), (unsigned long) pid)); } @@ -1434,11 +1436,11 @@ progman_create_sockets () comp->socket_type, comp->privs.user, comp->umask); if (fd == -1) - prog->v.p.status = status_disabled; + prog->v.p.comp->flags |= CF_DISABLED; else if (register_program_socket (comp->socket_type, fd, prog)) { close (fd); - prog->v.p.status = status_disabled; + prog->v.p.comp->flags |= CF_DISABLED; } else prog->v.p.socket = fd; @@ -1509,7 +1511,7 @@ progman_start () enable_socket (prog->v.p.socket); } } - else if ((prog->v.p.status == status_enabled && prog->pid == 0) + else if (prog->v.p.status == status_stopped || prog->v.p.status == status_sleeping) prog_start (prog); } @@ -1560,7 +1562,7 @@ progman_wake_sleeping (int onalrm) } else { - prog->v.p.status = status_enabled; + prog->v.p.status = status_running; prog->v.p.failcount = 0; prog->v.p.timestamp = 0; prog_start (prog); @@ -1576,9 +1578,8 @@ progman_wake_sleeping (int onalrm) check_stopping (prog, now); break; - case status_enabled: - if (prog->pid == 0) - prog_start (prog); + case status_stopped: + prog_start (prog); break; default: @@ -1597,7 +1598,7 @@ prog_start_prerequisites (struct prog *prog) struct component *comp; int warned = 0; - if (prog->v.p.status == status_disabled) + if (prog->v.p.comp->flags & CF_DISABLED) return 1; for (comp = component_depmap_first (depmap_col, prog->v.p.comp->arridx, &pos); comp; @@ -1612,17 +1613,21 @@ prog_start_prerequisites (struct prog *prog) debug (1, ("starting prerequisites of %s", prog_tag (prog))); warned = 1; } + + if (comp->flags & CF_DISABLED) + { + prog->v.p.comp->flags |= CF_DISABLED; + return 1; + } + p = comp->prog; switch (p->v.p.status) { - case status_enabled: - if (prog->pid != 0) - continue; - break; + case status_running: + continue; - case status_disabled: - prog->v.p.status = status_disabled; - return 1; + case status_stopped: + break; case status_listener: continue; @@ -1640,8 +1645,8 @@ prog_start_prerequisites (struct prog *prog) continue; } prog_start (p); - if (p->v.p.comp->mode == pies_comp_once || - !(p->v.p.status == status_enabled && p->pid)) + if (p->v.p.comp->mode == pies_comp_once + || p->v.p.status != status_running)//FIXME ret = 1; } depmap_end (pos); @@ -1690,7 +1695,7 @@ prog_stop (struct prog *prog, int sig) return; if (prog->type == TYPE_COMPONENT) { - if (prog->v.p.status == status_enabled) + if (prog->v.p.status == status_running) { prog->v.p.status = status_stopping; prog->v.p.timestamp = time (NULL); @@ -1712,7 +1717,7 @@ prog_stop_all (int sig) debug (1, ("stopping all components (signal %d)", sig)); for (prog = progtail; prog; prog = prog->prev) if (IS_COMPONENT (prog) - && (prog->v.p.status == status_enabled + && (prog->v.p.status == status_running || prog->v.p.status == status_stopping)) prog_stop (prog, sig); } @@ -1736,7 +1741,13 @@ progman_wait_until (int (*cond) (void *), void *data) static int no_children_left (void *p) { - return proghead == NULL; + struct prog *prog; + + for (prog = proghead; prog; prog = prog->next) + if (prog->pid > 0) + return 0; + + return 1; } void @@ -2227,7 +2238,7 @@ react (struct prog *prog, int status, pid_t pid) case action_disable: logmsg (LOG_NOTICE, _("disabling component %s"), prog_tag (prog)); - prog->v.p.status = status_disabled; + prog->v.p.comp->flags |= CF_DISABLED; /* FIXME: if (prog->v.p.comp->mode == pies_comp_inetd) disable_socket (prog->v.p.socket); @@ -2313,9 +2324,7 @@ progman_cleanup (int expect_term) sysvinit_acct (SYSV_ACCT_PROC_STOP, "", prog_tag (prog), pid, ""); - prog->v.p.status = - (prog->v.p.comp->flags & CF_DISABLED) - ? status_disabled : status_enabled; + prog->v.p.status = status_stopped; prog_stop_dependents (prog); if (!expect_term) react (prog, status, pid); @@ -2358,20 +2367,15 @@ progman_stop_component (struct prog **progptr) { switch (prog->v.p.status) { - case status_enabled: + case status_running: case status_listener: logmsg (LOG_INFO, _("stopping component `%s'"), prog_tag (prog)); prog_stop (prog, SIGTERM); break; - case status_disabled: + case status_stopped: if (!component_is_active (prog->v.p.comp)) destroy_prog (progptr); - else if (!(prog->v.p.comp->flags & CF_DISABLED)) - { - logmsg (LOG_INFO, _("enabling component `%s'"), prog_tag (prog)); - prog->v.p.status = status_enabled; - } break; case status_sleeping: diff --git a/src/sysvinit.c b/src/sysvinit.c index 9e918c7..c9447ff 100644 --- a/src/sysvinit.c +++ b/src/sysvinit.c @@ -219,7 +219,6 @@ static int enablecomp (struct prog *prog, void *data) { struct enstate *s = data; - int rc; struct component *comp = prog->v.p.comp; switch (boot_state) @@ -240,7 +239,8 @@ enablecomp (struct prog *prog, void *data) return 0; case pies_comp_ondemand: - return prog->v.p.status == status_enabled; + /* Disabled flag persists: */ + return !(prog->v.p.comp->flags & CF_DISABLED); case pies_comp_powerfail: case pies_comp_powerwait: @@ -253,11 +253,13 @@ enablecomp (struct prog *prog, void *data) break; } } - rc = !!strchr (comp->runlevels, runlevel); - if (!rc) - return rc; + + if (!strchr (comp->runlevels, runlevel)) + return 0; + if (prog->v.p.status == status_finished) return -1; + if (s && s->mask & PIES_COMP_WAIT) { if (comp->mode == pies_comp_wait) @@ -267,7 +269,8 @@ enablecomp (struct prog *prog, void *data) } return 0; } - return rc; + + return 1; } static int @@ -279,12 +282,12 @@ runlevel_setup_prog (struct prog *prog, void *data) if (rc < 0) return 0; if (rc) - prog->v.p.status = status_enabled; + prog->v.p.comp->flags &= ~CF_DISABLED; else - prog->v.p.status = status_disabled; - debug (1, ("%s: %s", prog_tag (prog), - prog->v.p.status == status_enabled ? - "enabled" : "disabled")); + prog->v.p.comp->flags |= CF_DISABLED; + debug (2, ("%s: %s", prog_tag (prog), + prog->v.p.comp->flags & CF_DISABLED ? + "disabled" : "enabled")); } return 0; } @@ -313,7 +316,7 @@ demand_prog (struct prog *prog, void *data) && comp->runlevels && strchr (comp->runlevels, *rl)) { - prog->v.p.status = status_enabled; + prog->v.p.comp->flags &= ~CF_DISABLED; debug (1, ("%s: %s", prog_tag (prog), "enabled")); } return 0; @@ -708,6 +711,31 @@ sysvinit_begin () sysvinit_sysdep_begin (); } +#define IS_RUNNING_DISABLED_PROG(prog) \ + (IS_COMPONENT (prog) \ + && prog->v.p.status == status_running \ + && prog->v.p.comp->flags & CF_DISABLED) \ + +static int +cond_running_disabled (struct prog *prog, void *data) +{ + return IS_RUNNING_DISABLED_PROG (prog); +} + +static int +running_disabled (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 () { @@ -769,6 +797,8 @@ inittrans () trans = 1; if (trans) { + int sig; + envsetup (); if (wait == 0) { @@ -777,6 +807,18 @@ inittrans () return 1; } sysvinit_runlevel_setup (PIES_COMP_DEFAULT, NULL); + + /* Stop disabled programs */ + sig = SIGTERM; + progman_foreach (terminate_disabled, &sig); + if (progman_wait_until (running_disabled, NULL)) + { + sig = SIGKILL; + progman_foreach (terminate_disabled, &sig); + progman_wait_until (running_disabled, NULL); + } + + /* Clear the wait flag */ wait = 0; } return trans; -- cgit v1.2.1