From 1ad426f2c0d3065f7f0dfa0b4b6f7c5142b0ff84 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Fri, 22 Feb 2019 21:01:22 +0100 Subject: [PATCH 1/4] worker: provide process.execArgv MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Provide `process.execArgv`. If an `execArgv` option is passed to the `Worker` constructor, that option is used as its value; if not, the parent’s `process.execArgv` is inherited (since that also goes for the actual options in that case). --- src/env-inl.h | 4 +++ src/env.cc | 1 + src/env.h | 2 ++ src/node_worker.cc | 16 ++++++--- src/node_worker.h | 4 ++- test/parallel/test-process-exec-argv.js | 48 +++++++++++++++++-------- test/parallel/test-worker-execargv.js | 1 + 7 files changed, 57 insertions(+), 19 deletions(-) diff --git a/src/env-inl.h b/src/env-inl.h index 824b7529a9945d..b233d2fddfe997 100644 --- a/src/env-inl.h +++ b/src/env-inl.h @@ -605,6 +605,10 @@ inline std::shared_ptr Environment::options() { return options_; } +inline const std::vector& Environment::exec_argv() { + return exec_argv_; +} + inline std::shared_ptr Environment::inspector_host_port() { return inspector_host_port_; } diff --git a/src/env.cc b/src/env.cc index 321e2591522562..63ea65380ddf40 100644 --- a/src/env.cc +++ b/src/env.cc @@ -386,6 +386,7 @@ MaybeLocal Environment::ProcessCliArgs( std::move(traced_value)); } + exec_argv_ = exec_args; Local process_object = node::CreateProcessObject(this, args, exec_args) .FromMaybe(Local()); diff --git a/src/env.h b/src/env.h index 92db65525e0bcd..288c404546fe2f 100644 --- a/src/env.h +++ b/src/env.h @@ -676,6 +676,7 @@ class Environment { v8::MaybeLocal ProcessCliArgs( const std::vector& args, const std::vector& exec_args); + inline const std::vector& exec_argv(); typedef void (*HandleCleanupCb)(Environment* env, uv_handle_t* handle, @@ -1060,6 +1061,7 @@ class Environment { // the inspector_host_port_->port() will be the actual port being // used. std::shared_ptr inspector_host_port_; + std::vector exec_argv_; uint32_t module_id_counter_ = 0; uint32_t script_id_counter_ = 0; diff --git a/src/node_worker.cc b/src/node_worker.cc index 0f1535074cca6c..b6a56b9b94b08e 100644 --- a/src/node_worker.cc +++ b/src/node_worker.cc @@ -101,10 +101,12 @@ void AsyncRequest::MemoryInfo(MemoryTracker* tracker) const { Worker::Worker(Environment* env, Local wrap, const std::string& url, - std::shared_ptr per_isolate_opts) + std::shared_ptr per_isolate_opts, + std::vector&& exec_argv) : AsyncWrap(env, wrap, AsyncWrap::PROVIDER_WORKER), url_(url), per_isolate_opts_(per_isolate_opts), + exec_argv_(exec_argv), platform_(env->isolate_data()->platform()), profiler_idle_notifier_started_(env->profiler_idle_notifier_started()), thread_id_(Environment::AllocateThreadId()) { @@ -284,7 +286,7 @@ void Worker::Run() { env_->Start(profiler_idle_notifier_started_); env_->ProcessCliArgs(std::vector{}, - std::vector{}); + std::move(exec_argv_)); } Debug(this, "Created Environment for worker with id %llu", thread_id_); @@ -434,6 +436,9 @@ void Worker::New(const FunctionCallbackInfo& args) { std::string url; std::shared_ptr per_isolate_opts = nullptr; + std::vector exec_argv_out; + bool has_explicit_exec_argv = false; + // Argument might be a string or URL if (args.Length() > 0 && !args[0]->IsNullOrUndefined()) { Utf8Value value( @@ -445,6 +450,7 @@ void Worker::New(const FunctionCallbackInfo& args) { v8::Local array = args[1].As(); // The first argument is reserved for program name, but we don't need it // in workers. + has_explicit_exec_argv = true; std::vector exec_argv = {""}; uint32_t length = array->Length(); for (uint32_t i = 0; i < length; i++) { @@ -472,7 +478,7 @@ void Worker::New(const FunctionCallbackInfo& args) { // options for the per isolate parser. options_parser::PerIsolateOptionsParser::instance.Parse( &exec_argv, - nullptr, + &exec_argv_out, &invalid_args, per_isolate_opts.get(), kDisallowedInEnvironment, @@ -492,7 +498,9 @@ void Worker::New(const FunctionCallbackInfo& args) { } } } - new Worker(env, args.This(), url, per_isolate_opts); + if (!has_explicit_exec_argv) + exec_argv_out = env->exec_argv(); + new Worker(env, args.This(), url, per_isolate_opts, std::move(exec_argv_out)); } void Worker::StartThread(const FunctionCallbackInfo& args) { diff --git a/src/node_worker.h b/src/node_worker.h index fb94bdc307e8b6..442056eaac1078 100644 --- a/src/node_worker.h +++ b/src/node_worker.h @@ -38,7 +38,8 @@ class Worker : public AsyncWrap { Worker(Environment* env, v8::Local wrap, const std::string& url, - std::shared_ptr per_isolate_opts); + std::shared_ptr per_isolate_opts, + std::vector&& exec_argv); ~Worker() override; // Run the worker. This is only called from the worker thread. @@ -74,6 +75,7 @@ class Worker : public AsyncWrap { const std::string url_; std::shared_ptr per_isolate_opts_; + std::vector exec_argv_; MultiIsolatePlatform* platform_; v8::Isolate* isolate_ = nullptr; bool profiler_idle_notifier_started_; diff --git a/test/parallel/test-process-exec-argv.js b/test/parallel/test-process-exec-argv.js index 578ee7b5d1a5e3..6321f151774665 100644 --- a/test/parallel/test-process-exec-argv.js +++ b/test/parallel/test-process-exec-argv.js @@ -20,26 +20,46 @@ // USE OR OTHER DEALINGS IN THE SOFTWARE. 'use strict'; -require('../common'); +const common = require('../common'); const assert = require('assert'); const spawn = require('child_process').spawn; +const { Worker, isMainThread } = require('worker_threads'); -if (process.argv[2] === 'child') { - process.stdout.write(JSON.stringify(process.execArgv)); +if (process.argv[2] === 'child' || !isMainThread) { + if (process.argv[3] === 'cp+worker') + new Worker(__filename); + else + process.stdout.write(JSON.stringify(process.execArgv)); } else { for (const extra of [ [], [ '--' ] ]) { - const execArgv = ['--stack-size=256']; - const args = [__filename, 'child', 'arg0']; - const child = spawn(process.execPath, [...execArgv, ...extra, ...args]); - let out = ''; + for (const kind of [ 'cp', 'worker', 'cp+worker' ]) { + const execArgv = ['--pending-deprecation']; + const args = [__filename, 'child', kind]; + let child; + switch (kind) { + case 'cp': + child = spawn(process.execPath, [...execArgv, ...extra, ...args]); + break; + case 'worker': + child = new Worker(__filename, { + execArgv: [...execArgv, ...extra], + stdout: true + }); + break; + case 'cp+worker': + child = spawn(process.execPath, [...execArgv, ...args]); + break; + } - child.stdout.setEncoding('utf8'); - child.stdout.on('data', function(chunk) { - out += chunk; - }); + let out = ''; + child.stdout.setEncoding('utf8'); + child.stdout.on('data', (chunk) => { + out += chunk; + }); - child.on('close', function() { - assert.deepStrictEqual(JSON.parse(out), execArgv); - }); + child.stdout.on('end', common.mustCall(() => { + assert.deepStrictEqual(JSON.parse(out), execArgv); + })); + } } } diff --git a/test/parallel/test-worker-execargv.js b/test/parallel/test-worker-execargv.js index e04f015e03e2ff..2d3418e4bae7da 100644 --- a/test/parallel/test-worker-execargv.js +++ b/test/parallel/test-worker-execargv.js @@ -19,4 +19,5 @@ if (isMainThread) { })); } else { process.emitWarning('some warning'); + assert.deepStrictEqual(process.execArgv, ['--trace-warnings']); } From 980bf7191e90d8b8bad7cbe2307713a6aba18ce8 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Thu, 28 Feb 2019 22:44:52 +0100 Subject: [PATCH 2/4] fixup! worker: provide process.execArgv --- doc/api/worker_threads.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/api/worker_threads.md b/doc/api/worker_threads.md index 54bd66a6ea683e..2215c4917f9cb3 100644 --- a/doc/api/worker_threads.md +++ b/doc/api/worker_threads.md @@ -428,7 +428,8 @@ if (isMainThread) { not automatically be piped through to `process.stderr` in the parent. * `execArgv` {string[]} List of node CLI options passed to the worker. V8 options (such as `--max-old-space-size`) and options that affect the - process (such as `--title`) are not supported. + process (such as `--title`) are not supported. If set, this will be provided + as [`process.execArgv`][] inside the worker. ### Event: 'error'