blob: 91f2cb35204b5336580407f1367fa07342cabfec [file] [log] [blame]
James M Snell98e54b02017-01-03 21:16:481// Copyright Joyent, Inc. and other Node contributors.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a
4// copy of this software and associated documentation files (the
5// "Software"), to deal in the Software without restriction, including
6// without limitation the rights to use, copy, modify, merge, publish,
7// distribute, sublicense, and/or sell copies of the Software, and to permit
8// persons to whom the Software is furnished to do so, subject to the
9// following conditions:
10//
11// The above copyright notice and this permission notice shall be included
12// in all copies or substantial portions of the Software.
13//
14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20// USE OR OTHER DEALINGS IN THE SOFTWARE.
21
Refael Ackermannf2064df2019-02-25 22:27:1922#include "node.h"
23
24// ========== local headers ==========
25
Anna Henningsen9cc747b2020-01-21 17:30:2026#include "debug_utils-inl.h"
Sam Robertsb6bfc192019-05-09 19:52:3827#include "env-inl.h"
Sam Roberts2ecef9b2019-05-17 20:11:0228#include "memory_tracker-inl.h"
Joyee Cheung3d668262018-11-28 16:46:4529#include "node_binding.h"
Gus Caplan43fb6ff2020-01-11 22:03:5930#include "node_errors.h"
Joyee Cheung58502202018-11-03 14:45:4031#include "node_internals.h"
Joyee Cheungcab1dc52019-04-14 06:41:0432#include "node_main_instance.h"
Joyee Cheungd17d7bd2018-12-01 20:16:0933#include "node_metadata.h"
Joyee Cheungdfd7e992019-04-09 21:08:4834#include "node_native_module_env.h"
Joyee Cheung61a89632018-12-01 17:30:3035#include "node_options-inl.h"
Joyee Cheungbd765d62018-11-03 06:26:3236#include "node_perf.h"
Joyee Cheung78242802018-12-31 15:18:0837#include "node_process.h"
cjihriga6bd2c22020-03-13 01:32:0738#include "node_report.h"
James M Snelld3875912016-02-04 01:16:1039#include "node_revert.h"
Joyee Cheung99c32432019-01-16 18:34:4340#include "node_v8_platform-inl.h"
Joyee Cheung58502202018-11-03 14:45:4041#include "node_version.h"
Ben Noordhuis02cab972013-07-31 21:16:0842
Ben Noordhuis02cab972013-07-31 21:16:0843#if HAVE_OPENSSL
44#include "node_crypto.h"
45#endif
46
Steven R. Loomisac2857b2014-09-05 05:03:2447#if defined(NODE_HAVE_I18N_SUPPORT)
48#include "node_i18n.h"
49#endif
50
Ben Noordhuis399cb252017-05-27 11:31:0051#if HAVE_INSPECTOR
Joyee Cheunga0d86be2019-05-20 11:39:2152#include "inspector_agent.h"
Ben Noordhuis399cb252017-05-27 11:31:0053#include "inspector_io.h"
54#endif
55
Ben Noordhuisc4def502013-10-28 19:18:5956#if defined HAVE_DTRACE || defined HAVE_ETW
Ben Noordhuis02cab972013-07-31 21:16:0857#include "node_dtrace.h"
58#endif
59
Stefan Budeanu410296c2016-03-27 00:17:5560#if NODE_USE_V8_PLATFORM
Ben Noordhuis4a801c22015-04-02 21:51:0161#include "libplatform/libplatform.h"
Stefan Budeanu410296c2016-03-27 00:17:5562#endif // NODE_USE_V8_PLATFORM
Ben Noordhuis57231d52013-10-02 04:37:4463#include "v8-profiler.h"
Ryan Dahl4635ed72010-03-11 20:40:1964
Joyee Cheunga0d86be2019-05-20 11:39:2165#if HAVE_INSPECTOR
66#include "inspector/worker_inspector.h" // ParentInspectorHandle
67#endif
68
Suresh Srinivasbf7ed802018-03-23 19:16:4869#include "large_pages/node_large_page.h"
Suresh Srinivasbf7ed802018-03-23 19:16:4870
Gus Caplanf2061932019-04-15 21:09:5171#if defined(__APPLE__) || defined(__linux__)
72#define NODE_USE_V8_WASM_TRAP_HANDLER 1
73#else
74#define NODE_USE_V8_WASM_TRAP_HANDLER 0
75#endif
76
77#if NODE_USE_V8_WASM_TRAP_HANDLER
78#include <atomic>
79#include "v8-wasm-trap-handler-posix.h"
80#endif // NODE_USE_V8_WASM_TRAP_HANDLER
81
Refael Ackermannf2064df2019-02-25 22:27:1982// ========== global C headers ==========
83
84#include <fcntl.h> // _O_RDWR
85#include <sys/types.h>
Ben Noordhuis02cab972013-07-31 21:16:0886
Evan Lucas30b8bb02015-09-27 15:59:0287#if defined(NODE_HAVE_I18N_SUPPORT)
88#include <unicode/uvernum.h>
Stephen Gallagherd502b832019-12-06 21:40:2589#include <unicode/utypes.h>
Evan Lucas30b8bb02015-09-27 15:59:0290#endif
91
Gireesh Punathil4f679732018-09-05 14:06:5992
Karl Skomski6ed06032015-08-14 08:07:1893#if defined(LEAK_SANITIZER)
94#include <sanitizer/lsan_interface.h>
95#endif
96
Ben Noordhuis02cab972013-07-31 21:16:0897#if defined(_MSC_VER)
Peter Bright13d6a1f2011-08-06 04:23:2598#include <direct.h>
Peter Brightb9d77772011-08-11 01:45:5699#include <io.h>
Joyee Cheung6967f912019-01-15 15:12:21100#define STDIN_FILENO 0
Ben Noordhuis02cab972013-07-31 21:16:08101#else
Ben Noordhuis844f0a92016-03-25 16:59:07102#include <pthread.h>
Victor Gomes64159cb2020-04-24 15:28:20103#ifndef __Fuchsia__
Ben Noordhuis68200542013-10-02 10:17:57104#include <sys/resource.h> // getrlimit, setrlimit
Victor Gomes64159cb2020-04-24 15:28:20105#endif
Ben Noordhuis58727052019-05-24 14:11:19106#include <termios.h> // tcgetattr, tcsetattr
Joyee Cheung321e2962018-12-15 19:13:12107#include <unistd.h> // STDIN_FILENO, STDERR_FILENO
Bert Beldera177d602010-11-25 00:02:55108#endif
109
Refael Ackermannf2064df2019-02-25 22:27:19110// ========== global C++ headers ==========
111
112#include <cerrno>
113#include <climits> // PATH_MAX
114#include <csignal>
115#include <cstdio>
116#include <cstdlib>
117#include <cstring>
118
119#include <string>
120#include <vector>
121
Ryand6c9d312009-09-11 14:02:29122namespace node {
123
Joyee Cheungdfd7e992019-04-09 21:08:48124using native_module::NativeModuleEnv;
Joyee Cheungdfd7e992019-04-09 21:08:48125
Joyee Cheung6967f912019-01-15 15:12:21126using v8::EscapableHandleScope;
Ben Noordhuis110a9cd2013-07-03 02:23:44127using v8::Function;
128using v8::FunctionCallbackInfo;
Ben Noordhuis110a9cd2013-07-03 02:23:44129using v8::HandleScope;
Ben Noordhuis110a9cd2013-07-03 02:23:44130using v8::Isolate;
Ben Noordhuis511af4d2013-07-30 19:28:43131using v8::Local;
Anna Henningsenf3cd5372017-12-01 23:04:56132using v8::Maybe;
Michaƫl Zasso023c3172016-02-08 21:34:05133using v8::MaybeLocal;
Ben Noordhuis110a9cd2013-07-03 02:23:44134using v8::Object;
Ben Noordhuis511af4d2013-07-30 19:28:43135using v8::String;
Anna Henningsen64616bb2017-08-08 18:02:55136using v8::Undefined;
Ben Noordhuis110a9cd2013-07-03 02:23:44137using v8::V8;
138using v8::Value;
Ben Noordhuis110a9cd2013-07-03 02:23:44139
Joyee Cheung9db9e7e2019-01-01 05:56:53140namespace per_process {
James M Snell35f6e592017-08-16 16:34:37141
Joyee Cheung9db9e7e2019-01-01 05:56:53142// node_revert.h
143// Bit flag used to track security reverts.
144unsigned int reverted_cve = 0;
145
146// util.h
147// Tells whether the per-process V8::Initialize() is called and
148// if it is safe to call v8::Isolate::GetCurrent().
Anna Henningsen72c60e82016-09-10 16:21:20149bool v8_initialized = false;
150
Joyee Cheung9db9e7e2019-01-01 05:56:53151// node_internals.h
Joyee Cheungfd0a8612019-02-09 15:48:14152// process-relative uptime base in nanoseconds, initialized in node::Start()
153uint64_t node_start_time;
Joyee Cheungca9e24e2019-01-16 19:00:55154// Tells whether --prof is passed.
155bool v8_is_profiling = false;
Joyee Cheung99c32432019-01-16 18:34:43156
157// node_v8_platform-inl.h
158struct V8Platform v8_platform;
Joyee Cheung9db9e7e2019-01-01 05:56:53159} // namespace per_process
Stefan Budeanu410296c2016-03-27 00:17:55160
Ben Noordhuis844f0a92016-03-25 16:59:07161#ifdef __POSIX__
Gus Caplanf2061932019-04-15 21:09:51162void SignalExit(int signo, siginfo_t* info, void* ucontext) {
Ben Noordhuis58727052019-05-24 14:11:19163 ResetStdio();
Geir Haugec61b0e92014-03-31 07:52:03164 raise(signo);
Dean McNameef67e8f22011-03-15 22:39:16165}
Gus Caplanf2061932019-04-15 21:09:51166#endif // __POSIX__
Dean McNameef67e8f22011-03-15 22:39:16167
Joyee Cheung19442652019-03-19 16:12:23168MaybeLocal<Value> ExecuteBootstrapper(Environment* env,
169 const char* id,
170 std::vector<Local<String>>* parameters,
171 std::vector<Local<Value>>* arguments) {
Joyee Cheung6967f912019-01-15 15:12:21172 EscapableHandleScope scope(env->isolate());
173 MaybeLocal<Function> maybe_fn =
Joyee Cheungdfd7e992019-04-09 21:08:48174 NativeModuleEnv::LookupAndCompile(env->context(), id, parameters, env);
Joyee Cheung6967f912019-01-15 15:12:21175
176 if (maybe_fn.IsEmpty()) {
177 return MaybeLocal<Value>();
178 }
179
180 Local<Function> fn = maybe_fn.ToLocalChecked();
181 MaybeLocal<Value> result = fn->Call(env->context(),
182 Undefined(env->isolate()),
183 arguments->size(),
184 arguments->data());
Joyee Cheung2a9eb312018-03-03 20:55:45185
Joyee Cheunga33c3c62019-06-15 00:07:15186 // If there was an error during bootstrap, it must be unrecoverable
187 // (e.g. max call stack exceeded). Clear the stack so that the
188 // AsyncCallbackScope destructor doesn't fail on the id check.
Joyee Cheung2a9eb312018-03-03 20:55:45189 // There are only two ways to have a stack size > 1: 1) the user manually
190 // called MakeCallback or 2) user awaited during bootstrap, which triggered
191 // _tickCallback().
Joyee Cheung6967f912019-01-15 15:12:21192 if (result.IsEmpty()) {
Joyee Cheung2a9eb312018-03-03 20:55:45193 env->async_hooks()->clear_async_id_stack();
194 }
195
Joyee Cheung6967f912019-01-15 15:12:21196 return scope.EscapeMaybe(result);
Joyee Cheung2a9eb312018-03-03 20:55:45197}
198
Shelley Vohr71b342f2019-10-18 17:56:24199#if HAVE_INSPECTOR
Joyee Cheunga0d86be2019-05-20 11:39:21200int Environment::InitializeInspector(
Anna Henningsen86cdfc62019-11-02 20:04:57201 std::unique_ptr<inspector::ParentInspectorHandle> parent_handle) {
Joyee Cheunga0d86be2019-05-20 11:39:21202 std::string inspector_path;
Anna Henningsena9fb51f2019-11-11 14:24:13203 bool is_main = !parent_handle;
Anna Henningsen86cdfc62019-11-02 20:04:57204 if (parent_handle) {
Joyee Cheunga0d86be2019-05-20 11:39:21205 inspector_path = parent_handle->url();
Anna Henningsen86cdfc62019-11-02 20:04:57206 inspector_agent_->SetParentHandle(std::move(parent_handle));
Joyee Cheunga0d86be2019-05-20 11:39:21207 } else {
208 inspector_path = argv_.size() > 1 ? argv_[1].c_str() : "";
209 }
210
211 CHECK(!inspector_agent_->IsListening());
212 // Inspector agent can't fail to start, but if it was configured to listen
213 // right away on the websocket port and fails to bind/etc, this will return
214 // false.
215 inspector_agent_->Start(inspector_path,
216 options_->debug_options(),
217 inspector_host_port(),
Anna Henningsena9fb51f2019-11-11 14:24:13218 is_main);
Joyee Cheunga0d86be2019-05-20 11:39:21219 if (options_->debug_options().inspector_enabled &&
220 !inspector_agent_->IsListening()) {
221 return 12; // Signal internal error
222 }
223
224 profiler::StartProfilers(this);
225
Samuel Attard42081582019-06-19 18:44:49226 if (inspector_agent_->options().break_node_first_line) {
Joyee Cheunga0d86be2019-05-20 11:39:21227 inspector_agent_->PauseOnNextJavascriptStatement("Break at bootstrap");
228 }
229
230 return 0;
231}
232#endif // HAVE_INSPECTOR && NODE_USE_V8_PLATFORM
233
234void Environment::InitializeDiagnostics() {
235 isolate_->GetHeapProfiler()->AddBuildEmbedderGraphCallback(
236 Environment::BuildEmbedderGraph, this);
Anna Henningsen31217a82019-10-18 15:05:35237 if (options_->trace_uncaught)
238 isolate_->SetCaptureStackTraceForUncaughtExceptions(true);
Joyee Cheunga0d86be2019-05-20 11:39:21239
240#if defined HAVE_DTRACE || defined HAVE_ETW
241 InitDTrace(this);
242#endif
243}
244
Joyee Cheung07785992019-05-20 11:50:13245MaybeLocal<Value> Environment::BootstrapInternalLoaders() {
246 EscapableHandleScope scope(isolate_);
Joyee Cheung39d92212019-01-30 14:21:07247
Joyee Cheung2a9eb312018-03-03 20:55:45248 // Create binding loaders
Joyee Cheungedcb9502018-11-26 17:50:41249 std::vector<Local<String>> loaders_params = {
Joyee Cheung07785992019-05-20 11:50:13250 process_string(),
251 FIXED_ONE_BYTE_STRING(isolate_, "getLinkedBinding"),
252 FIXED_ONE_BYTE_STRING(isolate_, "getInternalBinding"),
253 primordials_string()};
Joyee Cheungedcb9502018-11-26 17:50:41254 std::vector<Local<Value>> loaders_args = {
Joyee Cheung07785992019-05-20 11:50:13255 process_object(),
256 NewFunctionTemplate(binding::GetLinkedBinding)
257 ->GetFunction(context())
Joyee Cheungedcb9502018-11-26 17:50:41258 .ToLocalChecked(),
Joyee Cheung07785992019-05-20 11:50:13259 NewFunctionTemplate(binding::GetInternalBinding)
260 ->GetFunction(context())
Joyee Cheungedcb9502018-11-26 17:50:41261 .ToLocalChecked(),
Joyee Cheung07785992019-05-20 11:50:13262 primordials()};
Joyee Cheung2a9eb312018-03-03 20:55:45263
Joyee Cheung2a9eb312018-03-03 20:55:45264 // Bootstrap internal loaders
Joyee Cheung07785992019-05-20 11:50:13265 Local<Value> loader_exports;
266 if (!ExecuteBootstrapper(
267 this, "internal/bootstrap/loaders", &loaders_params, &loaders_args)
268 .ToLocal(&loader_exports)) {
Joyee Cheung6967f912019-01-15 15:12:21269 return MaybeLocal<Value>();
Joyee Cheung2a9eb312018-03-03 20:55:45270 }
Joyee Cheung07785992019-05-20 11:50:13271 CHECK(loader_exports->IsObject());
272 Local<Object> loader_exports_obj = loader_exports.As<Object>();
Joyee Cheung6967f912019-01-15 15:12:21273 Local<Value> internal_binding_loader =
Joyee Cheung07785992019-05-20 11:50:13274 loader_exports_obj->Get(context(), internal_binding_string())
Joyee Cheung6967f912019-01-15 15:12:21275 .ToLocalChecked();
Joyee Cheung07785992019-05-20 11:50:13276 CHECK(internal_binding_loader->IsFunction());
277 set_internal_binding_loader(internal_binding_loader.As<Function>());
Joyee Cheung6967f912019-01-15 15:12:21278 Local<Value> require =
Joyee Cheung07785992019-05-20 11:50:13279 loader_exports_obj->Get(context(), require_string()).ToLocalChecked();
280 CHECK(require->IsFunction());
281 set_native_module_require(require.As<Function>());
282
283 return scope.Escape(loader_exports);
284}
285
286MaybeLocal<Value> Environment::BootstrapNode() {
287 EscapableHandleScope scope(isolate_);
288
289 Local<Object> global = context()->Global();
290 // TODO(joyeecheung): this can be done in JS land now.
291 global->Set(context(), FIXED_ONE_BYTE_STRING(isolate_, "global"), global)
292 .Check();
Joyee Cheung6967f912019-01-15 15:12:21293
Joyee Cheungc63d5112019-12-09 02:53:02294 // process, require, internalBinding, primordials
Joyee Cheungedcb9502018-11-26 17:50:41295 std::vector<Local<String>> node_params = {
Joyee Cheung07785992019-05-20 11:50:13296 process_string(),
297 require_string(),
298 internal_binding_string(),
Joyee Cheung07785992019-05-20 11:50:13299 primordials_string()};
Joyee Cheungedcb9502018-11-26 17:50:41300 std::vector<Local<Value>> node_args = {
Joyee Cheung07785992019-05-20 11:50:13301 process_object(),
302 native_module_require(),
303 internal_binding_loader(),
Joyee Cheung07785992019-05-20 11:50:13304 primordials()};
Joyee Cheungedcb9502018-11-26 17:50:41305
Joyee Cheung6967f912019-01-15 15:12:21306 MaybeLocal<Value> result = ExecuteBootstrapper(
Joyee Cheung07785992019-05-20 11:50:13307 this, "internal/bootstrap/node", &node_params, &node_args);
Anna Henningsenf6a1d882019-01-02 21:14:23308
Joyee Cheungc63d5112019-12-09 02:53:02309 if (result.IsEmpty()) {
310 return scope.EscapeMaybe(result);
311 }
312
Denys Otrishko08f57262020-01-22 19:21:22313 auto thread_switch_id =
314 is_main_thread() ? "internal/bootstrap/switches/is_main_thread"
315 : "internal/bootstrap/switches/is_not_main_thread";
316 result =
317 ExecuteBootstrapper(this, thread_switch_id, &node_params, &node_args);
Joyee Cheungc63d5112019-12-09 02:53:02318
319 if (result.IsEmpty()) {
320 return scope.EscapeMaybe(result);
321 }
322
Denys Otrishko08f57262020-01-22 19:21:22323 auto process_state_switch_id =
324 owns_process_state()
325 ? "internal/bootstrap/switches/does_own_process_state"
326 : "internal/bootstrap/switches/does_not_own_process_state";
327 result = ExecuteBootstrapper(
328 this, process_state_switch_id, &node_params, &node_args);
Joyee Cheungc63d5112019-12-09 02:53:02329
330 if (result.IsEmpty()) {
331 return scope.EscapeMaybe(result);
332 }
333
Denys Otrishko08f57262020-01-22 19:21:22334 Local<String> env_string = FIXED_ONE_BYTE_STRING(isolate_, "env");
Joyee Cheungee2d2632019-03-06 14:25:18335 Local<Object> env_var_proxy;
Anna Henningsen6576b9b2019-03-05 00:28:45336 if (!CreateEnvVarProxy(context(), isolate_, current_callback_data())
Joyee Cheungee2d2632019-03-06 14:25:18337 .ToLocal(&env_var_proxy) ||
Denys Otrishko08f57262020-01-22 19:21:22338 process_object()->Set(context(), env_string, env_var_proxy).IsNothing()) {
Joyee Cheungee2d2632019-03-06 14:25:18339 return MaybeLocal<Value>();
Joyee Cheung07785992019-05-20 11:50:13340 }
341
342 return scope.EscapeMaybe(result);
343}
344
345MaybeLocal<Value> Environment::RunBootstrapping() {
346 EscapableHandleScope scope(isolate_);
347
348 CHECK(!has_run_bootstrapping_code());
349
350 if (BootstrapInternalLoaders().IsEmpty()) {
351 return MaybeLocal<Value>();
352 }
353
354 Local<Value> result;
355 if (!BootstrapNode().ToLocal(&result)) {
356 return MaybeLocal<Value>();
357 }
Joyee Cheungee2d2632019-03-06 14:25:18358
Joyee Cheung197dbf62019-03-11 15:52:47359 // Make sure that no request or handle is created during bootstrap -
gengjiawen3b48ce62019-05-06 13:58:16360 // if necessary those should be done in pre-execution.
Anna Henningsen850f3812019-11-12 18:33:37361 // Usually, doing so would trigger the checks present in the ReqWrap and
362 // HandleWrap classes, so this is only a consistency check.
Joyee Cheung07785992019-05-20 11:50:13363 CHECK(req_wrap_queue()->IsEmpty());
364 CHECK(handle_wrap_queue()->IsEmpty());
Joyee Cheung197dbf62019-03-11 15:52:47365
Joyee Cheung07785992019-05-20 11:50:13366 set_has_run_bootstrapping_code(true);
Joyee Cheung6967f912019-01-15 15:12:21367
Joyee Cheung07785992019-05-20 11:50:13368 return scope.Escape(result);
Anna Henningsenf6a1d882019-01-02 21:14:23369}
370
Joyee Cheung6967f912019-01-15 15:12:21371void MarkBootstrapComplete(const FunctionCallbackInfo<Value>& args) {
372 Environment* env = Environment::GetCurrent(args);
373 env->performance_state()->Mark(
374 performance::NODE_PERFORMANCE_MILESTONE_BOOTSTRAP_COMPLETE);
375}
Anna Henningsenf6a1d882019-01-02 21:14:23376
Anna Henningsenc44edec2019-11-13 15:54:57377static
Joyee Cheung6967f912019-01-15 15:12:21378MaybeLocal<Value> StartExecution(Environment* env, const char* main_script_id) {
379 EscapableHandleScope scope(env->isolate());
ZYSzys93e0c6a2019-02-04 07:38:51380 CHECK_NOT_NULL(main_script_id);
Joyee Cheung2c7f4f42019-01-13 15:44:09381
Joyee Cheung6967f912019-01-15 15:12:21382 std::vector<Local<String>> parameters = {
383 env->process_string(),
384 env->require_string(),
385 env->internal_binding_string(),
Michaƫl Zasso908292c2019-04-09 07:55:53386 env->primordials_string(),
Joyee Cheung6967f912019-01-15 15:12:21387 FIXED_ONE_BYTE_STRING(env->isolate(), "markBootstrapComplete")};
388
389 std::vector<Local<Value>> arguments = {
390 env->process_object(),
391 env->native_module_require(),
392 env->internal_binding_loader(),
Michaƫl Zasso908292c2019-04-09 07:55:53393 env->primordials(),
Joyee Cheung6967f912019-01-15 15:12:21394 env->NewFunctionTemplate(MarkBootstrapComplete)
395 ->GetFunction(env->context())
396 .ToLocalChecked()};
397
Anna Henningsend80e49d2019-11-03 12:00:24398 return scope.EscapeMaybe(
399 ExecuteBootstrapper(env, main_script_id, &parameters, &arguments));
Joyee Cheung6967f912019-01-15 15:12:21400}
401
Anna Henningsenc44edec2019-11-13 15:54:57402MaybeLocal<Value> StartExecution(Environment* env, StartExecutionCallback cb) {
403 InternalCallbackScope callback_scope(
404 env,
405 Object::New(env->isolate()),
406 { 1, 0 },
407 InternalCallbackScope::kSkipAsyncHooks);
408
409 if (cb != nullptr) {
410 EscapableHandleScope scope(env->isolate());
411
412 if (StartExecution(env, "internal/bootstrap/environment").IsEmpty())
413 return {};
414
415 StartExecutionCallbackInfo info = {
416 env->process_object(),
417 env->native_module_require(),
418 };
419
420 return scope.EscapeMaybe(cb(info));
421 }
422
Joyee Cheung6967f912019-01-15 15:12:21423 // To allow people to extend Node in different ways, this hook allows
424 // one to drop a file lib/_third_party_main.js into the build
425 // directory which will be executed instead of Node's normal loading.
Joyee Cheungdfd7e992019-04-09 21:08:48426 if (NativeModuleEnv::Exists("_third_party_main")) {
Joyee Cheung6967f912019-01-15 15:12:21427 return StartExecution(env, "internal/main/run_third_party_main");
Joyee Cheung2c7f4f42019-01-13 15:44:09428 }
429
Anna Henningsena9fb51f2019-11-11 14:24:13430 if (env->worker_context() != nullptr) {
431 return StartExecution(env, "internal/main/worker_thread");
432 }
433
Joyee Cheungd005f382019-03-19 23:55:59434 std::string first_argv;
435 if (env->argv().size() > 1) {
436 first_argv = env->argv()[1];
437 }
438
439 if (first_argv == "inspect" || first_argv == "debug") {
Joyee Cheung6967f912019-01-15 15:12:21440 return StartExecution(env, "internal/main/inspect");
441 }
442
443 if (per_process::cli_options->print_help) {
Joyee Cheung6967f912019-01-15 15:12:21444 return StartExecution(env, "internal/main/print_help");
445 }
446
Joyee Cheung6967f912019-01-15 15:12:21447
448 if (env->options()->prof_process) {
Joyee Cheung6967f912019-01-15 15:12:21449 return StartExecution(env, "internal/main/prof_process");
450 }
451
452 // -e/--eval without -i/--interactive
453 if (env->options()->has_eval_string && !env->options()->force_repl) {
Joyee Cheung6967f912019-01-15 15:12:21454 return StartExecution(env, "internal/main/eval_string");
455 }
456
457 if (env->options()->syntax_check_only) {
Joyee Cheung6967f912019-01-15 15:12:21458 return StartExecution(env, "internal/main/check_syntax");
459 }
460
Joyee Cheungd005f382019-03-19 23:55:59461 if (!first_argv.empty() && first_argv != "-") {
Joyee Cheung6967f912019-01-15 15:12:21462 return StartExecution(env, "internal/main/run_main_module");
463 }
464
465 if (env->options()->force_repl || uv_guess_handle(STDIN_FILENO) == UV_TTY) {
Joyee Cheung6967f912019-01-15 15:12:21466 return StartExecution(env, "internal/main/repl");
467 }
468
Joyee Cheung6967f912019-01-15 15:12:21469 return StartExecution(env, "internal/main/eval_stdin");
470}
471
Anna Henningsen89b32372019-05-20 00:03:48472#ifdef __POSIX__
473typedef void (*sigaction_cb)(int signo, siginfo_t* info, void* ucontext);
474#endif
Gus Caplanf2061932019-04-15 21:09:51475#if NODE_USE_V8_WASM_TRAP_HANDLER
Anna Henningsen89b32372019-05-20 00:03:48476static std::atomic<sigaction_cb> previous_sigsegv_action;
Gus Caplanf2061932019-04-15 21:09:51477
478void TrapWebAssemblyOrContinue(int signo, siginfo_t* info, void* ucontext) {
479 if (!v8::TryHandleWebAssemblyTrapPosix(signo, info, ucontext)) {
Anna Henningsen89b32372019-05-20 00:03:48480 sigaction_cb prev = previous_sigsegv_action.load();
Gus Caplanf2061932019-04-15 21:09:51481 if (prev != nullptr) {
482 prev(signo, info, ucontext);
483 } else {
Anna Henningsene2562042019-05-19 23:57:17484 // Reset to the default signal handler, i.e. cause a hard crash.
485 struct sigaction sa;
486 memset(&sa, 0, sizeof(sa));
487 sa.sa_handler = SIG_DFL;
488 CHECK_EQ(sigaction(signo, &sa, nullptr), 0);
489
Ben Noordhuis58727052019-05-24 14:11:19490 ResetStdio();
Gus Caplanf2061932019-04-15 21:09:51491 raise(signo);
492 }
493 }
494}
495#endif // NODE_USE_V8_WASM_TRAP_HANDLER
Ryan Dahl2a7e7b12010-12-18 19:17:29496
Victor Gomes64159cb2020-04-24 15:28:20497#if defined(POSIX) && !defined(__Fuchsia__)
Anna Henningsen0815b942016-05-08 01:28:47498void RegisterSignalHandler(int signal,
Anna Henningsen89b32372019-05-20 00:03:48499 sigaction_cb handler,
Anna Henningsen0815b942016-05-08 01:28:47500 bool reset_handler) {
Anna Henningsen89b32372019-05-20 00:03:48501 CHECK_NOT_NULL(handler);
Gus Caplanf2061932019-04-15 21:09:51502#if NODE_USE_V8_WASM_TRAP_HANDLER
503 if (signal == SIGSEGV) {
504 CHECK(previous_sigsegv_action.is_lock_free());
Anna Henningsen89b32372019-05-20 00:03:48505 CHECK(!reset_handler);
Gus Caplanf2061932019-04-15 21:09:51506 previous_sigsegv_action.store(handler);
507 return;
508 }
509#endif // NODE_USE_V8_WASM_TRAP_HANDLER
Tom Hughesf61b1102010-10-12 21:01:58510 struct sigaction sa;
Tom Hughesf61b1102010-10-12 21:01:58511 memset(&sa, 0, sizeof(sa));
Gus Caplanf2061932019-04-15 21:09:51512 sa.sa_sigaction = handler;
Geir Haugec61b0e92014-03-31 07:52:03513 sa.sa_flags = reset_handler ? SA_RESETHAND : 0;
Tom Hughesf61b1102010-10-12 21:01:58514 sigfillset(&sa.sa_mask);
Ben Noordhuis2d82cdf2014-10-22 01:29:32515 CHECK_EQ(sigaction(signal, &sa, nullptr), 0);
Bert Belder829735e2011-11-04 15:23:02516}
517
Fedor Indutny8e29ce92013-07-31 18:07:29518#endif // __POSIX__
Tom Hughesf61b1102010-10-12 21:01:58519
Ben Noordhuis58727052019-05-24 14:11:19520#ifdef __POSIX__
521static struct {
522 int flags;
523 bool isatty;
524 struct stat stat;
525 struct termios termios;
526} stdio[1 + STDERR_FILENO];
527#endif // __POSIX__
528
529
Ben Noordhuis5756f922015-01-26 22:15:20530inline void PlatformInit() {
531#ifdef __POSIX__
Daniel Bevenius65a6e052017-04-07 06:48:32532#if HAVE_INSPECTOR
Ben Noordhuis63ae1d22015-01-26 22:26:33533 sigset_t sigmask;
534 sigemptyset(&sigmask);
535 sigaddset(&sigmask, SIGUSR1);
Ben Noordhuisb5f25a92015-02-18 02:43:29536 const int err = pthread_sigmask(SIG_SETMASK, &sigmask, nullptr);
Daniel Bevenius65a6e052017-04-07 06:48:32537#endif // HAVE_INSPECTOR
Ben Noordhuisb5f25a92015-02-18 02:43:29538
539 // Make sure file descriptors 0-2 are valid before we start logging anything.
Ben Noordhuis58727052019-05-24 14:11:19540 for (auto& s : stdio) {
541 const int fd = &s - stdio;
Victor Gomes64159cb2020-04-24 15:28:20542#ifdef __Fuchsia__
543 // In fuchsia stdin is not readily available.
544 if (fd == 0) continue;
545#endif
Ben Noordhuis58727052019-05-24 14:11:19546 if (fstat(fd, &s.stat) == 0)
Ben Noordhuisb5f25a92015-02-18 02:43:29547 continue;
548 // Anything but EBADF means something is seriously wrong. We don't
549 // have to special-case EINTR, fstat() is not interruptible.
550 if (errno != EBADF)
Evan Lucas870229e2015-09-16 15:12:41551 ABORT();
Ben Noordhuisb5f25a92015-02-18 02:43:29552 if (fd != open("/dev/null", O_RDWR))
Evan Lucas870229e2015-09-16 15:12:41553 ABORT();
Ben Noordhuis58727052019-05-24 14:11:19554 if (fstat(fd, &s.stat) != 0)
555 ABORT();
Ben Noordhuisb5f25a92015-02-18 02:43:29556 }
557
Daniel Bevenius65a6e052017-04-07 06:48:32558#if HAVE_INSPECTOR
Ben Noordhuisb5f25a92015-02-18 02:43:29559 CHECK_EQ(err, 0);
Daniel Bevenius65a6e052017-04-07 06:48:32560#endif // HAVE_INSPECTOR
Ben Noordhuisdd47a8c2015-01-26 23:07:34561
Anna Henningsen7e2a1822019-11-02 18:06:59562 // TODO(addaleax): NODE_SHARED_MODE does not really make sense here.
Victor Gomes64159cb2020-04-24 15:28:20563#if !defined(NODE_SHARED_MODE) && !defined(__Fuchsia__)
Ben Noordhuisdd47a8c2015-01-26 23:07:34564 // Restore signal dispositions, the parent process may have changed them.
565 struct sigaction act;
566 memset(&act, 0, sizeof(act));
567
568 // The hard-coded upper limit is because NSIG is not very reliable; on Linux,
569 // it evaluates to 32, 34 or 64, depending on whether RT signals are enabled.
570 // Counting up to SIGRTMIN doesn't work for the same reason.
Eugene Ostroukhov66269192016-06-08 21:09:28571 for (unsigned nr = 1; nr < kMaxSignal; nr += 1) {
Ben Noordhuisdd47a8c2015-01-26 23:07:34572 if (nr == SIGKILL || nr == SIGSTOP)
573 continue;
Ben Noordhuis58fe4402019-05-23 09:27:53574 act.sa_handler = (nr == SIGPIPE || nr == SIGXFSZ) ? SIG_IGN : SIG_DFL;
Ben Noordhuisdd47a8c2015-01-26 23:07:34575 CHECK_EQ(0, sigaction(nr, &act, nullptr));
576 }
Stewart X Addison0f0f3d32016-12-30 12:44:46577#endif // !NODE_SHARED_MODE
Ben Noordhuisdd47a8c2015-01-26 23:07:34578
Ben Noordhuis58727052019-05-24 14:11:19579 // Record the state of the stdio file descriptors so we can restore it
580 // on exit. Needs to happen before installing signal handlers because
581 // they make use of that information.
582 for (auto& s : stdio) {
583 const int fd = &s - stdio;
584 int err;
Victor Gomes64159cb2020-04-24 15:28:20585#ifdef __Fuchsia__
586 // In fuchsia stdin is not readily available.
587 if (fd == 0) continue;
588#endif
Ben Noordhuis58727052019-05-24 14:11:19589
590 do
591 s.flags = fcntl(fd, F_GETFL);
592 while (s.flags == -1 && errno == EINTR); // NOLINT
593 CHECK_NE(s.flags, -1);
594
cjihrig38c07842020-01-12 23:52:41595 if (uv_guess_handle(fd) != UV_TTY) continue;
Ben Noordhuis58727052019-05-24 14:11:19596 s.isatty = true;
597
598 do
599 err = tcgetattr(fd, &s.termios);
600 while (err == -1 && errno == EINTR); // NOLINT
601 CHECK_EQ(err, 0);
602 }
603
Victor Gomes64159cb2020-04-24 15:28:20604#ifndef __Fuchsia__
Ben Noordhuis63ae1d22015-01-26 22:26:33605 RegisterSignalHandler(SIGINT, SignalExit, true);
606 RegisterSignalHandler(SIGTERM, SignalExit, true);
Ben Noordhuisdd47a8c2015-01-26 23:07:34607
Gus Caplanf2061932019-04-15 21:09:51608#if NODE_USE_V8_WASM_TRAP_HANDLER
609 // Tell V8 to disable emitting WebAssembly
610 // memory bounds checks. This means that we have
611 // to catch the SIGSEGV in TrapWebAssemblyOrContinue
612 // and pass the signal context to V8.
613 {
614 struct sigaction sa;
615 memset(&sa, 0, sizeof(sa));
616 sa.sa_sigaction = TrapWebAssemblyOrContinue;
617 CHECK_EQ(sigaction(SIGSEGV, &sa, nullptr), 0);
618 }
619 V8::EnableWebAssemblyTrapHandler(false);
620#endif // NODE_USE_V8_WASM_TRAP_HANDLER
621
Ben Noordhuis5756f922015-01-26 22:15:20622 // Raise the open file descriptor limit.
623 struct rlimit lim;
624 if (getrlimit(RLIMIT_NOFILE, &lim) == 0 && lim.rlim_cur != lim.rlim_max) {
625 // Do a binary search for the limit.
626 rlim_t min = lim.rlim_cur;
627 rlim_t max = 1 << 20;
628 // But if there's a defined upper bound, don't search, just set it.
629 if (lim.rlim_max != RLIM_INFINITY) {
630 min = lim.rlim_max;
631 max = lim.rlim_max;
632 }
633 do {
634 lim.rlim_cur = min + (max - min) / 2;
635 if (setrlimit(RLIMIT_NOFILE, &lim)) {
636 max = lim.rlim_cur;
637 } else {
638 min = lim.rlim_cur;
639 }
640 } while (min + 1 < max);
641 }
Victor Gomes64159cb2020-04-24 15:28:20642#endif // __Fuchsia__
Ben Noordhuis5756f922015-01-26 22:15:20643#endif // __POSIX__
Bartosz Sosnowskibd496e02017-03-14 17:22:53644#ifdef _WIN32
645 for (int fd = 0; fd <= 2; ++fd) {
646 auto handle = reinterpret_cast<HANDLE>(_get_osfhandle(fd));
647 if (handle == INVALID_HANDLE_VALUE ||
648 GetFileType(handle) == FILE_TYPE_UNKNOWN) {
649 // Ignore _close result. If it fails or not depends on used Windows
650 // version. We will just check _open result.
651 _close(fd);
652 if (fd != _open("nul", _O_RDWR))
653 ABORT();
654 }
655 }
656#endif // _WIN32
Ben Noordhuis5756f922015-01-26 22:15:20657}
658
Ben Noordhuis58727052019-05-24 14:11:19659
660// Safe to call more than once and from signal handlers.
661void ResetStdio() {
662 uv_tty_reset_mode();
663#ifdef __POSIX__
664 for (auto& s : stdio) {
665 const int fd = &s - stdio;
666
Victor Gomes64159cb2020-04-24 15:28:20667#ifdef __Fuchsia__
668 // In fuchsia stdin is not readily available.
669 if (fd == 0) continue;
670#endif
671
Ben Noordhuis58727052019-05-24 14:11:19672 struct stat tmp;
673 if (-1 == fstat(fd, &tmp)) {
674 CHECK_EQ(errno, EBADF); // Program closed file descriptor.
675 continue;
676 }
677
678 bool is_same_file =
679 (s.stat.st_dev == tmp.st_dev && s.stat.st_ino == tmp.st_ino);
680 if (!is_same_file) continue; // Program reopened file descriptor.
681
682 int flags;
683 do
684 flags = fcntl(fd, F_GETFL);
685 while (flags == -1 && errno == EINTR); // NOLINT
686 CHECK_NE(flags, -1);
687
688 // Restore the O_NONBLOCK flag if it changed.
689 if (O_NONBLOCK & (flags ^ s.flags)) {
690 flags &= ~O_NONBLOCK;
691 flags |= s.flags & O_NONBLOCK;
692
693 int err;
694 do
695 err = fcntl(fd, F_SETFL, flags);
696 while (err == -1 && errno == EINTR); // NOLINT
697 CHECK_NE(err, -1);
698 }
699
700 if (s.isatty) {
Ben Noordhuisb06ce0b2019-07-04 10:11:00701 sigset_t sa;
Ben Noordhuis58727052019-05-24 14:11:19702 int err;
Ben Noordhuisb06ce0b2019-07-04 10:11:00703
704 // We might be a background job that doesn't own the TTY so block SIGTTOU
705 // before making the tcsetattr() call, otherwise that signal suspends us.
706 sigemptyset(&sa);
707 sigaddset(&sa, SIGTTOU);
708
709 CHECK_EQ(0, pthread_sigmask(SIG_BLOCK, &sa, nullptr));
Ben Noordhuis58727052019-05-24 14:11:19710 do
711 err = tcsetattr(fd, TCSANOW, &s.termios);
712 while (err == -1 && errno == EINTR); // NOLINT
Ben Noordhuisb06ce0b2019-07-04 10:11:00713 CHECK_EQ(0, pthread_sigmask(SIG_UNBLOCK, &sa, nullptr));
714 CHECK_EQ(0, err);
Ben Noordhuis58727052019-05-24 14:11:19715 }
716 }
717#endif // __POSIX__
718}
719
720
Anna Henningseneb664c32019-01-06 21:55:09721int ProcessGlobalArgs(std::vector<std::string>* args,
722 std::vector<std::string>* exec_args,
723 std::vector<std::string>* errors,
Shelley Vohr0f58bfd2019-11-13 15:53:19724 OptionEnvvarSettings settings) {
Sam Robertsf2282bb2017-02-20 14:18:43725 // Parse a few arguments which are specific to Node.
Anna Henningsen29a71ba2018-08-10 00:45:28726 std::vector<std::string> v8_args;
Anna Henningsene812be42018-08-23 14:41:05727
Anna Henningseneb664c32019-01-06 21:55:09728 Mutex::ScopedLock lock(per_process::cli_options_mutex);
Refael Ackermannaf8b92c2019-02-23 22:21:56729 options_parser::Parse(
Anna Henningseneb664c32019-01-06 21:55:09730 args,
731 exec_args,
732 &v8_args,
733 per_process::cli_options.get(),
Shelley Vohr0f58bfd2019-11-13 15:53:19734 settings,
Anna Henningseneb664c32019-01-06 21:55:09735 errors);
Anna Henningsene812be42018-08-23 14:41:05736
Anna Henningseneb664c32019-01-06 21:55:09737 if (!errors->empty()) return 9;
Anna Henningsen29a71ba2018-08-10 00:45:28738
Anna Henningsen38ab1e92019-01-12 19:55:58739 std::string revert_error;
740 for (const std::string& cve : per_process::cli_options->security_reverts) {
741 Revert(cve.c_str(), &revert_error);
742 if (!revert_error.empty()) {
743 errors->emplace_back(std::move(revert_error));
744 return 12;
745 }
746 }
Anna Henningsen29a71ba2018-08-10 00:45:28747
Gus Caplan7a742ec2020-03-15 00:54:15748 if (per_process::cli_options->disable_proto != "delete" &&
749 per_process::cli_options->disable_proto != "throw" &&
750 per_process::cli_options->disable_proto != "") {
751 errors->emplace_back("invalid mode passed to --disable-proto");
752 return 12;
753 }
754
Joyee Cheung9db9e7e2019-01-01 05:56:53755 auto env_opts = per_process::cli_options->per_isolate->per_env;
Anna Henningsen29a71ba2018-08-10 00:45:28756 if (std::find(v8_args.begin(), v8_args.end(),
757 "--abort-on-uncaught-exception") != v8_args.end() ||
758 std::find(v8_args.begin(), v8_args.end(),
759 "--abort_on_uncaught_exception") != v8_args.end()) {
Daniel Bevenius6a9e7762018-09-06 08:39:38760 env_opts->abort_on_uncaught_exception = true;
Anna Henningsen29a71ba2018-08-10 00:45:28761 }
Sam Robertsf2282bb2017-02-20 14:18:43762
763 // TODO(bnoordhuis) Intercept --prof arguments and start the CPU profiler
764 // manually? That would give us a little more control over its runtime
765 // behavior but it could also interfere with the user's intentions in ways
766 // we fail to anticipate. Dillema.
Anna Henningsen29a71ba2018-08-10 00:45:28767 if (std::find(v8_args.begin(), v8_args.end(), "--prof") != v8_args.end()) {
Joyee Cheung9db9e7e2019-01-01 05:56:53768 per_process::v8_is_profiling = true;
Sam Robertsf2282bb2017-02-20 14:18:43769 }
770
771#ifdef __POSIX__
772 // Block SIGPROF signals when sleeping in epoll_wait/kevent/etc. Avoids the
773 // performance penalty of frequent EINTR wakeups when the profiler is running.
774 // Only do this for v8.log profiling, as it breaks v8::CpuProfiler users.
Joyee Cheung9db9e7e2019-01-01 05:56:53775 if (per_process::v8_is_profiling) {
Sam Robertsf2282bb2017-02-20 14:18:43776 uv_loop_configure(uv_default_loop(), UV_LOOP_BLOCK_SIGNAL, SIGPROF);
777 }
778#endif
779
Anna Henningsen29a71ba2018-08-10 00:45:28780 std::vector<char*> v8_args_as_char_ptr(v8_args.size());
781 if (v8_args.size() > 0) {
782 for (size_t i = 0; i < v8_args.size(); ++i)
783 v8_args_as_char_ptr[i] = &v8_args[i][0];
784 int argc = v8_args.size();
785 V8::SetFlagsFromCommandLine(&argc, &v8_args_as_char_ptr[0], true);
786 v8_args_as_char_ptr.resize(argc);
787 }
Sam Robertsf2282bb2017-02-20 14:18:43788
789 // Anything that's still in v8_argv is not a V8 or a node option.
Anna Henningseneb664c32019-01-06 21:55:09790 for (size_t i = 1; i < v8_args_as_char_ptr.size(); i++)
791 errors->push_back("bad option: " + std::string(v8_args_as_char_ptr[i]));
Sam Robertsf2282bb2017-02-20 14:18:43792
Anna Henningseneb664c32019-01-06 21:55:09793 if (v8_args_as_char_ptr.size() > 1) return 9;
794
795 return 0;
Sam Robertsf2282bb2017-02-20 14:18:43796}
797
Anna Henningsen97ce5e02019-03-05 19:16:33798static std::atomic_bool init_called{false};
799
Joyee Cheung963ee0b2019-03-07 13:52:31800int InitializeNodeWithArgs(std::vector<std::string>* argv,
801 std::vector<std::string>* exec_argv,
802 std::vector<std::string>* errors) {
803 // Make sure InitializeNodeWithArgs() is called only once.
Anna Henningsen97ce5e02019-03-05 19:16:33804 CHECK(!init_called.exchange(true));
805
Micha Hanselmann35cb9552019-07-24 22:34:33806 // Initialize node_start_time to get relative uptime.
807 per_process::node_start_time = uv_hrtime();
808
Yihong Wang8680bb92017-10-22 06:16:50809 // Register built-in modules
Joyee Cheung3d668262018-11-28 16:46:45810 binding::RegisterBuiltinModules();
Yihong Wang8680bb92017-10-22 06:16:50811
Bert Belder09be3602012-06-13 23:28:51812 // Make inherited handles noninheritable.
813 uv_disable_stdio_inheritance();
814
Gireesh Punathil4f679732018-09-05 14:06:59815 // Cache the original command line to be
816 // used in diagnostic reports.
817 per_process::cli_options->cmdline = *argv;
Gireesh Punathil4f679732018-09-05 14:06:59818
Ben Noordhuis490d5ab2014-03-31 12:22:49819#if defined(NODE_V8_OPTIONS)
820 // Should come before the call to V8::SetFlagsFromCommandLine()
821 // so the user can disable a flag --foo at run-time by passing
822 // --no_foo from the command line.
823 V8::SetFlagsFromString(NODE_V8_OPTIONS, sizeof(NODE_V8_OPTIONS) - 1);
824#endif
Fedor Indutnyb55c9d62014-03-26 20:30:49825
Denys Otrishko84b88572020-02-09 22:17:33826 HandleEnvOptions(per_process::cli_options->per_isolate->per_env);
James M Snell03e89b32016-12-04 18:38:35827
Sam Robertsf2282bb2017-02-20 14:18:43828#if !defined(NODE_WITHOUT_NODE_OPTIONS)
829 std::string node_options;
Maƫl Nison3ef15122018-11-03 17:52:44830
Joyee Cheung321e2962018-12-15 19:13:12831 if (credentials::SafeGetenv("NODE_OPTIONS", &node_options)) {
Denys Otrishko84b88572020-02-09 22:17:33832 std::vector<std::string> env_argv =
833 ParseNodeOptionsEnvVar(node_options, errors);
834
835 if (!errors->empty()) return 9;
836
Maƫl Nison3ef15122018-11-03 17:52:44837 // [0] is expected to be the program name, fill it in from the real argv.
Denys Otrishko84b88572020-02-09 22:17:33838 env_argv.insert(env_argv.begin(), argv->at(0));
Anna Henningsen29a71ba2018-08-10 00:45:28839
Shelley Vohr0f58bfd2019-11-13 15:53:19840 const int exit_code = ProcessGlobalArgs(&env_argv,
841 nullptr,
842 errors,
843 kAllowedInEnvironment);
Anna Henningseneb664c32019-01-06 21:55:09844 if (exit_code != 0) return exit_code;
Oleksandr Chekhovskyi8e141352015-08-07 13:03:04845 }
846#endif
847
Shelley Vohr0f58bfd2019-11-13 15:53:19848 const int exit_code = ProcessGlobalArgs(argv,
849 exec_argv,
850 errors,
851 kDisallowedInEnvironment);
Anna Henningseneb664c32019-01-06 21:55:09852 if (exit_code != 0) return exit_code;
Sam Robertsf2282bb2017-02-20 14:18:43853
James M Snell9d716192018-06-22 23:16:03854 // Set the process.title immediately after processing argv if --title is set.
Joyee Cheung9db9e7e2019-01-01 05:56:53855 if (!per_process::cli_options->title.empty())
856 uv_set_process_title(per_process::cli_options->title.c_str());
James M Snell9d716192018-06-22 23:16:03857
Steven R. Loomisac2857b2014-09-05 05:03:24858#if defined(NODE_HAVE_I18N_SUPPORT)
Ben Noordhuisa8734af2017-01-28 12:27:02859 // If the parameter isn't given, use the env variable.
Joyee Cheung9db9e7e2019-01-01 05:56:53860 if (per_process::cli_options->icu_data_dir.empty())
861 credentials::SafeGetenv("NODE_ICU_DATA",
862 &per_process::cli_options->icu_data_dir);
Stephen Gallagherd502b832019-12-06 21:40:25863
864#ifdef NODE_ICU_DEFAULT_DATA_DIR
865 // If neither the CLI option nor the environment variable was specified,
866 // fall back to the configured default
867 if (per_process::cli_options->icu_data_dir.empty()) {
868 // Check whether the NODE_ICU_DEFAULT_DATA_DIR contains the right data
869 // file and can be read.
870 static const char full_path[] =
871 NODE_ICU_DEFAULT_DATA_DIR "/" U_ICUDATA_NAME ".dat";
872
873 FILE* f = fopen(full_path, "rb");
874
875 if (f != nullptr) {
876 fclose(f);
877 per_process::cli_options->icu_data_dir = NODE_ICU_DEFAULT_DATA_DIR;
878 }
879 }
880#endif // NODE_ICU_DEFAULT_DATA_DIR
881
Steven R. Loomisac2857b2014-09-05 05:03:24882 // Initialize ICU.
Ben Noordhuisa8734af2017-01-28 12:27:02883 // If icu_data_dir is empty here, it will load the 'minimal' data.
Joyee Cheung9db9e7e2019-01-01 05:56:53884 if (!i18n::InitializeICUDirectory(per_process::cli_options->icu_data_dir)) {
Anna Henningseneb664c32019-01-06 21:55:09885 errors->push_back("could not initialize ICU "
886 "(check NODE_ICU_DATA or --icu-data-dir parameters)\n");
887 return 9;
Steven R. Loomisac2857b2014-09-05 05:03:24888 }
Joyee Cheung263d1372018-12-18 21:23:47889 per_process::metadata.versions.InitializeIntlVersions();
Steven R. Loomisac2857b2014-09-05 05:03:24890#endif
Tom Hughes78da9cb2010-10-18 22:50:56891
Joyee Cheungdfd7e992019-04-09 21:08:48892 NativeModuleEnv::InitializeCodeCache();
893
Cheng Zhao22e1aea2015-01-12 21:31:25894 // We should set node_is_initialized here instead of in node::Start,
895 // otherwise embedders using node::Init to initialize everything will not be
896 // able to set it and native modules will not load for them.
897 node_is_initialized = true;
Anna Henningseneb664c32019-01-06 21:55:09898 return 0;
Ben Noordhuis5866f1a2011-12-09 18:02:33899}
Ben Noordhuis356992f2011-11-22 16:10:09900
Anna Henningsen29a71ba2018-08-10 00:45:28901// TODO(addaleax): Deprecate and eventually remove this.
902void Init(int* argc,
903 const char** argv,
904 int* exec_argc,
905 const char*** exec_argv) {
906 std::vector<std::string> argv_(argv, argv + *argc); // NOLINT
907 std::vector<std::string> exec_argv_;
Anna Henningseneb664c32019-01-06 21:55:09908 std::vector<std::string> errors;
Anna Henningsen29a71ba2018-08-10 00:45:28909
Anna Henningseneb664c32019-01-06 21:55:09910 // This (approximately) duplicates some logic that has been moved to
911 // node::Start(), with the difference that here we explicitly call `exit()`.
Joyee Cheung963ee0b2019-03-07 13:52:31912 int exit_code = InitializeNodeWithArgs(&argv_, &exec_argv_, &errors);
Anna Henningseneb664c32019-01-06 21:55:09913
914 for (const std::string& error : errors)
915 fprintf(stderr, "%s: %s\n", argv_.at(0).c_str(), error.c_str());
916 if (exit_code != 0) exit(exit_code);
917
918 if (per_process::cli_options->print_version) {
919 printf("%s\n", NODE_VERSION);
920 exit(0);
921 }
922
Joyee Cheung403c84a2019-02-03 03:47:26923 if (per_process::cli_options->print_bash_completion) {
924 std::string completion = options_parser::GetBashCompletion();
925 printf("%s\n", completion.c_str());
926 exit(0);
927 }
928
Anna Henningseneb664c32019-01-06 21:55:09929 if (per_process::cli_options->print_v8_help) {
Michaƫl Zasso94e980c2019-07-20 11:35:59930 // Doesn't return.
931 V8::SetFlagsFromString("--help", static_cast<size_t>(6));
Anna Henningseneb664c32019-01-06 21:55:09932 UNREACHABLE();
933 }
Anna Henningsen29a71ba2018-08-10 00:45:28934
935 *argc = argv_.size();
936 *exec_argc = exec_argv_.size();
937 // These leak memory, because, in the original code of this function, no
938 // extra allocations were visible. This should be okay because this function
939 // is only supposed to be called once per process, though.
940 *exec_argv = Malloc<const char*>(*exec_argc);
941 for (int i = 0; i < *exec_argc; ++i)
942 (*exec_argv)[i] = strdup(exec_argv_[i].c_str());
943 for (int i = 0; i < *argc; ++i)
944 argv[i] = strdup(argv_[i].c_str());
945}
Ben Noordhuis5866f1a2011-12-09 18:02:33946
Joyee Cheung5356b4a2019-04-14 09:46:52947InitializationResult InitializeOncePerProcess(int argc, char** argv) {
Joyee Cheung51bc55f2020-02-20 09:22:48948 // Initialized the enabled list for Debug() calls with system
949 // environment variables.
950 per_process::enabled_debug_list.Parse(nullptr);
951
Ben Noordhuis58727052019-05-24 14:11:19952 atexit(ResetStdio);
Ben Noordhuis5756f922015-01-26 22:15:20953 PlatformInit();
954
Ben Noordhuis5fdff382014-10-11 14:52:07955 CHECK_GT(argc, 0);
Micheil Smith19fd5302012-03-05 17:53:15956
Ben Noordhuis185c5152013-09-02 14:42:01957 // Hack around with the argv pointer. Used for process.title = "blah".
Ben Noordhuis1a979982012-03-15 22:10:32958 argv = uv_setup_args(argc, argv);
959
Joyee Cheung5356b4a2019-04-14 09:46:52960 InitializationResult result;
961 result.args = std::vector<std::string>(argv, argv + argc);
Anna Henningseneb664c32019-01-06 21:55:09962 std::vector<std::string> errors;
Joyee Cheung5356b4a2019-04-14 09:46:52963
Anna Henningsen29a71ba2018-08-10 00:45:28964 // This needs to run *before* V8::Initialize().
Anna Henningseneb664c32019-01-06 21:55:09965 {
Joyee Cheung5356b4a2019-04-14 09:46:52966 result.exit_code =
967 InitializeNodeWithArgs(&(result.args), &(result.exec_args), &errors);
Anna Henningseneb664c32019-01-06 21:55:09968 for (const std::string& error : errors)
Joyee Cheung5356b4a2019-04-14 09:46:52969 fprintf(stderr, "%s: %s\n", result.args.at(0).c_str(), error.c_str());
970 if (result.exit_code != 0) {
971 result.early_return = true;
972 return result;
973 }
Anna Henningseneb664c32019-01-06 21:55:09974 }
Ben Noordhuis5866f1a2011-12-09 18:02:33975
Gabriel Schulhof89521052019-12-13 19:59:37976 if (per_process::cli_options->use_largepages == "on" ||
977 per_process::cli_options->use_largepages == "silent") {
Gabriel Schulhof0dff8512020-02-21 16:26:29978 int result = node::MapStaticCodeToLargePages();
979 if (per_process::cli_options->use_largepages == "on" && result != 0) {
980 fprintf(stderr, "%s\n", node::LargePagesError(result));
Gabriel Schulhof89521052019-12-13 19:59:37981 }
982 }
Gabriel Schulhof89521052019-12-13 19:59:37983
Joyee Cheung963ee0b2019-03-07 13:52:31984 if (per_process::cli_options->print_version) {
985 printf("%s\n", NODE_VERSION);
Joyee Cheung5356b4a2019-04-14 09:46:52986 result.exit_code = 0;
987 result.early_return = true;
988 return result;
Joyee Cheung963ee0b2019-03-07 13:52:31989 }
990
Joyee Cheung403c84a2019-02-03 03:47:26991 if (per_process::cli_options->print_bash_completion) {
992 std::string completion = options_parser::GetBashCompletion();
993 printf("%s\n", completion.c_str());
994 exit(0);
995 }
996
Joyee Cheung963ee0b2019-03-07 13:52:31997 if (per_process::cli_options->print_v8_help) {
Michaƫl Zasso94e980c2019-07-20 11:35:59998 // Doesn't return.
999 V8::SetFlagsFromString("--help", static_cast<size_t>(6));
Joyee Cheung963ee0b2019-03-07 13:52:311000 UNREACHABLE();
1001 }
1002
Ben Noordhuis7ac23912013-09-20 20:01:491003#if HAVE_OPENSSL
Ben Noordhuisa8734af2017-01-28 12:27:021004 {
1005 std::string extra_ca_certs;
Joyee Cheung321e2962018-12-15 19:13:121006 if (credentials::SafeGetenv("NODE_EXTRA_CA_CERTS", &extra_ca_certs))
Ben Noordhuisa8734af2017-01-28 12:27:021007 crypto::UseExtraCaCerts(extra_ca_certs);
1008 }
Stefan Budeanu7c48cb52016-01-22 23:10:091009#ifdef NODE_FIPS_MODE
1010 // In the case of FIPS builds we should make sure
1011 // the random source is properly initialized first.
1012 OPENSSL_init();
1013#endif // NODE_FIPS_MODE
Ben Noordhuis7ac23912013-09-20 20:01:491014 // V8 on Windows doesn't have a good source of entropy. Seed it from
1015 // OpenSSL's pool.
1016 V8::SetEntropySource(crypto::EntropySource);
Ben Noordhuisa8734af2017-01-28 12:27:021017#endif // HAVE_OPENSSL
Ben Noordhuis7ac23912013-09-20 20:01:491018
Ben Noordhuis93b0e392020-01-07 13:18:561019 per_process::v8_platform.Initialize(
1020 per_process::cli_options->v8_thread_pool_size);
Ben Noordhuis75ea5662013-09-23 12:27:261021 V8::Initialize();
Daniel Beveniuscae41822018-02-23 14:42:201022 performance::performance_v8_start = PERFORMANCE_NOW();
Joyee Cheung9db9e7e2019-01-01 05:56:531023 per_process::v8_initialized = true;
Joyee Cheung5356b4a2019-04-14 09:46:521024 return result;
1025}
Joyee Cheungcab1dc52019-04-14 06:41:041026
Joyee Cheung5356b4a2019-04-14 09:46:521027void TearDownOncePerProcess() {
Joyee Cheung9db9e7e2019-01-01 05:56:531028 per_process::v8_initialized = false;
Ryan27b268b2009-06-17 13:05:441029 V8::Dispose();
Igor Zinkovskya58b6432011-07-07 20:54:301030
Matt Loring9e086952017-03-13 22:17:571031 // uv_run cannot be called from the time before the beforeExit callback
1032 // runs until the program exits unless the event loop has any referenced
1033 // handles after beforeExit terminates. This prevents unrefed timers
1034 // that happen to terminate during shutdown from being run unsafely.
1035 // Since uv_run cannot be called, uv_async handles held by the platform
1036 // will never be fully cleaned up.
Joyee Cheung99c32432019-01-16 18:34:431037 per_process::v8_platform.Dispose();
Joyee Cheung5356b4a2019-04-14 09:46:521038}
Ben Noordhuis4a801c22015-04-02 21:51:011039
Joyee Cheung5356b4a2019-04-14 09:46:521040int Start(int argc, char** argv) {
1041 InitializationResult result = InitializeOncePerProcess(argc, argv);
1042 if (result.early_return) {
1043 return result.exit_code;
1044 }
1045
1046 {
Joyee Cheung70d887e2019-04-19 04:50:381047 Isolate::CreateParams params;
Joyee Cheung581bddc2019-07-05 18:43:271048 const std::vector<size_t>* indexes = nullptr;
1049 std::vector<intptr_t> external_references;
1050
1051 bool force_no_snapshot =
1052 per_process::cli_options->per_isolate->no_node_snapshot;
1053 if (!force_no_snapshot) {
1054 v8::StartupData* blob = NodeMainInstance::GetEmbeddedSnapshotBlob();
1055 if (blob != nullptr) {
1056 // TODO(joyeecheung): collect external references and set it in
1057 // params.external_references.
1058 external_references.push_back(reinterpret_cast<intptr_t>(nullptr));
1059 params.external_references = external_references.data();
1060 params.snapshot_blob = blob;
1061 indexes = NodeMainInstance::GetIsolateDataIndexes();
1062 }
Joyee Cheungbf5dade2019-04-18 14:09:281063 }
1064
Joyee Cheung70d887e2019-04-19 04:50:381065 NodeMainInstance main_instance(&params,
1066 uv_default_loop(),
1067 per_process::v8_platform.Platform(),
1068 result.args,
Joyee Cheungbf5dade2019-04-18 14:09:281069 result.exec_args,
1070 indexes);
Joyee Cheung5356b4a2019-04-14 09:46:521071 result.exit_code = main_instance.Run();
1072 }
1073
1074 TearDownOncePerProcess();
1075 return result.exit_code;
Ryan19478ed2009-03-03 00:56:151076}
Ryan Dahl124fbed2010-09-19 20:13:571077
Gireesh Punathild35af562018-06-12 13:01:461078int Stop(Environment* env) {
Anna Henningsenf6215362020-04-02 21:40:251079 env->ExitEnv();
Gireesh Punathild35af562018-06-12 13:01:461080 return 0;
1081}
1082
Ryan Dahl124fbed2010-09-19 20:13:571083} // namespace node
Eugene Ostroukhov3f48ab32017-04-25 21:55:551084
1085#if !HAVE_INSPECTOR
Daniel Beveniusebbf3932018-03-23 08:38:161086void Initialize() {}
Eugene Ostroukhov3f48ab32017-04-25 21:55:551087
Beni von Cheni05002372018-12-10 03:12:391088NODE_MODULE_CONTEXT_AWARE_INTERNAL(inspector, Initialize)
Eugene Ostroukhov3f48ab32017-04-25 21:55:551089#endif // !HAVE_INSPECTOR