worker: create per-Environment message port after bootstrap
PR-URL: https://github.com/nodejs/node/pull/26593 Reviewed-By: Gus Caplan <me@gus.host> Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
parent
927f29d244
commit
9868d54411
@ -146,7 +146,7 @@ if (isMainThread) {
|
|||||||
setupProcessStdio(getStdout, getStdin, getStderr);
|
setupProcessStdio(getStdout, getStdin, getStderr);
|
||||||
} else {
|
} else {
|
||||||
const { getStdout, getStdin, getStderr } =
|
const { getStdout, getStdin, getStderr } =
|
||||||
workerThreadSetup.initializeWorkerStdio();
|
workerThreadSetup.createStdioGetters();
|
||||||
setupProcessStdio(getStdout, getStdin, getStderr);
|
setupProcessStdio(getStdout, getStdin, getStderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,32 +2,25 @@
|
|||||||
|
|
||||||
// This file contains process bootstrappers that can only be
|
// This file contains process bootstrappers that can only be
|
||||||
// run in the worker thread.
|
// run in the worker thread.
|
||||||
const {
|
|
||||||
getEnvMessagePort
|
|
||||||
} = internalBinding('worker');
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
kWaitingStreams,
|
createWorkerStdio
|
||||||
ReadableWorkerStdio,
|
|
||||||
WritableWorkerStdio
|
|
||||||
} = require('internal/worker/io');
|
} = require('internal/worker/io');
|
||||||
|
|
||||||
const {
|
const {
|
||||||
codes: { ERR_WORKER_UNSUPPORTED_OPERATION }
|
codes: { ERR_WORKER_UNSUPPORTED_OPERATION }
|
||||||
} = require('internal/errors');
|
} = require('internal/errors');
|
||||||
const workerStdio = {};
|
|
||||||
|
|
||||||
function initializeWorkerStdio() {
|
|
||||||
const port = getEnvMessagePort();
|
|
||||||
port[kWaitingStreams] = 0;
|
|
||||||
workerStdio.stdin = new ReadableWorkerStdio(port, 'stdin');
|
|
||||||
workerStdio.stdout = new WritableWorkerStdio(port, 'stdout');
|
|
||||||
workerStdio.stderr = new WritableWorkerStdio(port, 'stderr');
|
|
||||||
|
|
||||||
|
let workerStdio;
|
||||||
|
function lazyWorkerStdio() {
|
||||||
|
if (!workerStdio) workerStdio = createWorkerStdio();
|
||||||
|
return workerStdio;
|
||||||
|
}
|
||||||
|
function createStdioGetters() {
|
||||||
return {
|
return {
|
||||||
getStdout() { return workerStdio.stdout; },
|
getStdout() { return lazyWorkerStdio().stdout; },
|
||||||
getStderr() { return workerStdio.stderr; },
|
getStderr() { return lazyWorkerStdio().stderr; },
|
||||||
getStdin() { return workerStdio.stdin; }
|
getStdin() { return lazyWorkerStdio().stdin; }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,7 +48,7 @@ function unavailable(name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
initializeWorkerStdio,
|
createStdioGetters,
|
||||||
unavailable,
|
unavailable,
|
||||||
wrapProcessMethods
|
wrapProcessMethods
|
||||||
};
|
};
|
||||||
|
@ -11,7 +11,10 @@ const {
|
|||||||
moveMessagePortToContext,
|
moveMessagePortToContext,
|
||||||
stopMessagePort
|
stopMessagePort
|
||||||
} = internalBinding('messaging');
|
} = internalBinding('messaging');
|
||||||
const { threadId } = internalBinding('worker');
|
const {
|
||||||
|
threadId,
|
||||||
|
getEnvMessagePort
|
||||||
|
} = internalBinding('worker');
|
||||||
|
|
||||||
const { Readable, Writable } = require('stream');
|
const { Readable, Writable } = require('stream');
|
||||||
const EventEmitter = require('events');
|
const EventEmitter = require('events');
|
||||||
@ -227,6 +230,16 @@ class WritableWorkerStdio extends Writable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createWorkerStdio() {
|
||||||
|
const port = getEnvMessagePort();
|
||||||
|
port[kWaitingStreams] = 0;
|
||||||
|
return {
|
||||||
|
stdin: new ReadableWorkerStdio(port, 'stdin'),
|
||||||
|
stdout: new WritableWorkerStdio(port, 'stdout'),
|
||||||
|
stderr: new WritableWorkerStdio(port, 'stderr')
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
drainMessagePort,
|
drainMessagePort,
|
||||||
messageTypes,
|
messageTypes,
|
||||||
@ -239,5 +252,6 @@ module.exports = {
|
|||||||
MessageChannel,
|
MessageChannel,
|
||||||
setupPortReferencing,
|
setupPortReferencing,
|
||||||
ReadableWorkerStdio,
|
ReadableWorkerStdio,
|
||||||
WritableWorkerStdio
|
WritableWorkerStdio,
|
||||||
|
createWorkerStdio
|
||||||
};
|
};
|
||||||
|
@ -269,22 +269,6 @@ void Worker::Run() {
|
|||||||
Debug(this, "Created Environment for worker with id %llu", thread_id_);
|
Debug(this, "Created Environment for worker with id %llu", thread_id_);
|
||||||
if (is_stopped()) return;
|
if (is_stopped()) return;
|
||||||
{
|
{
|
||||||
HandleScope handle_scope(isolate_);
|
|
||||||
Mutex::ScopedLock lock(mutex_);
|
|
||||||
// Set up the message channel for receiving messages in the child.
|
|
||||||
child_port_ = MessagePort::New(env_.get(),
|
|
||||||
env_->context(),
|
|
||||||
std::move(child_port_data_));
|
|
||||||
// MessagePort::New() may return nullptr if execution is terminated
|
|
||||||
// within it.
|
|
||||||
if (child_port_ != nullptr)
|
|
||||||
env_->set_message_port(child_port_->object(isolate_));
|
|
||||||
|
|
||||||
Debug(this, "Created message port for worker %llu", thread_id_);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_stopped()) return;
|
|
||||||
{
|
|
||||||
#if NODE_USE_V8_PLATFORM && HAVE_INSPECTOR
|
#if NODE_USE_V8_PLATFORM && HAVE_INSPECTOR
|
||||||
StartWorkerInspector(env_.get(),
|
StartWorkerInspector(env_.get(),
|
||||||
std::move(inspector_parent_handle_),
|
std::move(inspector_parent_handle_),
|
||||||
@ -296,6 +280,9 @@ void Worker::Run() {
|
|||||||
Environment::AsyncCallbackScope callback_scope(env_.get());
|
Environment::AsyncCallbackScope callback_scope(env_.get());
|
||||||
env_->async_hooks()->push_async_ids(1, 0);
|
env_->async_hooks()->push_async_ids(1, 0);
|
||||||
if (!RunBootstrapping(env_.get()).IsEmpty()) {
|
if (!RunBootstrapping(env_.get()).IsEmpty()) {
|
||||||
|
CreateEnvMessagePort(env_.get());
|
||||||
|
if (is_stopped()) return;
|
||||||
|
Debug(this, "Created message port for worker %llu", thread_id_);
|
||||||
USE(StartExecution(env_.get(), "internal/main/worker_thread"));
|
USE(StartExecution(env_.get(), "internal/main/worker_thread"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -348,6 +335,19 @@ void Worker::Run() {
|
|||||||
Debug(this, "Worker %llu thread stops", thread_id_);
|
Debug(this, "Worker %llu thread stops", thread_id_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Worker::CreateEnvMessagePort(Environment* env) {
|
||||||
|
HandleScope handle_scope(isolate_);
|
||||||
|
Mutex::ScopedLock lock(mutex_);
|
||||||
|
// Set up the message channel for receiving messages in the child.
|
||||||
|
child_port_ = MessagePort::New(env,
|
||||||
|
env->context(),
|
||||||
|
std::move(child_port_data_));
|
||||||
|
// MessagePort::New() may return nullptr if execution is terminated
|
||||||
|
// within it.
|
||||||
|
if (child_port_ != nullptr)
|
||||||
|
env->set_message_port(child_port_->object(isolate_));
|
||||||
|
}
|
||||||
|
|
||||||
void Worker::JoinThread() {
|
void Worker::JoinThread() {
|
||||||
if (thread_joined_)
|
if (thread_joined_)
|
||||||
return;
|
return;
|
||||||
|
@ -50,7 +50,7 @@ class Worker : public AsyncWrap {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void OnThreadStopped();
|
void OnThreadStopped();
|
||||||
|
void CreateEnvMessagePort(Environment* env);
|
||||||
const std::string url_;
|
const std::string url_;
|
||||||
|
|
||||||
std::shared_ptr<PerIsolateOptions> per_isolate_opts_;
|
std::shared_ptr<PerIsolateOptions> per_isolate_opts_;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user