From 11563e179f2670b0918575e3ba7553c9e27b1aac Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Wed, 14 Jun 2017 12:32:40 +0200 Subject: [PATCH] unix: reset signal mask before execve() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Like the previous commit, except now the signal mask is reset instead of the signal disposition. This does open a race window where blocked signals can get delivered in the interval between the pthread_sigmask() call and the execve() call (and may end up terminating the process) but that cannot be helped; the same caveat applies to the previous commit. Fixes: https://github.com/nodejs/node/issues/13662 PR-URL: https://github.com/libuv/libuv/pull/1376 Reviewed-By: Colin Ihrig Reviewed-By: Fedor Indutny Reviewed-By: Santiago Gimeno Reviewed-By: Saúl Ibarra Corretgé --- src/unix/process.c | 11 +++++++++++ test/test-spawn.c | 12 ++++++++++++ 2 files changed, 23 insertions(+) diff --git a/src/unix/process.c b/src/unix/process.c index af44bc5d..80b9686e 100644 --- a/src/unix/process.c +++ b/src/unix/process.c @@ -279,8 +279,10 @@ static void uv__process_child_init(const uv_process_options_t* options, int stdio_count, int (*pipes)[2], int error_fd) { + sigset_t set; int close_fd; int use_fd; + int err; int fd; int n; @@ -393,6 +395,15 @@ static void uv__process_child_init(const uv_process_options_t* options, _exit(127); } + /* Reset signal mask. */ + sigemptyset(&set); + err = pthread_sigmask(SIG_SETMASK, &set, NULL); + + if (err != 0) { + uv__write_int(error_fd, -err); + _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 1ec6bc13..bb35e32b 100644 --- a/test/test-spawn.c +++ b/test/test-spawn.c @@ -931,6 +931,12 @@ TEST_IMPL(kill) { /* Verify that uv_spawn() resets the signal disposition. */ #ifndef _WIN32 + { + sigset_t set; + sigemptyset(&set); + sigaddset(&set, SIGTERM); + ASSERT(0 == pthread_sigmask(SIG_BLOCK, &set, NULL)); + } ASSERT(SIG_ERR != signal(SIGTERM, SIG_IGN)); #endif @@ -938,6 +944,12 @@ TEST_IMPL(kill) { ASSERT(r == 0); #ifndef _WIN32 + { + sigset_t set; + sigemptyset(&set); + sigaddset(&set, SIGTERM); + ASSERT(0 == pthread_sigmask(SIG_UNBLOCK, &set, NULL)); + } ASSERT(SIG_ERR != signal(SIGTERM, SIG_DFL)); #endif