unix: reset signal disposition before execve()
Signal dispositions are inherited by child processes. Libuv itself does not touch them (if you don't use uv_signal_start(), that is) but the embedder might and probably does in the case of SIGPIPE. Reset the disposition for signals 1-31 to their defaults right before execve'ing into the new process. Fixes: https://github.com/nodejs/node/issues/13662 PR-URL: https://github.com/libuv/libuv/pull/1376 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com> Reviewed-By: Santiago Gimeno <santiago.gimeno@gmail.com> Reviewed-By: Saúl Ibarra Corretgé <saghul@gmail.com>
This commit is contained in:
parent
d0a27baa7d
commit
28eb1d44f5
@ -282,6 +282,7 @@ static void uv__process_child_init(const uv_process_options_t* options,
|
||||
int close_fd;
|
||||
int use_fd;
|
||||
int fd;
|
||||
int n;
|
||||
|
||||
if (options->flags & UV_PROCESS_DETACHED)
|
||||
setsid();
|
||||
@ -376,6 +377,22 @@ static void uv__process_child_init(const uv_process_options_t* options,
|
||||
environ = options->env;
|
||||
}
|
||||
|
||||
/* Reset signal disposition. Use a hard-coded limit because NSIG
|
||||
* is not fixed on Linux: it's either 32, 34 or 64, depending on
|
||||
* whether RT signals are enabled. We are not allowed to touch
|
||||
* RT signal handlers, glibc uses them internally.
|
||||
*/
|
||||
for (n = 1; n < 32; n += 1) {
|
||||
if (n == SIGKILL || n == SIGSTOP)
|
||||
continue; /* Can't be changed. */
|
||||
|
||||
if (SIG_ERR != signal(n, SIG_DFL))
|
||||
continue;
|
||||
|
||||
uv__write_int(error_fd, -errno);
|
||||
_exit(127);
|
||||
}
|
||||
|
||||
execvp(options->file, options->args);
|
||||
uv__write_int(error_fd, -errno);
|
||||
_exit(127);
|
||||
|
||||
@ -929,9 +929,18 @@ TEST_IMPL(kill) {
|
||||
|
||||
init_process_options("spawn_helper4", kill_cb);
|
||||
|
||||
/* Verify that uv_spawn() resets the signal disposition. */
|
||||
#ifndef _WIN32
|
||||
ASSERT(SIG_ERR != signal(SIGTERM, SIG_IGN));
|
||||
#endif
|
||||
|
||||
r = uv_spawn(uv_default_loop(), &process, &options);
|
||||
ASSERT(r == 0);
|
||||
|
||||
#ifndef _WIN32
|
||||
ASSERT(SIG_ERR != signal(SIGTERM, SIG_DFL));
|
||||
#endif
|
||||
|
||||
/* Sending signum == 0 should check if the
|
||||
* child process is still alive, not kill it.
|
||||
*/
|
||||
|
||||
Loading…
Reference in New Issue
Block a user