diff options
| author | Denys Vlasenko <vda.linux@googlemail.com> | 2019-01-14 14:45:18 +0100 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2019-01-14 14:47:21 +0100 |
| commit | 088fec36fedff2cd50437c95b7fb430abf8d303c (patch) | |
| tree | f0dd190ed56fdf4b43710331e3527149903d87d2 /debianutils | |
| parent | b67d900395a847e29f2afa81198f783004c80fc5 (diff) | |
| download | busybox-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>
Diffstat (limited to 'debianutils')
| -rw-r--r-- | debianutils/start_stop_daemon.c | 66 |
1 files changed, 44 insertions, 22 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 | } |
