aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2015-03-02 17:37:31 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2015-03-02 17:37:31 +0100
commitfa535f3e485456a7fd85db060532ea6539670af0 (patch)
tree9107bd0622a7af4abcf8ae08e5ae2d77de4d5669
parent1eafd4494706c21a87dc66e4e0afa8799b576cb5 (diff)
downloadbusybox-w32-fa535f3e485456a7fd85db060532ea6539670af0.tar.gz
busybox-w32-fa535f3e485456a7fd85db060532ea6539670af0.tar.bz2
busybox-w32-fa535f3e485456a7fd85db060532ea6539670af0.zip
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>
-rw-r--r--runit/runsvdir.c53
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 {
59 int svnum; 59 int svnum;
60#if ENABLE_FEATURE_RUNSVDIR_LOG 60#if ENABLE_FEATURE_RUNSVDIR_LOG
61 char *rplog; 61 char *rplog;
62 int rploglen;
63 struct fd_pair logpipe; 62 struct fd_pair logpipe;
64 struct pollfd pfd[1]; 63 struct pollfd pfd[1];
65 unsigned stamplog; 64 unsigned stamplog;
@@ -70,7 +69,6 @@ struct globals {
70#define svdir (G.svdir ) 69#define svdir (G.svdir )
71#define svnum (G.svnum ) 70#define svnum (G.svnum )
72#define rplog (G.rplog ) 71#define rplog (G.rplog )
73#define rploglen (G.rploglen )
74#define logpipe (G.logpipe ) 72#define logpipe (G.logpipe )
75#define pfd (G.pfd ) 73#define pfd (G.pfd )
76#define stamplog (G.stamplog ) 74#define stamplog (G.stamplog )
@@ -219,15 +217,11 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv)
219 struct stat s; 217 struct stat s;
220 dev_t last_dev = last_dev; /* for gcc */ 218 dev_t last_dev = last_dev; /* for gcc */
221 ino_t last_ino = last_ino; /* for gcc */ 219 ino_t last_ino = last_ino; /* for gcc */
222 time_t last_mtime = 0; 220 time_t last_mtime;
223 int wstat;
224 int curdir; 221 int curdir;
225 pid_t pid;
226 unsigned deadline;
227 unsigned now;
228 unsigned stampcheck; 222 unsigned stampcheck;
229 int i; 223 int i;
230 int need_rescan = 1; 224 int need_rescan;
231 char *opt_s_argv[3]; 225 char *opt_s_argv[3];
232 226
233 INIT_G(); 227 INIT_G();
@@ -257,8 +251,7 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv)
257 /* setup log */ 251 /* setup log */
258 if (*argv) { 252 if (*argv) {
259 rplog = *argv; 253 rplog = *argv;
260 rploglen = strlen(rplog); 254 if (strlen(rplog) < 7) {
261 if (rploglen < 7) {
262 warnx("log must have at least seven characters"); 255 warnx("log must have at least seven characters");
263 } else if (piped_pair(logpipe)) { 256 } else if (piped_pair(logpipe)) {
264 warnx("can't create pipe for log"); 257 warnx("can't create pipe for log");
@@ -287,11 +280,16 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv)
287 close_on_exec_on(curdir); 280 close_on_exec_on(curdir);
288 281
289 stampcheck = monotonic_sec(); 282 stampcheck = monotonic_sec();
283 need_rescan = 1;
284 last_mtime = 0;
290 285
291 for (;;) { 286 for (;;) {
287 unsigned now;
288 unsigned sig;
289
292 /* collect children */ 290 /* collect children */
293 for (;;) { 291 for (;;) {
294 pid = wait_any_nohang(&wstat); 292 pid_t pid = wait_any_nohang(NULL);
295 if (pid <= 0) 293 if (pid <= 0)
296 break; 294 break;
297 for (i = 0; i < svnum; i++) { 295 for (i = 0; i < svnum; i++) {
@@ -345,15 +343,17 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv)
345 } 343 }
346 pfd[0].revents = 0; 344 pfd[0].revents = 0;
347#endif 345#endif
348 deadline = (need_rescan ? 1 : 5); 346 {
349 sig_block(SIGCHLD); 347 unsigned deadline = (need_rescan ? 1 : 5);
348 sig_block(SIGCHLD);
350#if ENABLE_FEATURE_RUNSVDIR_LOG 349#if ENABLE_FEATURE_RUNSVDIR_LOG
351 if (rplog) 350 if (rplog)
352 poll(pfd, 1, deadline*1000); 351 poll(pfd, 1, deadline*1000);
353 else 352 else
354#endif 353#endif
355 sleep(deadline); 354 sleep(deadline);
356 sig_unblock(SIGCHLD); 355 sig_unblock(SIGCHLD);
356 }
357 357
358#if ENABLE_FEATURE_RUNSVDIR_LOG 358#if ENABLE_FEATURE_RUNSVDIR_LOG
359 if (pfd[0].revents & POLLIN) { 359 if (pfd[0].revents & POLLIN) {
@@ -361,21 +361,25 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv)
361 while (read(logpipe.rd, &ch, 1) > 0) { 361 while (read(logpipe.rd, &ch, 1) > 0) {
362 if (ch < ' ') 362 if (ch < ' ')
363 ch = ' '; 363 ch = ' ';
364 for (i = 6; i < rploglen; i++) 364 for (i = 6; rplog[i] != '\0'; i++)
365 rplog[i-1] = rplog[i]; 365 rplog[i-1] = rplog[i];
366 rplog[rploglen-1] = ch; 366 rplog[i-1] = ch;
367 } 367 }
368 } 368 }
369#endif 369#endif
370 if (!bb_got_signal) 370 sig = bb_got_signal;
371 if (!sig)
371 continue; 372 continue;
373 bb_got_signal = 0;
372 374
373 /* -s SCRIPT: useful if we are init. 375 /* -s SCRIPT: useful if we are init.
374 * In this case typically script never returns, 376 * In this case typically script never returns,
375 * it halts/powers off/reboots the system. */ 377 * it halts/powers off/reboots the system. */
376 if (opt_s_argv[0]) { 378 if (opt_s_argv[0]) {
379 pid_t pid;
380
377 /* Single parameter: signal# */ 381 /* Single parameter: signal# */
378 opt_s_argv[1] = utoa(bb_got_signal); 382 opt_s_argv[1] = utoa(sig);
379 pid = spawn(opt_s_argv); 383 pid = spawn(opt_s_argv);
380 if (pid > 0) { 384 if (pid > 0) {
381 /* Remembering to wait for _any_ children, 385 /* Remembering to wait for _any_ children,
@@ -385,7 +389,7 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv)
385 } 389 }
386 } 390 }
387 391
388 if (bb_got_signal == SIGHUP) { 392 if (sig == SIGHUP) {
389 for (i = 0; i < svnum; i++) 393 for (i = 0; i < svnum; i++)
390 if (sv[i].pid) 394 if (sv[i].pid)
391 kill(sv[i].pid, SIGTERM); 395 kill(sv[i].pid, SIGTERM);
@@ -393,9 +397,8 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv)
393 /* SIGHUP or SIGTERM (or SIGUSRn if we are init) */ 397 /* SIGHUP or SIGTERM (or SIGUSRn if we are init) */
394 /* Exit unless we are init */ 398 /* Exit unless we are init */
395 if (getpid() != 1) 399 if (getpid() != 1)
396 return (SIGHUP == bb_got_signal) ? 111 : EXIT_SUCCESS; 400 return (SIGHUP == sig) ? 111 : EXIT_SUCCESS;
397 401
398 /* init continues to monitor services forever */ 402 /* init continues to monitor services forever */
399 bb_got_signal = 0;
400 } /* for (;;) */ 403 } /* for (;;) */
401} 404}