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:
Joyee Cheung 2019-03-12 00:42:31 +08:00
parent 927f29d244
commit 9868d54411
No known key found for this signature in database
GPG Key ID: 92B78A53C8303B8D
5 changed files with 45 additions and 38 deletions

View File

@ -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);
} }

View File

@ -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
}; };

View File

@ -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
}; };

View File

@ -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;

View File

@ -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_;