diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2015-03-02 17:37:31 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2015-03-02 17:37:31 +0100 |
commit | fa535f3e485456a7fd85db060532ea6539670af0 (patch) | |
tree | 9107bd0622a7af4abcf8ae08e5ae2d77de4d5669 /runit/runsvdir.c | |
parent | 1eafd4494706c21a87dc66e4e0afa8799b576cb5 (diff) |
runsvdir: (almost) close a signal race
We could lose a signal while processing previous one
function old new delta
runsvdir_main 1088 1077 -11
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'runit/runsvdir.c')
-rw-r--r-- | runit/runsvdir.c | 53 |
1 files changed, 28 insertions, 25 deletions
diff --git a/runit/runsvdir.c b/runit/runsvdir.c index af7e75ba7..809c48a51 100644 --- a/runit/runsvdir.c +++ b/runit/runsvdir.c @@ -59,7 +59,6 @@ struct globals { int svnum; #if ENABLE_FEATURE_RUNSVDIR_LOG char *rplog; - int rploglen; struct fd_pair logpipe; struct pollfd pfd[1]; unsigned stamplog; @@ -70,7 +69,6 @@ struct globals { #define svdir (G.svdir ) #define svnum (G.svnum ) #define rplog (G.rplog ) -#define rploglen (G.rploglen ) #define logpipe (G.logpipe ) #define pfd (G.pfd ) #define stamplog (G.stamplog ) @@ -219,15 +217,11 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv) struct stat s; dev_t last_dev = last_dev; /* for gcc */ ino_t last_ino = last_ino; /* for gcc */ - time_t last_mtime = 0; - int wstat; + time_t last_mtime; int curdir; - pid_t pid; - unsigned deadline; - unsigned now; unsigned stampcheck; int i; - int need_rescan = 1; + int need_rescan; char *opt_s_argv[3]; INIT_G(); @@ -257,8 +251,7 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv) /* setup log */ if (*argv) { rplog = *argv; - rploglen = strlen(rplog); - if (rploglen < 7) { + if (strlen(rplog) < 7) { warnx("log must have at least seven characters"); } else if (piped_pair(logpipe)) { warnx("can't create pipe for log"); @@ -287,11 +280,16 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv) close_on_exec_on(curdir); stampcheck = monotonic_sec(); + need_rescan = 1; + last_mtime = 0; for (;;) { + unsigned now; + unsigned sig; + /* collect children */ for (;;) { - pid = wait_any_nohang(&wstat); + pid_t pid = wait_any_nohang(NULL); if (pid <= 0) break; for (i = 0; i < svnum; i++) { @@ -345,15 +343,17 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv) } pfd[0].revents = 0; #endif - deadline = (need_rescan ? 1 : 5); - sig_block(SIGCHLD); + { + unsigned deadline = (need_rescan ? 1 : 5); + sig_block(SIGCHLD); #if ENABLE_FEATURE_RUNSVDIR_LOG - if (rplog) - poll(pfd, 1, deadline*1000); - else + if (rplog) + poll(pfd, 1, deadline*1000); + else #endif - sleep(deadline); - sig_unblock(SIGCHLD); + sleep(deadline); + sig_unblock(SIGCHLD); + } #if ENABLE_FEATURE_RUNSVDIR_LOG if (pfd[0].revents & POLLIN) { @@ -361,21 +361,25 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv) while (read(logpipe.rd, &ch, 1) > 0) { if (ch < ' ') ch = ' '; - for (i = 6; i < rploglen; i++) + for (i = 6; rplog[i] != '\0'; i++) rplog[i-1] = rplog[i]; - rplog[rploglen-1] = ch; + rplog[i-1] = ch; } } #endif - if (!bb_got_signal) + sig = bb_got_signal; + if (!sig) continue; + bb_got_signal = 0; /* -s SCRIPT: useful if we are init. * In this case typically script never returns, * it halts/powers off/reboots the system. */ if (opt_s_argv[0]) { + pid_t pid; + /* Single parameter: signal# */ - opt_s_argv[1] = utoa(bb_got_signal); + opt_s_argv[1] = utoa(sig); pid = spawn(opt_s_argv); if (pid > 0) { /* Remembering to wait for _any_ children, @@ -385,7 +389,7 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv) } } - if (bb_got_signal == SIGHUP) { + if (sig == SIGHUP) { for (i = 0; i < svnum; i++) if (sv[i].pid) kill(sv[i].pid, SIGTERM); @@ -393,9 +397,8 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv) /* SIGHUP or SIGTERM (or SIGUSRn if we are init) */ /* Exit unless we are init */ if (getpid() != 1) - return (SIGHUP == bb_got_signal) ? 111 : EXIT_SUCCESS; + return (SIGHUP == sig) ? 111 : EXIT_SUCCESS; /* init continues to monitor services forever */ - bb_got_signal = 0; } /* for (;;) */ } |