bb_daemonize_or_rexec(): add flag to double-fork; use it in start-stop-daemon

Add a DAEMON_DOUBLE_FORK flag to make bb_daemonize double-fork so it isn't a
session leader, and hence doesn't get a controlling tty on Linux if a tty is
ever opened, similar to how libdaemon's daemon_fork or the big
start-stop-daemon does it - And use it in start-stop-daemon.

For details, see http://www.win.tue.nl/~aeb/linux/lk/lk-10.html#ss10.3

Signed-off-by: Peter Korsgaard <jacmet@sunsite.dk>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Peter Korsgaard 2011-11-09 19:44:37 +01:00 committed by Denys Vlasenko
parent 7e21f0491c
commit 743edac6c8
3 changed files with 11 additions and 2 deletions

View File

@ -474,7 +474,7 @@ int start_stop_daemon_main(int argc UNUSED_PARAM, char **argv)
*--argv = startas; *--argv = startas;
if (opt & OPT_BACKGROUND) { if (opt & OPT_BACKGROUND) {
#if BB_MMU #if BB_MMU
bb_daemonize(DAEMON_DEVNULL_STDIO + DAEMON_CLOSE_EXTRA_FDS); bb_daemonize(DAEMON_DEVNULL_STDIO + DAEMON_CLOSE_EXTRA_FDS + DAEMON_DOUBLE_FORK);
/* DAEMON_DEVNULL_STDIO is superfluous - /* DAEMON_DEVNULL_STDIO is superfluous -
* it's always done by bb_daemonize() */ * it's always done by bb_daemonize() */
#else #else

View File

@ -966,6 +966,7 @@ enum {
DAEMON_DEVNULL_STDIO = 2, DAEMON_DEVNULL_STDIO = 2,
DAEMON_CLOSE_EXTRA_FDS = 4, DAEMON_CLOSE_EXTRA_FDS = 4,
DAEMON_ONLY_SANITIZE = 8, /* internal use */ DAEMON_ONLY_SANITIZE = 8, /* internal use */
DAEMON_DOUBLE_FORK = 16, /* double fork to avoid controlling tty */
}; };
#if BB_MMU #if BB_MMU
enum { re_execed = 0 }; enum { re_execed = 0 };

View File

@ -253,11 +253,19 @@ void FAST_FUNC bb_daemonize_or_rexec(int flags, char **argv)
if (!(flags & DAEMON_ONLY_SANITIZE)) { if (!(flags & DAEMON_ONLY_SANITIZE)) {
if (fork_or_rexec(argv)) if (fork_or_rexec(argv))
exit(EXIT_SUCCESS); /* parent */ exit(EXIT_SUCCESS); /* parent */
/* if daemonizing, make sure we detach from stdio & ctty */ /* if daemonizing, detach from stdio & ctty */
setsid(); setsid();
dup2(fd, 0); dup2(fd, 0);
dup2(fd, 1); dup2(fd, 1);
dup2(fd, 2); dup2(fd, 2);
if (flags & DAEMON_DOUBLE_FORK) {
/* On Linux, session leader can acquire ctty
* unknowingly, by opening a tty.
* Prevent this: stop being a session leader.
*/
if (fork_or_rexec(argv))
exit(EXIT_SUCCESS); /* parent */
}
} }
while (fd > 2) { while (fd > 2) {
close(fd--); close(fd--);