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 /src | |
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
Diffstat (limited to 'src')
-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, | |||
2149 | if (strlen (val->v.s) == 1 | 2149 | if (strlen (val->v.s) == 1 |
2150 | && sysvinit_set_runlevel (val->v.s[0]) == 0) | 2150 | && sysvinit_set_runlevel (val->v.s[0]) == 0) |
2151 | { | 2151 | { |
2152 | pies_schedule_action (ACTION_RELOAD); | ||
2153 | json_object_set_string (io->output.reply, "status", "OK"); | 2152 | json_object_set_string (io->output.reply, "status", "OK"); |
2154 | } | 2153 | } |
2155 | else | 2154 | else |
@@ -2220,9 +2220,7 @@ main (int argc, char **argv) | |||
2220 | 2220 | ||
2221 | do | 2221 | do |
2222 | { | 2222 | { |
2223 | if (init_process && inittrans ()) | 2223 | if (children_op == PIES_CHLD_NONE) |
2224 | action = ACTION_CONT; | ||
2225 | else if (children_op == PIES_CHLD_NONE) | ||
2226 | pies_pause (); | 2224 | pies_pause (); |
2227 | switch (action) | 2225 | switch (action) |
2228 | { | 2226 | { |
@@ -417,6 +417,7 @@ struct component *component_depmap_next (pies_depmap_pos_t pos); | |||
417 | 417 | ||
418 | 418 | ||
419 | 419 | ||
420 | void pies_set_hook (int (*f) (void)); | ||
420 | void pies_pause (void); | 421 | void pies_pause (void); |
421 | 422 | ||
422 | enum | 423 | enum |
@@ -531,7 +532,6 @@ struct inetd_builtin *inetd_builtin_lookup (const char *service, int socktype); | |||
531 | 532 | ||
532 | /* sysvinit.c */ | 533 | /* sysvinit.c */ |
533 | void sysvinit_begin (void); | 534 | void sysvinit_begin (void); |
534 | int inittrans (void); | ||
535 | int is_comp_wait (struct component *comp); | 535 | int is_comp_wait (struct component *comp); |
536 | int is_valid_runlevel (int c); | 536 | int is_valid_runlevel (int c); |
537 | int console_open (int mode); | 537 | 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) | |||
559 | FD_SET (fd, &fdset[PIES_EVT_EX]); | 559 | FD_SET (fd, &fdset[PIES_EVT_EX]); |
560 | } | 560 | } |
561 | 561 | ||
562 | static int (*pies_pause_hook) (void); | ||
563 | |||
564 | void | ||
565 | pies_set_hook (int (*f) (void)) | ||
566 | { | ||
567 | pies_pause_hook = f; | ||
568 | } | ||
569 | |||
562 | void | 570 | void |
563 | pies_pause (void) | 571 | pies_pause (void) |
564 | { | 572 | { |
573 | if (pies_pause_hook && pies_pause_hook ()) | ||
574 | return; | ||
575 | |||
565 | if (fd_max == -1) | 576 | if (fd_max == -1) |
566 | calc_fd_max (); | 577 | calc_fd_max (); |
567 | 578 | ||
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; | |||
63 | char *emergency_shell = "/sbin/sulogin"; | 63 | char *emergency_shell = "/sbin/sulogin"; |
64 | int emergency; | 64 | int emergency; |
65 | 65 | ||
66 | static int inittrans (void); | ||
66 | 67 | ||
67 | int | 68 | int |
68 | console_open (int mode) | 69 | console_open (int mode) |
@@ -532,10 +533,10 @@ sysvinit_fifo_handler (int fd, void *data) | |||
532 | { | 533 | { |
533 | case INIT_CMD_RUNLVL: | 534 | case INIT_CMD_RUNLVL: |
534 | buf.req.runlevel = toupper (buf.req.runlevel); | 535 | buf.req.runlevel = toupper (buf.req.runlevel); |
535 | pies_schedule_action (ACTION_RELOAD); | ||
536 | switch (buf.req.runlevel) | 536 | switch (buf.req.runlevel) |
537 | { | 537 | { |
538 | case 'Q': | 538 | case 'Q': |
539 | pies_schedule_action (ACTION_RELOAD); | ||
539 | break; | 540 | break; |
540 | 541 | ||
541 | default: | 542 | default: |
@@ -799,6 +800,7 @@ sysvinit_begin (void) | |||
799 | add_extra_sigv (sigv, ARRAY_SIZE (sigv)); | 800 | add_extra_sigv (sigv, ARRAY_SIZE (sigv)); |
800 | sysvinit_sysdep_begin (); | 801 | sysvinit_sysdep_begin (); |
801 | save_argv (); | 802 | save_argv (); |
803 | pies_set_hook (inittrans); | ||
802 | if (emergency) | 804 | if (emergency) |
803 | start_shell (emergency_shell); | 805 | start_shell (emergency_shell); |
804 | } | 806 | } |
@@ -815,7 +817,8 @@ inittrans (void) | |||
815 | int newlevel = 0; | 817 | int newlevel = 0; |
816 | enum boot_state newstate; | 818 | enum boot_state newstate; |
817 | int trans = 0; | 819 | int trans = 0; |
818 | 820 | int userchg = 0; | |
821 | |||
819 | if (progman_waiting_p ()) | 822 | if (progman_waiting_p ()) |
820 | /* Noting to do if there are processes left in the previous runlevel */ | 823 | /* Noting to do if there are processes left in the previous runlevel */ |
821 | return 0; | 824 | return 0; |
@@ -855,6 +858,8 @@ inittrans (void) | |||
855 | ctl_open (); | 858 | ctl_open (); |
856 | diag_setup (DIAG_TO_SYSLOG | DIAG_REOPEN_LOG); | 859 | diag_setup (DIAG_TO_SYSLOG | DIAG_REOPEN_LOG); |
857 | } | 860 | } |
861 | else | ||
862 | userchg = 1; | ||
858 | } | 863 | } |
859 | if (newlevel && newlevel != runlevel) | 864 | if (newlevel && newlevel != runlevel) |
860 | { | 865 | { |
@@ -870,8 +875,14 @@ inittrans (void) | |||
870 | if (trans) | 875 | if (trans) |
871 | { | 876 | { |
872 | envsetup (); | 877 | envsetup (); |
873 | sysvinit_runlevel_setup (PIES_COMP_DEFAULT); | 878 | |
874 | pies_schedule_children (PIES_CHLD_WAKEUP); | 879 | if (userchg) |
880 | pies_schedule_action (ACTION_RELOAD); | ||
881 | else | ||
882 | { | ||
883 | sysvinit_runlevel_setup (PIES_COMP_DEFAULT); | ||
884 | pies_schedule_children (PIES_CHLD_WAKEUP); | ||
885 | } | ||
875 | } | 886 | } |
876 | return trans; | 887 | return trans; |
877 | } | 888 | } |
@@ -1254,8 +1265,7 @@ sysvinit_report (struct json_value *obj) | |||
1254 | json_object_set_string (obj, "bootstate", "%s", | 1265 | json_object_set_string (obj, "bootstate", "%s", |
1255 | boot_state_name[boot_state]); | 1266 | boot_state_name[boot_state]); |
1256 | if (initdefault) | 1267 | if (initdefault) |
1257 | json_object_set_string (obj, "initdefault", "%c", | 1268 | json_object_set_string (obj, "initdefault", "%c", initdefault); |
1258 | initdefault); | ||
1259 | } | 1269 | } |
1260 | 1270 | ||
1261 | void | 1271 | void |