diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2016-02-28 20:42:50 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2016-02-28 21:39:28 +0200 |
commit | 0d0a148121dcb8edd49cad900f27141336576f9d (patch) | |
tree | d458628bb80d5972f540826e1cf3fc8b8224265b | |
parent | 14e0802da5587179607f3340d105914435ee117a (diff) | |
download | pies-0d0a148121dcb8edd49cad900f27141336576f9d.tar.gz pies-0d0a148121dcb8edd49cad900f27141336576f9d.tar.bz2 |
Synchronize changes in runlevel with configuration reloads
State transition algorithm used this far could cause spurious component
wakeups in some cases. Consider the following scenario: being in
runlevel N, the configuration is changed so that a component X is added
at runlevel N. Then a change to runlevel N+1 is initiated. What happens
then is that X is woken up (still being in runlevel N) and terminated
shortly afterwards, upon entering runlevel N+1.
To avoid this, configuration must be reloaded after runlevel changes.
* src/ctl.c (res_runlevel): Don't initiate ACTION_RELOAD after
setting the runlevel.
* src/pies.c (main): Begin main event loop with call
to pies_pause.
* src/pies.h (pies_set_hook): New proto.
(inittrans): Remove proto.
* src/socket.c (pies_set_hook): New function.
(pies_pause): Call pies_pause_hook if defined.
* src/sysvinit.c (inittrans): Change to static.
If transition was initiated by user (e.g. by invoking telinit),
schedule ACTION_RELOAD.
(sysvinit_begin): Set inittrans as pies_hook
-rw-r--r-- | src/ctl.c | 1 | ||||
-rw-r--r-- | src/pies.c | 4 | ||||
-rw-r--r-- | src/pies.h | 2 | ||||
-rw-r--r-- | src/socket.c | 11 | ||||
-rw-r--r-- | src/sysvinit.c | 24 |
5 files changed, 30 insertions, 12 deletions
@@ -2149,7 +2149,6 @@ res_runlevel (struct ctlio *io, enum http_method meth, if (strlen (val->v.s) == 1 && sysvinit_set_runlevel (val->v.s[0]) == 0) { - pies_schedule_action (ACTION_RELOAD); json_object_set_string (io->output.reply, "status", "OK"); } else @@ -2220,9 +2220,7 @@ main (int argc, char **argv) do { - if (init_process && inittrans ()) - action = ACTION_CONT; - else if (children_op == PIES_CHLD_NONE) + if (children_op == PIES_CHLD_NONE) pies_pause (); switch (action) { @@ -417,6 +417,7 @@ struct component *component_depmap_next (pies_depmap_pos_t pos); +void pies_set_hook (int (*f) (void)); void pies_pause (void); enum @@ -531,7 +532,6 @@ struct inetd_builtin *inetd_builtin_lookup (const char *service, int socktype); /* sysvinit.c */ void sysvinit_begin (void); -int inittrans (void); int is_comp_wait (struct component *comp); int is_valid_runlevel (int c); int console_open (int mode); diff --git a/src/socket.c b/src/socket.c index 2b2bc52..0a0a3a9 100644 --- a/src/socket.c +++ b/src/socket.c @@ -559,9 +559,20 @@ enable_socket (int fd) FD_SET (fd, &fdset[PIES_EVT_EX]); } +static int (*pies_pause_hook) (void); + +void +pies_set_hook (int (*f) (void)) +{ + pies_pause_hook = f; +} + void pies_pause (void) { + if (pies_pause_hook && pies_pause_hook ()) + return; + if (fd_max == -1) calc_fd_max (); diff --git a/src/sysvinit.c b/src/sysvinit.c index 46d62c3..f4ef101 100644 --- a/src/sysvinit.c +++ b/src/sysvinit.c @@ -63,6 +63,7 @@ int dfl_level; char *emergency_shell = "/sbin/sulogin"; int emergency; +static int inittrans (void); int console_open (int mode) @@ -532,10 +533,10 @@ sysvinit_fifo_handler (int fd, void *data) { case INIT_CMD_RUNLVL: buf.req.runlevel = toupper (buf.req.runlevel); - pies_schedule_action (ACTION_RELOAD); switch (buf.req.runlevel) { - case 'Q': + case 'Q': + pies_schedule_action (ACTION_RELOAD); break; default: @@ -799,6 +800,7 @@ sysvinit_begin (void) add_extra_sigv (sigv, ARRAY_SIZE (sigv)); sysvinit_sysdep_begin (); save_argv (); + pies_set_hook (inittrans); if (emergency) start_shell (emergency_shell); } @@ -815,7 +817,8 @@ inittrans (void) int newlevel = 0; enum boot_state newstate; int trans = 0; - + int userchg = 0; + if (progman_waiting_p ()) /* Noting to do if there are processes left in the previous runlevel */ return 0; @@ -855,6 +858,8 @@ inittrans (void) ctl_open (); diag_setup (DIAG_TO_SYSLOG | DIAG_REOPEN_LOG); } + else + userchg = 1; } if (newlevel && newlevel != runlevel) { @@ -870,8 +875,14 @@ inittrans (void) if (trans) { envsetup (); - sysvinit_runlevel_setup (PIES_COMP_DEFAULT); - pies_schedule_children (PIES_CHLD_WAKEUP); + + if (userchg) + pies_schedule_action (ACTION_RELOAD); + else + { + sysvinit_runlevel_setup (PIES_COMP_DEFAULT); + pies_schedule_children (PIES_CHLD_WAKEUP); + } } return trans; } @@ -1254,8 +1265,7 @@ sysvinit_report (struct json_value *obj) json_object_set_string (obj, "bootstate", "%s", boot_state_name[boot_state]); if (initdefault) - json_object_set_string (obj, "initdefault", "%c", - initdefault); + json_object_set_string (obj, "initdefault", "%c", initdefault); } void |