From d8221ce9bdd2d7ae6162bed0e1c85e9f7a3ff8f2 Mon Sep 17 00:00:00 2001 From: Sergey Poznyakoff Date: Fri, 4 Jan 2013 15:33:00 +0200 Subject: Fix sysvinit transition logic. * src/pies.c (main): Call sysvinit_begin to initialize sysvinit subsystem. In the main loop, force wakeup if inittrans returns 1. * src/pies.h (is_sysvinit): Rewrite macro. (progman_sysvinit_enable): New proto. (inittrans): Change return type. * src/progman.c (progman_sysvinit_enable): New function. (progman_running_p): Additional debugging. (prog_start): Special handling for sysvinit components. Remove calls to runlevel_match * src/sysvinit.c (runlevel_match): Remove function. (sysvinit_begin): New function. (inittrans): Return boolean value indicating whether a transition has been made. Call progman_sysvinit_enable to change the status of sysvinit components as appropriate. --- src/pies.c | 12 ++++-- src/pies.h | 11 +++-- src/progman.c | 55 +++++++++++++++++++------ src/sysvinit.c | 124 ++++++++++++++++++++++++++++++++++++++------------------- 4 files changed, 142 insertions(+), 60 deletions(-) diff --git a/src/pies.c b/src/pies.c index 713ae8e..a2dc5e0 100644 --- a/src/pies.c +++ b/src/pies.c @@ -959,7 +959,7 @@ _cb_flags (enum grecs_callback_command cmd, return 0; } -static const char valid_runlevels[] = "0123456Ss"; +static const char valid_runlevels[] = "0123456789Ss"; static int _cb_initdefault (enum grecs_callback_command cmd, @@ -2309,6 +2309,7 @@ main (int argc, char **argv) { foreground = 1; set_console_dev (); + sysvinit_begin (); } else switch (pies_check_status (&pid)) @@ -2360,9 +2361,12 @@ main (int argc, char **argv) do { - if (init_process) - inittrans (); - if (!children_cleanup) + if (init_process && inittrans ()) + { + got_alarm = 1; + action = ACTION_CONT; + } + else if (!children_cleanup) pies_pause (); switch (action) { diff --git a/src/pies.h b/src/pies.h index a679afd..fc4f59c 100644 --- a/src/pies.h +++ b/src/pies.h @@ -183,8 +183,6 @@ enum pies_comp_mode pies_comp_respawn = pies_comp_exec, }; -#define is_sysvinit(m) ((m)>=pies_mark_sysvinit) - #define CF_DISABLED 0x001 /* The componenet is disabled */ #define CF_PRECIOUS 0x002 /* The component is precious (should not be disabled) */ @@ -253,6 +251,8 @@ struct component struct action act_temp; /* Auxiliary object used during configuration */ }; +#define is_sysvinit(cp) ((cp)->mode >= pies_mark_sysvinit || (cp)->runlevels) + union pies_sockaddr_storage { struct sockaddr s; @@ -301,6 +301,9 @@ void progman_run_comp (struct component *comp, int fd, void progman_iterate_comp (int (*fun) (struct component *, void *), void *data); +void progman_sysvinit_enable (int (*fun) (struct component *, int, void *), + void *data); + void fd_report (int fd, const char *msg); int check_acl (pies_acl_t acl, struct sockaddr *s, socklen_t salen); @@ -450,8 +453,8 @@ struct inetd_builtin struct inetd_builtin *inetd_builtin_lookup (const char *service, int socktype); /* sysvinit.c */ -int runlevel_match (struct component *comp); -void inittrans (void); +void sysvinit_begin (void); +int inittrans (void); int is_comp_wait (struct component *comp); diff --git a/src/progman.c b/src/progman.c index f0d0de6..15b8c44 100644 --- a/src/progman.c +++ b/src/progman.c @@ -106,6 +106,29 @@ progman_iterate_comp (int (*fun) (struct component *, void *), void *data) break; } +void +progman_sysvinit_enable (int (*fun) (struct component *, int, void *), + void *data) +{ + struct prog *prog; + + for (prog = proghead; prog; prog = prog->next) + if (IS_COMPONENT (prog) && is_sysvinit (prog->v.p.comp)) + { + int rc = fun (prog->v.p.comp, prog->v.p.status == status_finished, + data); + if (rc < 0) + continue; + if (rc) + prog->v.p.status = status_enabled; + else + prog->v.p.status = status_disabled; + debug (1, ("%s: %s", prog->tag, + prog->v.p.status == status_enabled ? + "enabled" : "disabled")); + } +} + static struct prog * prog_lookup_by_pid (pid_t pid) { @@ -412,7 +435,10 @@ progman_running_p () { if (IS_COMPONENT (prog) && is_comp_wait (prog->v.p.comp) && prog->pid > 0) - return 1; + { + debug (1, ("COMP %s still running", prog->tag)); + return 1; + } } return 0; } @@ -1185,14 +1211,21 @@ prog_start (struct prog *prog) if (prog->pid > 0 || !IS_COMPONENT (prog)) return; - if (is_sysvinit (prog->v.p.comp->mode) && !init_process && - prog->v.p.status != status_disabled) + if (is_sysvinit (prog->v.p.comp)) { - logmsg (LOG_NOTICE, "disabling sysvinit component %s", prog->tag); - prog->v.p.status = status_disabled; - return; + if (!init_process) + { + if (prog->v.p.status != status_disabled) + { + logmsg (LOG_NOTICE, "disabling sysvinit component %s", + prog->tag); + prog->v.p.status = status_disabled; + } + return; + } + debug (1, ("ok to start %s", prog->v.p.comp->tag)); } - + /* This call returns 1 in two cases: Either prog is marked as disabled, in which case there's nothing more to do, or one or more of its prerequisites are in status_stopping. In the latter case either the @@ -1782,8 +1815,7 @@ progman_start () { if (prog->v.p.comp->mode == pies_comp_inetd) { - if ((prog->v.p.comp->flags & CF_DISABLED) - || !runlevel_match (prog->v.p.comp)) + if (prog->v.p.comp->flags & CF_DISABLED) disable_socket (prog->v.p.socket); else { @@ -1791,8 +1823,7 @@ progman_start () enable_socket (prog->v.p.socket); } } - else if ((prog->v.p.status == status_enabled && prog->pid == 0 - && runlevel_match (prog->v.p.comp)) + else if ((prog->v.p.status == status_enabled && prog->pid == 0) || prog->v.p.status == status_sleeping) prog_start (prog); } @@ -2459,7 +2490,7 @@ progman_cleanup (int expect_term) if (listener->v.p.comp->flags & CF_WAIT) enable_socket (listener->v.p.socket); } - else if (is_sysvinit(prog->v.p.comp->mode)) + else if (prog->v.p.comp->mode >= pies_mark_sysvinit) { prog->v.p.status = status_finished; } diff --git a/src/sysvinit.c b/src/sysvinit.c index e09802f..5a0d98a 100644 --- a/src/sysvinit.c +++ b/src/sysvinit.c @@ -54,7 +54,7 @@ static int boot_trans_tab[max_boot_state][sizeof(valid_runlevels)-1] = { }; enum boot_state boot_state; -int runlevel; +int runlevel = 0; int initdefault; /* Default runlevel */ int dfl_level; @@ -62,75 +62,104 @@ int dfl_level; static int runlevel_index (int n) { - char *p = strchr (valid_runlevels, n); + char *p; + + if (n == 0) + return -1; + + p = strchr (valid_runlevels, n); if (!p) return -1; return p - valid_runlevels; } -int -runlevel_match (struct component *comp) +static int +enablecomp (struct component *comp, int finished, void *data) { - if (init_process) + int *wait = data; + int rc; + + switch (boot_state) { - switch (boot_state) - { - case sysinit: - return comp->mode == pies_comp_sysinit; - - case boot: - return comp->mode == pies_comp_boot || - comp->mode == pies_comp_bootwait; + case sysinit: + return comp->mode == pies_comp_sysinit; - case single0: - case single1: - case normal: - switch (comp->mode) - { - case pies_comp_sysinit: - case pies_comp_boot: - case pies_comp_bootwait: - return 0; - case pies_comp_powerfail: - case pies_comp_powerwait: - case pies_comp_powerokwait: - case pies_comp_ctrlaltdel: - case pies_comp_ondemand: - case pies_comp_powerfailnow: - case pies_comp_kbrequest: - /* FIXME */ - return 0; - } + case boot: + return comp->mode == pies_comp_boot || comp->mode == pies_comp_bootwait; - if (!comp->runlevels) - return 1; - return !!strchr (comp->runlevels, runlevel); + case single0: + case single1: + case normal: + switch (comp->mode) + { + case pies_comp_sysinit: + case pies_comp_boot: + case pies_comp_bootwait: + return 0; + case pies_comp_powerfail: + case pies_comp_powerwait: + case pies_comp_powerokwait: + case pies_comp_ctrlaltdel: + case pies_comp_ondemand: + case pies_comp_powerfailnow: + case pies_comp_kbrequest: + /* FIXME */ + return 0; } } - return 1; + rc = !!strchr (comp->runlevels, runlevel); + if (!rc) + return rc; + if (finished) + return -1; + if (wait) + { + if (comp->mode == pies_comp_wait) + { + *wait = 1; + return 1; + } + return 0; + } + return rc; } void +sysvinit_begin () +{ + progman_sysvinit_enable (enablecomp, NULL); +} + +int inittrans () { int n; int newlevel = 0; enum boot_state newstate; - + int trans = 0; + static int wait = 0; + if (progman_running_p ()) /* Noting to do if there are processes left in the previous runlevel */ - return; + return 0; - n = runlevel_index (runlevel); + if (runlevel == 0) + n = runlevel_index (dfl_level ? dfl_level : initdefault); + else + n = runlevel_index (runlevel); if (n == -1) - n = 11; /* assume S */ + n = runlevel_index ('S'); newstate = boot_trans_tab[boot_state][n]; + debug (1, ("STATE TRANS: %s(%c,%d) -> %s", boot_state_name[boot_state], + runlevel,n, + boot_state_name[newstate])); if (newstate != boot_state) { debug (1, ("STATE TRANS: %s -> %s", boot_state_name[boot_state], boot_state_name[newstate])); boot_state = newstate; + trans = 1; } switch (boot_state) @@ -150,7 +179,22 @@ inittrans () { debug (1, ("RL TRANS: %c -> %c", runlevel, newlevel)); runlevel = newlevel; + trans = 1; + wait = 0; + } + if (wait) + trans = 1; + if (trans) + { + if (wait == 0) + { + progman_sysvinit_enable (enablecomp, &wait); + if (wait) + return 1; + } + progman_sysvinit_enable (enablecomp, NULL); } + return trans; } /* Return true if the progman should wait for the component to -- cgit v1.2.1