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>
This commit is contained in:
Denys Vlasenko 2015-03-02 17:37:31 +01:00
parent 1eafd44947
commit fa535f3e48

View File

@ -59,7 +59,6 @@ struct globals {
int svnum; int svnum;
#if ENABLE_FEATURE_RUNSVDIR_LOG #if ENABLE_FEATURE_RUNSVDIR_LOG
char *rplog; char *rplog;
int rploglen;
struct fd_pair logpipe; struct fd_pair logpipe;
struct pollfd pfd[1]; struct pollfd pfd[1];
unsigned stamplog; unsigned stamplog;
@ -70,7 +69,6 @@ struct globals {
#define svdir (G.svdir ) #define svdir (G.svdir )
#define svnum (G.svnum ) #define svnum (G.svnum )
#define rplog (G.rplog ) #define rplog (G.rplog )
#define rploglen (G.rploglen )
#define logpipe (G.logpipe ) #define logpipe (G.logpipe )
#define pfd (G.pfd ) #define pfd (G.pfd )
#define stamplog (G.stamplog ) #define stamplog (G.stamplog )
@ -219,15 +217,11 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv)
struct stat s; struct stat s;
dev_t last_dev = last_dev; /* for gcc */ dev_t last_dev = last_dev; /* for gcc */
ino_t last_ino = last_ino; /* for gcc */ ino_t last_ino = last_ino; /* for gcc */
time_t last_mtime = 0; time_t last_mtime;
int wstat;
int curdir; int curdir;
pid_t pid;
unsigned deadline;
unsigned now;
unsigned stampcheck; unsigned stampcheck;
int i; int i;
int need_rescan = 1; int need_rescan;
char *opt_s_argv[3]; char *opt_s_argv[3];
INIT_G(); INIT_G();
@ -257,8 +251,7 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv)
/* setup log */ /* setup log */
if (*argv) { if (*argv) {
rplog = *argv; rplog = *argv;
rploglen = strlen(rplog); if (strlen(rplog) < 7) {
if (rploglen < 7) {
warnx("log must have at least seven characters"); warnx("log must have at least seven characters");
} else if (piped_pair(logpipe)) { } else if (piped_pair(logpipe)) {
warnx("can't create pipe for log"); 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); close_on_exec_on(curdir);
stampcheck = monotonic_sec(); stampcheck = monotonic_sec();
need_rescan = 1;
last_mtime = 0;
for (;;) { for (;;) {
unsigned now;
unsigned sig;
/* collect children */ /* collect children */
for (;;) { for (;;) {
pid = wait_any_nohang(&wstat); pid_t pid = wait_any_nohang(NULL);
if (pid <= 0) if (pid <= 0)
break; break;
for (i = 0; i < svnum; i++) { for (i = 0; i < svnum; i++) {
@ -345,15 +343,17 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv)
} }
pfd[0].revents = 0; pfd[0].revents = 0;
#endif #endif
deadline = (need_rescan ? 1 : 5); {
sig_block(SIGCHLD); unsigned deadline = (need_rescan ? 1 : 5);
sig_block(SIGCHLD);
#if ENABLE_FEATURE_RUNSVDIR_LOG #if ENABLE_FEATURE_RUNSVDIR_LOG
if (rplog) if (rplog)
poll(pfd, 1, deadline*1000); poll(pfd, 1, deadline*1000);
else else
#endif #endif
sleep(deadline); sleep(deadline);
sig_unblock(SIGCHLD); sig_unblock(SIGCHLD);
}
#if ENABLE_FEATURE_RUNSVDIR_LOG #if ENABLE_FEATURE_RUNSVDIR_LOG
if (pfd[0].revents & POLLIN) { 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) { while (read(logpipe.rd, &ch, 1) > 0) {
if (ch < ' ') if (ch < ' ')
ch = ' '; ch = ' ';
for (i = 6; i < rploglen; i++) for (i = 6; rplog[i] != '\0'; i++)
rplog[i-1] = rplog[i]; rplog[i-1] = rplog[i];
rplog[rploglen-1] = ch; rplog[i-1] = ch;
} }
} }
#endif #endif
if (!bb_got_signal) sig = bb_got_signal;
if (!sig)
continue; continue;
bb_got_signal = 0;
/* -s SCRIPT: useful if we are init. /* -s SCRIPT: useful if we are init.
* In this case typically script never returns, * In this case typically script never returns,
* it halts/powers off/reboots the system. */ * it halts/powers off/reboots the system. */
if (opt_s_argv[0]) { if (opt_s_argv[0]) {
pid_t pid;
/* Single parameter: signal# */ /* Single parameter: signal# */
opt_s_argv[1] = utoa(bb_got_signal); opt_s_argv[1] = utoa(sig);
pid = spawn(opt_s_argv); pid = spawn(opt_s_argv);
if (pid > 0) { if (pid > 0) {
/* Remembering to wait for _any_ children, /* 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++) for (i = 0; i < svnum; i++)
if (sv[i].pid) if (sv[i].pid)
kill(sv[i].pid, SIGTERM); 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) */ /* SIGHUP or SIGTERM (or SIGUSRn if we are init) */
/* Exit unless we are init */ /* Exit unless we are init */
if (getpid() != 1) if (getpid() != 1)
return (SIGHUP == bb_got_signal) ? 111 : EXIT_SUCCESS; return (SIGHUP == sig) ? 111 : EXIT_SUCCESS;
/* init continues to monitor services forever */ /* init continues to monitor services forever */
bb_got_signal = 0;
} /* for (;;) */ } /* for (;;) */
} }