Skip to content
This repository has been archived by the owner on May 4, 2018. It is now read-only.

Implement uv_sanitize_signal_handling(). #1440

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions include/uv.h
Original file line number Diff line number Diff line change
Expand Up @@ -2251,6 +2251,30 @@ UV_EXTERN extern uint64_t uv_hrtime(void);
*/
UV_EXTERN void uv_disable_stdio_inheritance(void);

/*
* On Unix, this function can be called early from main, before any threads
* are started, to set up a safe environment with respect to signal handling.
*
* This function does the following when it is called for the first time:
* - Starts a dummy thread, which consists of an infinite pause() loop.
* - Blocks all signals in the current thread.
*
* Remember that signal masks are thread-specific and inherited at thread
* creation. Therefore the dummy thread will have the same signals unblocked
* as the main thread did when this function was called.
*
* This will ensure that signals directed at the process will only be processed
* by this dummy thread. Most imporantly, system calls will not randomly fail
* with EINTR errors (unless signals are later unmasked by threads...).
*
* Calling this function is not necessary for libuv itself to operate
* correctly, since EINTR is handled by retrying calls. But code outside
* of libuv may not be handling EINTR.
*
* This function does nothing on Windows.
*/
UV_EXTERN void uv_sanitize_signal_handling(void);

/*
* Opens a shared library. The filename is in utf-8. Returns 0 on success and
* -1 on error. Call uv_dlerror(uv_lib_t*) to get the error message.
Expand Down
35 changes: 35 additions & 0 deletions src/unix/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@
#endif

static void uv__run_pending(uv_loop_t* loop);
static void uv__signal_thread_proc(void *arg);

static int uv__sanitize_signals_done;
static uv_thread_t uv__signal_thread;

/* Verify that uv_buf_t is ABI-compatible with struct iovec. */
STATIC_ASSERT(sizeof(uv_buf_t) == sizeof(struct iovec));
Expand Down Expand Up @@ -662,6 +666,29 @@ void uv_disable_stdio_inheritance(void) {
}


void uv_sanitize_signal_handling(void) {
sigset_t full_ss;
sigset_t old_ss;

/* Don't do it twice.
* This looks like a race condition but then it should only be
* called from main. */
if (uv__sanitize_signals_done) {
return;
}
uv__sanitize_signals_done = 1;

// Create dummy signal handling thread.
if (uv_thread_create(&uv__signal_thread, uv__signal_thread_proc, NULL))
abort();

/* Block all signals in the current (main) thread. */
sigfillset(&full_ss);
if (pthread_sigmask(SIG_SETMASK, &full_ss, &old_ss))
abort();
}


static void uv__run_pending(uv_loop_t* loop) {
QUEUE* q;
uv__io_t* w;
Expand Down Expand Up @@ -946,3 +973,11 @@ int uv__dup2_cloexec(int oldfd, int newfd) {
return r;
}
}


static void uv__signal_thread_proc(void* arg) {
/* Handle signals by doing nothing. */
while (1) {
pause();
}
}
3 changes: 3 additions & 0 deletions src/win/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -456,3 +456,6 @@ int uv__socket_sockopt(uv_handle_t* handle, int optname, int* value) {

return 0;
}

void uv_sanitize_signal_handling(void) {
}