summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGus Caplan <me@gus.host>2019-04-15 16:09:51 -0500
committerSam Roberts <vieuxtech@gmail.com>2019-05-16 10:52:53 -0700
commitf2061930c83cb579410a7f26bed726d6568575e3 (patch)
treeddcfcc116344fd03d5d04721df49eacb0059dd13 /src
parentcca375f4af235ed7e7f763b2e35532ae843a5854 (diff)
downloadandroid-node-v8-f2061930c83cb579410a7f26bed726d6568575e3.tar.gz
android-node-v8-f2061930c83cb579410a7f26bed726d6568575e3.tar.bz2
android-node-v8-f2061930c83cb579410a7f26bed726d6568575e3.zip
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>
Diffstat (limited to 'src')
-rw-r--r--src/inspector_agent.cc2
-rw-r--r--src/node.cc58
-rw-r--r--src/node.h15
-rw-r--r--src/node_internals.h5
-rw-r--r--src/node_watchdog.cc5
-rw-r--r--src/node_watchdog.h2
6 files changed, 76 insertions, 11 deletions
diff --git a/src/inspector_agent.cc b/src/inspector_agent.cc
index d8b5d01a28..d551c3a7d7 100644
--- a/src/inspector_agent.cc
+++ b/src/inspector_agent.cc
@@ -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);
}
diff --git a/src/node.cc b/src/node.cc
index 953465e04a..7dccd7ce57 100644
--- a/src/node.cc
+++ b/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) {
diff --git a/src/node.h b/src/node.h
index 5af0655a84..73a3998285 100644
--- a/src/node.h
+++ b/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_
diff --git a/src/node_internals.h b/src/node_internals.h
index 91cc0efd50..cb039f297b 100644
--- a/src/node_internals.h
+++ b/src/node_internals.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();
diff --git a/src/node_watchdog.cc b/src/node_watchdog.cc
index 7c62aafa82..28df2fb449 100644
--- a/src/node_watchdog.cc
+++ b/src/node_watchdog.cc
@@ -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_);
}
diff --git a/src/node_watchdog.h b/src/node_watchdog.h
index 9c56b90e9e..36c2df1109 100644
--- a/src/node_watchdog.h
+++ b/src/node_watchdog.h
@@ -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);