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>
This commit is contained in:
parent
b67d900395
commit
088fec36fe
@ -409,7 +409,7 @@ int start_stop_daemon_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
{
|
{
|
||||||
unsigned opt;
|
unsigned opt;
|
||||||
char *signame;
|
char *signame;
|
||||||
char *startas;
|
char *startas = NULL;
|
||||||
char *chuid;
|
char *chuid;
|
||||||
#if ENABLE_FEATURE_START_STOP_DAEMON_FANCY
|
#if ENABLE_FEATURE_START_STOP_DAEMON_FANCY
|
||||||
// char *retry_arg = NULL;
|
// char *retry_arg = NULL;
|
||||||
@ -425,10 +425,11 @@ int start_stop_daemon_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
/* -K or -S is required; they are mutually exclusive */
|
/* -K or -S is required; they are mutually exclusive */
|
||||||
/* -p is required if -m is given */
|
/* -p is required if -m is given */
|
||||||
/* -xpun (at least one) is required if -K is given */
|
/* -xpun (at least one) is required if -K is given */
|
||||||
/* -xa (at least one) is required if -S is given */
|
// /* -xa (at least one) is required if -S is given */
|
||||||
|
//WRONG: "start-stop-daemon -S -- sleep 5" is a valid invocation
|
||||||
/* -q turns off -v */
|
/* -q turns off -v */
|
||||||
"\0"
|
"\0"
|
||||||
"K:S:K--S:S--K:m?p:K?xpun:S?xa"
|
"K:S:K--S:S--K:m?p:K?xpun"
|
||||||
IF_FEATURE_START_STOP_DAEMON_FANCY("q-v"),
|
IF_FEATURE_START_STOP_DAEMON_FANCY("q-v"),
|
||||||
LONGOPTS
|
LONGOPTS
|
||||||
&startas, &cmdname, &signame, &userspec, &chuid, &execname, &pidfile
|
&startas, &cmdname, &signame, &userspec, &chuid, &execname, &pidfile
|
||||||
@ -442,21 +443,34 @@ int start_stop_daemon_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
if (signal_nr < 0) bb_show_usage();
|
if (signal_nr < 0) bb_show_usage();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(opt & OPT_a))
|
//argc -= optind;
|
||||||
startas = execname;
|
argv += optind;
|
||||||
if (!execname) /* in case -a is given and -x is not */
|
// ARGS contains zeroth arg if -x/-a is not given, else it starts with 1st arg.
|
||||||
|
// These will try to execute "[/bin/]sleep 5":
|
||||||
|
// "start-stop-daemon -S -- sleep 5"
|
||||||
|
// "start-stop-daemon -S -x /bin/sleep -- 5"
|
||||||
|
// "start-stop-daemon -S -a sleep -- 5"
|
||||||
|
// NB: -n option does _not_ behave in this way: this will try to execute "5":
|
||||||
|
// "start-stop-daemon -S -n sleep -- 5"
|
||||||
|
if (!execname) { /* -x is not given */
|
||||||
execname = startas;
|
execname = startas;
|
||||||
if (execname) {
|
if (!execname) { /* neither -x nor -a is given */
|
||||||
G.execname_sizeof = strlen(execname) + 1;
|
execname = argv[0];
|
||||||
G.execname_cmpbuf = xmalloc(G.execname_sizeof + 1);
|
if (!execname)
|
||||||
|
bb_show_usage();
|
||||||
|
argv++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if (!startas) /* -a is not given: use -x EXECUTABLE or argv[0] */
|
||||||
|
startas = execname;
|
||||||
|
*--argv = startas;
|
||||||
|
G.execname_sizeof = strlen(execname) + 1;
|
||||||
|
G.execname_cmpbuf = xmalloc(G.execname_sizeof + 1);
|
||||||
|
|
||||||
// IF_FEATURE_START_STOP_DAEMON_FANCY(
|
// IF_FEATURE_START_STOP_DAEMON_FANCY(
|
||||||
// if (retry_arg)
|
// if (retry_arg)
|
||||||
// retries = xatoi_positive(retry_arg);
|
// retries = xatoi_positive(retry_arg);
|
||||||
// )
|
// )
|
||||||
//argc -= optind;
|
|
||||||
argv += optind;
|
|
||||||
|
|
||||||
if (userspec) {
|
if (userspec) {
|
||||||
user_id = bb_strtou(userspec, NULL, 10);
|
user_id = bb_strtou(userspec, NULL, 10);
|
||||||
@ -473,7 +487,7 @@ int start_stop_daemon_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
|
|
||||||
if (G.found_procs) {
|
if (G.found_procs) {
|
||||||
if (!QUIET)
|
if (!QUIET)
|
||||||
printf("%s is already running\n%u\n", execname, (unsigned)G.found_procs->pid);
|
printf("%s is already running\n", execname);
|
||||||
return !(opt & OPT_OKNODO);
|
return !(opt & OPT_OKNODO);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -482,30 +496,37 @@ int start_stop_daemon_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
xstat(execname, &G.execstat);
|
xstat(execname, &G.execstat);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
*--argv = startas;
|
|
||||||
if (opt & OPT_BACKGROUND) {
|
if (opt & OPT_BACKGROUND) {
|
||||||
#if BB_MMU
|
|
||||||
bb_daemonize(DAEMON_DEVNULL_STDIO + DAEMON_CLOSE_EXTRA_FDS + DAEMON_DOUBLE_FORK);
|
|
||||||
/* DAEMON_DEVNULL_STDIO is superfluous -
|
|
||||||
* it's always done by bb_daemonize() */
|
|
||||||
#else
|
|
||||||
/* Daemons usually call bb_daemonize_or_rexec(), but SSD can do
|
/* Daemons usually call bb_daemonize_or_rexec(), but SSD can do
|
||||||
* without: SSD is not itself a daemon, it _execs_ a daemon.
|
* without: SSD is not itself a daemon, it _execs_ a daemon.
|
||||||
* The usual NOMMU problem of "child can't run indefinitely,
|
* The usual NOMMU problem of "child can't run indefinitely,
|
||||||
* it must exec" does not bite us: we exec anyway.
|
* it must exec" does not bite us: we exec anyway.
|
||||||
|
*
|
||||||
|
* bb_daemonize(DAEMON_DEVNULL_STDIO | DAEMON_CLOSE_EXTRA_FDS | DAEMON_DOUBLE_FORK)
|
||||||
|
* can be used on MMU systems, but use of vfork()
|
||||||
|
* is preferable since we want to create pidfile
|
||||||
|
* _before_ parent returns, and vfork() on Linux
|
||||||
|
* ensures that (by blocking parent until exec in the child).
|
||||||
*/
|
*/
|
||||||
pid_t pid = xvfork();
|
pid_t pid = xvfork();
|
||||||
if (pid != 0) {
|
if (pid != 0) {
|
||||||
/* parent */
|
/* Parent */
|
||||||
/* why _exit? the child may have changed the stack,
|
/* why _exit? the child may have changed the stack,
|
||||||
* so "return 0" may do bad things */
|
* so "return 0" may do bad things
|
||||||
|
*/
|
||||||
_exit(EXIT_SUCCESS);
|
_exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
/* Child */
|
/* Child */
|
||||||
setsid(); /* detach from controlling tty */
|
setsid(); /* detach from controlling tty */
|
||||||
/* Redirect stdio to /dev/null, close extra FDs */
|
/* Redirect stdio to /dev/null, close extra FDs */
|
||||||
bb_daemon_helper(DAEMON_DEVNULL_STDIO + DAEMON_CLOSE_EXTRA_FDS);
|
bb_daemon_helper(DAEMON_DEVNULL_STDIO + DAEMON_CLOSE_EXTRA_FDS);
|
||||||
#endif
|
/* On Linux, session leader can acquire ctty
|
||||||
|
* unknowingly, by opening a tty.
|
||||||
|
* Prevent this: stop being a session leader.
|
||||||
|
*/
|
||||||
|
pid = xvfork();
|
||||||
|
if (pid != 0)
|
||||||
|
_exit(EXIT_SUCCESS); /* Parent */
|
||||||
}
|
}
|
||||||
if (opt & OPT_MAKEPID) {
|
if (opt & OPT_MAKEPID) {
|
||||||
/* User wants _us_ to make the pidfile */
|
/* User wants _us_ to make the pidfile */
|
||||||
@ -534,6 +555,7 @@ int start_stop_daemon_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
execvp(startas, argv);
|
//bb_error_msg("HERE %d '%s'%s'", __LINE__, argv[0], argv[1]);
|
||||||
|
execvp(argv[0], argv);
|
||||||
bb_perror_msg_and_die("can't execute '%s'", startas);
|
bb_perror_msg_and_die("can't execute '%s'", startas);
|
||||||
}
|
}
|
||||||
|
@ -1201,11 +1201,11 @@ void set_task_comm(const char *comm) FAST_FUNC;
|
|||||||
* to /dev/null if they are not.
|
* to /dev/null if they are not.
|
||||||
*/
|
*/
|
||||||
enum {
|
enum {
|
||||||
DAEMON_CHDIR_ROOT = 1,
|
DAEMON_CHDIR_ROOT = 1 << 0,
|
||||||
DAEMON_DEVNULL_STDIO = 2,
|
DAEMON_DEVNULL_STDIO = 1 << 1,
|
||||||
DAEMON_CLOSE_EXTRA_FDS = 4,
|
DAEMON_CLOSE_EXTRA_FDS = 1 << 2,
|
||||||
DAEMON_ONLY_SANITIZE = 8, /* internal use */
|
DAEMON_ONLY_SANITIZE = 1 << 3, /* internal use */
|
||||||
DAEMON_DOUBLE_FORK = 16, /* double fork to avoid controlling tty */
|
//DAEMON_DOUBLE_FORK = 1 << 4, /* double fork to avoid controlling tty */
|
||||||
};
|
};
|
||||||
#if BB_MMU
|
#if BB_MMU
|
||||||
enum { re_execed = 0 };
|
enum { re_execed = 0 };
|
||||||
|
@ -292,14 +292,14 @@ void FAST_FUNC bb_daemonize_or_rexec(int flags, char **argv)
|
|||||||
dup2(fd, 0);
|
dup2(fd, 0);
|
||||||
dup2(fd, 1);
|
dup2(fd, 1);
|
||||||
dup2(fd, 2);
|
dup2(fd, 2);
|
||||||
if (flags & DAEMON_DOUBLE_FORK) {
|
// if (flags & DAEMON_DOUBLE_FORK) {
|
||||||
/* On Linux, session leader can acquire ctty
|
// /* On Linux, session leader can acquire ctty
|
||||||
* unknowingly, by opening a tty.
|
// * unknowingly, by opening a tty.
|
||||||
* Prevent this: stop being a session leader.
|
// * Prevent this: stop being a session leader.
|
||||||
*/
|
// */
|
||||||
if (fork_or_rexec(argv))
|
// if (fork_or_rexec(argv))
|
||||||
_exit(EXIT_SUCCESS); /* parent */
|
// _exit(EXIT_SUCCESS); /* parent */
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
while (fd > 2) {
|
while (fd > 2) {
|
||||||
close(fd--);
|
close(fd--);
|
||||||
|
@ -16,4 +16,9 @@ testing "start-stop-daemon -a without -x" \
|
|||||||
"1\n" \
|
"1\n" \
|
||||||
"" ""
|
"" ""
|
||||||
|
|
||||||
|
testing "start-stop-daemon without -x and -a" \
|
||||||
|
'start-stop-daemon -S false 2>&1; echo $?' \
|
||||||
|
"1\n" \
|
||||||
|
"" ""
|
||||||
|
|
||||||
exit $FAILCOUNT
|
exit $FAILCOUNT
|
||||||
|
Loading…
Reference in New Issue
Block a user