diff --git a/src/unix/process.c b/src/unix/process.c index f2fe3052..af44bc5d 100644 --- a/src/unix/process.c +++ b/src/unix/process.c @@ -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); diff --git a/test/test-spawn.c b/test/test-spawn.c index 52fc7f6c..1ec6bc13 100644 --- a/test/test-spawn.c +++ b/test/test-spawn.c @@ -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. */