summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnna Henningsen <anna@addaleax.net>2019-02-05 21:51:28 +0100
committerAnna Henningsen <anna@addaleax.net>2019-02-13 21:36:24 +0100
commita80b29b38a66cec456e4ec73fb8030f45d186005 (patch)
treead44198e7620505db311cdc99f689b6d7f7a058b
parentda0dc51e396ea4a1f12f259a8149f4177ad674e8 (diff)
downloadandroid-node-v8-a80b29b38a66cec456e4ec73fb8030f45d186005.tar.gz
android-node-v8-a80b29b38a66cec456e4ec73fb8030f45d186005.tar.bz2
android-node-v8-a80b29b38a66cec456e4ec73fb8030f45d186005.zip
worker: set stack size for worker threads
This is so we can inform V8 about a known limit for the stack. Otherwise, on some systems recursive functions may lead to segmentation faults rather than “safe” failures. PR-URL: https://github.com/nodejs/node/pull/26049 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
-rw-r--r--src/node_worker.cc13
-rw-r--r--src/node_worker.h6
-rw-r--r--test/parallel/test-worker-stack-overflow.js11
3 files changed, 29 insertions, 1 deletions
diff --git a/src/node_worker.cc b/src/node_worker.cc
index ebd1924b8f..f38b187c18 100644
--- a/src/node_worker.cc
+++ b/src/node_worker.cc
@@ -118,6 +118,8 @@ class WorkerThreadData {
{
Locker locker(isolate);
Isolate::Scope isolate_scope(isolate);
+ isolate->SetStackLimit(w_->stack_base_);
+
HandleScope handle_scope(isolate);
isolate_data_.reset(CreateIsolateData(isolate,
&loop_,
@@ -488,8 +490,17 @@ void Worker::StartThread(const FunctionCallbackInfo<Value>& args) {
static_cast<Worker*>(handle->data)->OnThreadStopped();
}), 0);
- CHECK_EQ(uv_thread_create(&w->tid_, [](void* arg) {
+ uv_thread_options_t thread_options;
+ thread_options.flags = UV_THREAD_HAS_STACK_SIZE;
+ thread_options.stack_size = kStackSize;
+ CHECK_EQ(uv_thread_create_ex(&w->tid_, &thread_options, [](void* arg) {
Worker* w = static_cast<Worker*>(arg);
+ const uintptr_t stack_top = reinterpret_cast<uintptr_t>(&arg);
+
+ // Leave a few kilobytes just to make sure we're within limits and have
+ // some space to do work in C++ land.
+ w->stack_base_ = stack_top - (kStackSize - kStackBufferSize);
+
w->Run();
Mutex::ScopedLock lock(w->mutex_);
diff --git a/src/node_worker.h b/src/node_worker.h
index 4d7a7335ca..68848c8599 100644
--- a/src/node_worker.h
+++ b/src/node_worker.h
@@ -80,6 +80,12 @@ class Worker : public AsyncWrap {
bool thread_joined_ = true;
int exit_code_ = 0;
uint64_t thread_id_ = -1;
+ uintptr_t stack_base_;
+
+ // Full size of the thread's stack.
+ static constexpr size_t kStackSize = 4 * 1024 * 1024;
+ // Stack buffer size that is not available to the JS engine.
+ static constexpr size_t kStackBufferSize = 192 * 1024;
std::unique_ptr<MessagePortData> child_port_data_;
diff --git a/test/parallel/test-worker-stack-overflow.js b/test/parallel/test-worker-stack-overflow.js
new file mode 100644
index 0000000000..99a34b5369
--- /dev/null
+++ b/test/parallel/test-worker-stack-overflow.js
@@ -0,0 +1,11 @@
+'use strict';
+const common = require('../common');
+const assert = require('assert');
+const { Worker } = require('worker_threads');
+
+const worker = new Worker('function f() { f(); } f();', { eval: true });
+
+worker.on('error', common.mustCall((err) => {
+ assert.strictEqual(err.constructor, RangeError);
+ assert.strictEqual(err.message, 'Maximum call stack size exceeded');
+}));