★ wanayoo — archive 1999 https://github.com/nodejs/node/commit/f2061930c8Nouvelle recherche | Portail wanayoo
Skip to content
Permalink
Browse files
src: enable V8's WASM trap handlers
This uses SIGSEGV handlers to catch WASM out of bound (OOB) memory
accesses instead of inserting OOB checks inline, resulting in a 25%-30%
speed increase.

Note that installing a custom SIGSEGV handler will break this, resulting
in potentially scary behaviour.

Refs: #14927

PR-URL: #27246
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
  • Loading branch information
devsnek authored and sam-github committed May 16, 2019
1 parent cca375f commit f2061930c83cb579410a7f26bed726d6568575e3
Showing with 76 additions and 11 deletions.
  1. +1 −1 src/inspector_agent.cc
  2. +55 −3 src/node.cc
  3. +15 −0 src/node.h
  4. +1 −4 src/node_internals.h
  5. +3 −2 src/node_watchdog.cc
  6. +1 −1 src/node_watchdog.h
@@ -88,7 +88,7 @@ void StartIoInterrupt(Isolate* isolate, void* agent) {


#ifdef __POSIX__
static void StartIoThreadWakeup(int signo) {
static void StartIoThreadWakeup(int signo, siginfo_t* info, void* ucontext) {
uv_sem_post(&start_io_thread_semaphore);
}

@@ -70,6 +70,17 @@
#include "node_report.h"
#endif

#if defined(__APPLE__) || defined(__linux__)
#define NODE_USE_V8_WASM_TRAP_HANDLER 1
#else
#define NODE_USE_V8_WASM_TRAP_HANDLER 0
#endif

#if NODE_USE_V8_WASM_TRAP_HANDLER
#include <atomic>
#include "v8-wasm-trap-handler-posix.h"
#endif // NODE_USE_V8_WASM_TRAP_HANDLER

// ========== global C headers ==========

#include <fcntl.h> // _O_RDWR
@@ -177,7 +188,8 @@ void WaitForInspectorDisconnect(Environment* env) {
#endif
}

void SignalExit(int signo) {
#ifdef __POSIX__
void SignalExit(int signo, siginfo_t* info, void* ucontext) {
uv_tty_reset_mode();
#ifdef __FreeBSD__
// FreeBSD has a nasty bug, see RegisterSignalHandler for details
@@ -188,6 +200,7 @@ void SignalExit(int signo) {
#endif
raise(signo);
}
#endif // __POSIX__

MaybeLocal<Value> ExecuteBootstrapper(Environment* env,
const char* id,
@@ -434,14 +447,39 @@ void LoadEnvironment(Environment* env) {
USE(StartMainThreadExecution(env));
}

#if NODE_USE_V8_WASM_TRAP_HANDLER
static std::atomic<void (*)(int signo, siginfo_t* info, void* ucontext)>
previous_sigsegv_action;

void TrapWebAssemblyOrContinue(int signo, siginfo_t* info, void* ucontext) {
if (!v8::TryHandleWebAssemblyTrapPosix(signo, info, ucontext)) {
auto prev = previous_sigsegv_action.load();
if (prev != nullptr) {
prev(signo, info, ucontext);
} else {
uv_tty_reset_mode();
raise(signo);
}
}
}
#endif // NODE_USE_V8_WASM_TRAP_HANDLER

#ifdef __POSIX__
void RegisterSignalHandler(int signal,
void (*handler)(int signal),
void (*handler)(int signal,
siginfo_t* info,
void* ucontext),
bool reset_handler) {
#if NODE_USE_V8_WASM_TRAP_HANDLER
if (signal == SIGSEGV) {
CHECK(previous_sigsegv_action.is_lock_free());
previous_sigsegv_action.store(handler);
return;
}
#endif // NODE_USE_V8_WASM_TRAP_HANDLER
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_handler = handler;
sa.sa_sigaction = handler;
#ifndef __FreeBSD__
// FreeBSD has a nasty bug with SA_RESETHAND reseting the SA_SIGINFO, that is
// in turn set for a libthr wrapper. This leads to a crash.
@@ -499,6 +537,20 @@ inline void PlatformInit() {
RegisterSignalHandler(SIGINT, SignalExit, true);
RegisterSignalHandler(SIGTERM, SignalExit, true);

#if NODE_USE_V8_WASM_TRAP_HANDLER
// Tell V8 to disable emitting WebAssembly
// memory bounds checks. This means that we have
// to catch the SIGSEGV in TrapWebAssemblyOrContinue
// and pass the signal context to V8.
{
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_sigaction = TrapWebAssemblyOrContinue;
CHECK_EQ(sigaction(SIGSEGV, &sa, nullptr), 0);
}
V8::EnableWebAssemblyTrapHandler(false);
#endif // NODE_USE_V8_WASM_TRAP_HANDLER

// Raise the open file descriptor limit.
struct rlimit lim;
if (getrlimit(RLIMIT_NOFILE, &lim) == 0 && lim.rlim_cur != lim.rlim_max) {
@@ -66,6 +66,10 @@

#include <memory>

#ifdef __POSIX__
#include <signal.h>
#endif // __POSIX__

#define NODE_MAKE_VERSION(major, minor, patch) \
((major) * 0x1000 + (minor) * 0x100 + (patch))

@@ -816,6 +820,17 @@ class NODE_EXTERN AsyncResource {
async_context async_context_;
};

#ifdef __POSIX__
// Register a signal handler without interrupting
// any handlers that node itself needs.
NODE_EXTERN
void RegisterSignalHandler(int signal,
void (*handler)(int signal,
siginfo_t* info,
void* ucontext),
bool reset_handler = false);
#endif // __POSIX__

} // namespace node

#endif // SRC_NODE_H_
@@ -91,11 +91,8 @@ void PrintCaughtException(v8::Isolate* isolate,
const v8::TryCatch& try_catch);

void WaitForInspectorDisconnect(Environment* env);
void SignalExit(int signo);
#ifdef __POSIX__
void RegisterSignalHandler(int signal,
void (*handler)(int signal),
bool reset_handler = false);
void SignalExit(int signal, siginfo_t* info, void* ucontext);
#endif

std::string GetHumanReadableProcessName();
@@ -127,8 +127,9 @@ void* SigintWatchdogHelper::RunSigintWatchdog(void* arg) {
return nullptr;
}


void SigintWatchdogHelper::HandleSignal(int signum) {
void SigintWatchdogHelper::HandleSignal(int signum,
siginfo_t* info,
void* ucontext) {
uv_sem_post(&instance.sem_);
}

@@ -99,7 +99,7 @@ class SigintWatchdogHelper {
bool stopping_;

static void* RunSigintWatchdog(void* arg);
static void HandleSignal(int signum);
static void HandleSignal(int signum, siginfo_t* info, void* ucontext);
#else
bool watchdog_disabled_;
static BOOL WINAPI WinCtrlCHandlerRoutine(DWORD dwCtrlType);

0 comments on commit f206193

Please sign in to comment.