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: https://github.com/nodejs/node/issues/14927 PR-URL: https://github.com/nodejs/node/pull/27246 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net>
This commit is contained in:
parent
cca375f4af
commit
f2061930c8
@ -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);
|
||||
}
|
||||
|
||||
|
58
src/node.cc
58
src/node.cc
@ -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) {
|
||||
|
15
src/node.h
15
src/node.h
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user