aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2019-01-14 14:45:18 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2019-01-14 14:47:21 +0100
commit088fec36fedff2cd50437c95b7fb430abf8d303c (patch)
treef0dd190ed56fdf4b43710331e3527149903d87d2
parentb67d900395a847e29f2afa81198f783004c80fc5 (diff)
downloadbusybox-w32-088fec36fedff2cd50437c95b7fb430abf8d303c.tar.gz
busybox-w32-088fec36fedff2cd50437c95b7fb430abf8d303c.tar.bz2
busybox-w32-088fec36fedff2cd50437c95b7fb430abf8d303c.zip
start-stop-daemon: create pidfile before parent exits, closes 8596
This removes DAEMON_DOUBLE_FORK flag from bb_daemonize_or_rexec(), as SSD was the only user. Also includes fix for -S: now works without -a and -x, does not print pids (compat with "start-stop-daemon (OpenRC) 0.34.11 (Gentoo Linux)"). function old new delta start_stop_daemon_main 1018 1084 +66 add_interface 99 103 +4 fail_hunk 139 136 -3 bb_daemonize_or_rexec 205 183 -22 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/2 up/down: 70/-25) Total: 45 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--debianutils/start_stop_daemon.c66
-rw-r--r--include/libbb.h10
-rw-r--r--libbb/vfork_daemon_rexec.c16
-rwxr-xr-xtestsuite/start-stop-daemon.tests5
4 files changed, 62 insertions, 35 deletions
diff --git a/debianutils/start_stop_daemon.c b/debianutils/start_stop_daemon.c
index 43b6fca26..fa08f48cf 100644
--- a/debianutils/start_stop_daemon.c
+++ b/debianutils/start_stop_daemon.c
@@ -409,7 +409,7 @@ int start_stop_daemon_main(int argc UNUSED_PARAM, char **argv)
409{ 409{
410 unsigned opt; 410 unsigned opt;
411 char *signame; 411 char *signame;
412 char *startas; 412 char *startas = NULL;
413 char *chuid; 413 char *chuid;
414#if ENABLE_FEATURE_START_STOP_DAEMON_FANCY 414#if ENABLE_FEATURE_START_STOP_DAEMON_FANCY
415// char *retry_arg = NULL; 415// char *retry_arg = NULL;
@@ -425,10 +425,11 @@ int start_stop_daemon_main(int argc UNUSED_PARAM, char **argv)
425 /* -K or -S is required; they are mutually exclusive */ 425 /* -K or -S is required; they are mutually exclusive */
426 /* -p is required if -m is given */ 426 /* -p is required if -m is given */
427 /* -xpun (at least one) is required if -K is given */ 427 /* -xpun (at least one) is required if -K is given */
428 /* -xa (at least one) is required if -S is given */ 428// /* -xa (at least one) is required if -S is given */
429//WRONG: "start-stop-daemon -S -- sleep 5" is a valid invocation
429 /* -q turns off -v */ 430 /* -q turns off -v */
430 "\0" 431 "\0"
431 "K:S:K--S:S--K:m?p:K?xpun:S?xa" 432 "K:S:K--S:S--K:m?p:K?xpun"
432 IF_FEATURE_START_STOP_DAEMON_FANCY("q-v"), 433 IF_FEATURE_START_STOP_DAEMON_FANCY("q-v"),
433 LONGOPTS 434 LONGOPTS
434 &startas, &cmdname, &signame, &userspec, &chuid, &execname, &pidfile 435 &startas, &cmdname, &signame, &userspec, &chuid, &execname, &pidfile
@@ -442,21 +443,34 @@ int start_stop_daemon_main(int argc UNUSED_PARAM, char **argv)
442 if (signal_nr < 0) bb_show_usage(); 443 if (signal_nr < 0) bb_show_usage();
443 } 444 }
444 445
445 if (!(opt & OPT_a)) 446 //argc -= optind;
446 startas = execname; 447 argv += optind;
447 if (!execname) /* in case -a is given and -x is not */ 448// ARGS contains zeroth arg if -x/-a is not given, else it starts with 1st arg.
449// These will try to execute "[/bin/]sleep 5":
450// "start-stop-daemon -S -- sleep 5"
451// "start-stop-daemon -S -x /bin/sleep -- 5"
452// "start-stop-daemon -S -a sleep -- 5"
453// NB: -n option does _not_ behave in this way: this will try to execute "5":
454// "start-stop-daemon -S -n sleep -- 5"
455 if (!execname) { /* -x is not given */
448 execname = startas; 456 execname = startas;
449 if (execname) { 457 if (!execname) { /* neither -x nor -a is given */
450 G.execname_sizeof = strlen(execname) + 1; 458 execname = argv[0];
451 G.execname_cmpbuf = xmalloc(G.execname_sizeof + 1); 459 if (!execname)
460 bb_show_usage();
461 argv++;
462 }
452 } 463 }
464 if (!startas) /* -a is not given: use -x EXECUTABLE or argv[0] */
465 startas = execname;
466 *--argv = startas;
467 G.execname_sizeof = strlen(execname) + 1;
468 G.execname_cmpbuf = xmalloc(G.execname_sizeof + 1);
453 469
454// IF_FEATURE_START_STOP_DAEMON_FANCY( 470// IF_FEATURE_START_STOP_DAEMON_FANCY(
455// if (retry_arg) 471// if (retry_arg)
456// retries = xatoi_positive(retry_arg); 472// retries = xatoi_positive(retry_arg);
457// ) 473// )
458 //argc -= optind;
459 argv += optind;
460 474
461 if (userspec) { 475 if (userspec) {
462 user_id = bb_strtou(userspec, NULL, 10); 476 user_id = bb_strtou(userspec, NULL, 10);
@@ -473,7 +487,7 @@ int start_stop_daemon_main(int argc UNUSED_PARAM, char **argv)
473 487
474 if (G.found_procs) { 488 if (G.found_procs) {
475 if (!QUIET) 489 if (!QUIET)
476 printf("%s is already running\n%u\n", execname, (unsigned)G.found_procs->pid); 490 printf("%s is already running\n", execname);
477 return !(opt & OPT_OKNODO); 491 return !(opt & OPT_OKNODO);
478 } 492 }
479 493
@@ -482,30 +496,37 @@ int start_stop_daemon_main(int argc UNUSED_PARAM, char **argv)
482 xstat(execname, &G.execstat); 496 xstat(execname, &G.execstat);
483#endif 497#endif
484 498
485 *--argv = startas;
486 if (opt & OPT_BACKGROUND) { 499 if (opt & OPT_BACKGROUND) {
487#if BB_MMU
488 bb_daemonize(DAEMON_DEVNULL_STDIO + DAEMON_CLOSE_EXTRA_FDS + DAEMON_DOUBLE_FORK);
489 /* DAEMON_DEVNULL_STDIO is superfluous -
490 * it's always done by bb_daemonize() */
491#else
492 /* Daemons usually call bb_daemonize_or_rexec(), but SSD can do 500 /* Daemons usually call bb_daemonize_or_rexec(), but SSD can do
493 * without: SSD is not itself a daemon, it _execs_ a daemon. 501 * without: SSD is not itself a daemon, it _execs_ a daemon.
494 * The usual NOMMU problem of "child can't run indefinitely, 502 * The usual NOMMU problem of "child can't run indefinitely,
495 * it must exec" does not bite us: we exec anyway. 503 * it must exec" does not bite us: we exec anyway.
504 *
505 * bb_daemonize(DAEMON_DEVNULL_STDIO | DAEMON_CLOSE_EXTRA_FDS | DAEMON_DOUBLE_FORK)
506 * can be used on MMU systems, but use of vfork()
507 * is preferable since we want to create pidfile
508 * _before_ parent returns, and vfork() on Linux
509 * ensures that (by blocking parent until exec in the child).
496 */ 510 */
497 pid_t pid = xvfork(); 511 pid_t pid = xvfork();
498 if (pid != 0) { 512 if (pid != 0) {
499 /* parent */ 513 /* Parent */
500 /* why _exit? the child may have changed the stack, 514 /* why _exit? the child may have changed the stack,
501 * so "return 0" may do bad things */ 515 * so "return 0" may do bad things
516 */
502 _exit(EXIT_SUCCESS); 517 _exit(EXIT_SUCCESS);
503 } 518 }
504 /* Child */ 519 /* Child */
505 setsid(); /* detach from controlling tty */ 520 setsid(); /* detach from controlling tty */
506 /* Redirect stdio to /dev/null, close extra FDs */ 521 /* Redirect stdio to /dev/null, close extra FDs */
507 bb_daemon_helper(DAEMON_DEVNULL_STDIO + DAEMON_CLOSE_EXTRA_FDS); 522 bb_daemon_helper(DAEMON_DEVNULL_STDIO + DAEMON_CLOSE_EXTRA_FDS);
508#endif 523 /* On Linux, session leader can acquire ctty
524 * unknowingly, by opening a tty.
525 * Prevent this: stop being a session leader.
526 */
527 pid = xvfork();
528 if (pid != 0)
529 _exit(EXIT_SUCCESS); /* Parent */
509 } 530 }
510 if (opt & OPT_MAKEPID) { 531 if (opt & OPT_MAKEPID) {
511 /* User wants _us_ to make the pidfile */ 532 /* User wants _us_ to make the pidfile */
@@ -534,6 +555,7 @@ int start_stop_daemon_main(int argc UNUSED_PARAM, char **argv)
534 } 555 }
535 } 556 }
536#endif 557#endif
537 execvp(startas, argv); 558//bb_error_msg("HERE %d '%s'%s'", __LINE__, argv[0], argv[1]);
559 execvp(argv[0], argv);
538 bb_perror_msg_and_die("can't execute '%s'", startas); 560 bb_perror_msg_and_die("can't execute '%s'", startas);
539} 561}
diff --git a/include/libbb.h b/include/libbb.h
index d2563999a..3366df30f 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -1201,11 +1201,11 @@ void set_task_comm(const char *comm) FAST_FUNC;
1201 * to /dev/null if they are not. 1201 * to /dev/null if they are not.
1202 */ 1202 */
1203enum { 1203enum {
1204 DAEMON_CHDIR_ROOT = 1, 1204 DAEMON_CHDIR_ROOT = 1 << 0,
1205 DAEMON_DEVNULL_STDIO = 2, 1205 DAEMON_DEVNULL_STDIO = 1 << 1,
1206 DAEMON_CLOSE_EXTRA_FDS = 4, 1206 DAEMON_CLOSE_EXTRA_FDS = 1 << 2,
1207 DAEMON_ONLY_SANITIZE = 8, /* internal use */ 1207 DAEMON_ONLY_SANITIZE = 1 << 3, /* internal use */
1208 DAEMON_DOUBLE_FORK = 16, /* double fork to avoid controlling tty */ 1208 //DAEMON_DOUBLE_FORK = 1 << 4, /* double fork to avoid controlling tty */
1209}; 1209};
1210#if BB_MMU 1210#if BB_MMU
1211 enum { re_execed = 0 }; 1211 enum { re_execed = 0 };
diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c
index c0bea0ed2..1aac27b36 100644
--- a/libbb/vfork_daemon_rexec.c
+++ b/libbb/vfork_daemon_rexec.c
@@ -292,14 +292,14 @@ void FAST_FUNC bb_daemonize_or_rexec(int flags, char **argv)
292 dup2(fd, 0); 292 dup2(fd, 0);
293 dup2(fd, 1); 293 dup2(fd, 1);
294 dup2(fd, 2); 294 dup2(fd, 2);
295 if (flags & DAEMON_DOUBLE_FORK) { 295// if (flags & DAEMON_DOUBLE_FORK) {
296 /* On Linux, session leader can acquire ctty 296// /* On Linux, session leader can acquire ctty
297 * unknowingly, by opening a tty. 297// * unknowingly, by opening a tty.
298 * Prevent this: stop being a session leader. 298// * Prevent this: stop being a session leader.
299 */ 299// */
300 if (fork_or_rexec(argv)) 300// if (fork_or_rexec(argv))
301 _exit(EXIT_SUCCESS); /* parent */ 301// _exit(EXIT_SUCCESS); /* parent */
302 } 302// }
303 } 303 }
304 while (fd > 2) { 304 while (fd > 2) {
305 close(fd--); 305 close(fd--);
diff --git a/testsuite/start-stop-daemon.tests b/testsuite/start-stop-daemon.tests
index d07aeef0e..be1c1a856 100755
--- a/testsuite/start-stop-daemon.tests
+++ b/testsuite/start-stop-daemon.tests
@@ -16,4 +16,9 @@ testing "start-stop-daemon -a without -x" \
16 "1\n" \ 16 "1\n" \
17 "" "" 17 "" ""
18 18
19testing "start-stop-daemon without -x and -a" \
20 'start-stop-daemon -S false 2>&1; echo $?' \
21 "1\n" \
22 "" ""
23
19exit $FAILCOUNT 24exit $FAILCOUNT