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>
This commit is contained in:
parent
da0dc51e39
commit
a80b29b38a
@ -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_);
|
||||
|
@ -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_;
|
||||
|
||||
|
11
test/parallel/test-worker-stack-overflow.js
Normal file
11
test/parallel/test-worker-stack-overflow.js
Normal file
@ -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');
|
||||
}));
|
Loading…
x
Reference in New Issue
Block a user