GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage-daily/nodes/benchmark/out/../src/node.cc Lines: 369 424 87.0 %
Date: 2019-09-15 22:29:17 Branches: 240 348 69.0 %

Line Branch Exec Source
1
// 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
22
#include "node.h"
23
24
// ========== local headers ==========
25
26
#include "debug_utils.h"
27
#include "env-inl.h"
28
#include "memory_tracker-inl.h"
29
#include "node_binding.h"
30
#include "node_internals.h"
31
#include "node_main_instance.h"
32
#include "node_metadata.h"
33
#include "node_native_module_env.h"
34
#include "node_options-inl.h"
35
#include "node_perf.h"
36
#include "node_process.h"
37
#include "node_revert.h"
38
#include "node_v8_platform-inl.h"
39
#include "node_version.h"
40
41
#if HAVE_OPENSSL
42
#include "node_crypto.h"
43
#endif
44
45
#if defined(NODE_HAVE_I18N_SUPPORT)
46
#include "node_i18n.h"
47
#endif
48
49
#if HAVE_INSPECTOR
50
#include "inspector_agent.h"
51
#include "inspector_io.h"
52
#endif
53
54
#if defined HAVE_DTRACE || defined HAVE_ETW
55
#include "node_dtrace.h"
56
#endif
57
58
#if NODE_USE_V8_PLATFORM
59
#include "libplatform/libplatform.h"
60
#endif  // NODE_USE_V8_PLATFORM
61
#include "v8-profiler.h"
62
63
#if HAVE_INSPECTOR
64
#include "inspector/worker_inspector.h"  // ParentInspectorHandle
65
#endif
66
67
#ifdef NODE_ENABLE_LARGE_CODE_PAGES
68
#include "large_pages/node_large_page.h"
69
#endif
70
71
#ifdef NODE_REPORT
72
#include "node_report.h"
73
#endif
74
75
#if defined(__APPLE__) || defined(__linux__)
76
#define NODE_USE_V8_WASM_TRAP_HANDLER 1
77
#else
78
#define NODE_USE_V8_WASM_TRAP_HANDLER 0
79
#endif
80
81
#if NODE_USE_V8_WASM_TRAP_HANDLER
82
#include <atomic>
83
#include "v8-wasm-trap-handler-posix.h"
84
#endif  // NODE_USE_V8_WASM_TRAP_HANDLER
85
86
// ========== global C headers ==========
87
88
#include <fcntl.h>  // _O_RDWR
89
#include <sys/types.h>
90
91
#if defined(NODE_HAVE_I18N_SUPPORT)
92
#include <unicode/uvernum.h>
93
#endif
94
95
96
#if defined(LEAK_SANITIZER)
97
#include <sanitizer/lsan_interface.h>
98
#endif
99
100
#if defined(_MSC_VER)
101
#include <direct.h>
102
#include <io.h>
103
#define STDIN_FILENO 0
104
#else
105
#include <pthread.h>
106
#include <sys/resource.h>  // getrlimit, setrlimit
107
#include <termios.h>       // tcgetattr, tcsetattr
108
#include <unistd.h>        // STDIN_FILENO, STDERR_FILENO
109
#endif
110
111
// ========== global C++ headers ==========
112
113
#include <cerrno>
114
#include <climits>  // PATH_MAX
115
#include <csignal>
116
#include <cstdio>
117
#include <cstdlib>
118
#include <cstring>
119
120
#include <string>
121
#include <vector>
122
123
namespace node {
124
125
using native_module::NativeModuleEnv;
126
using options_parser::kAllowedInEnvironment;
127
using options_parser::kDisallowedInEnvironment;
128
129
using v8::Boolean;
130
using v8::EscapableHandleScope;
131
using v8::Function;
132
using v8::FunctionCallbackInfo;
133
using v8::HandleScope;
134
using v8::Isolate;
135
using v8::Local;
136
using v8::Maybe;
137
using v8::MaybeLocal;
138
using v8::Object;
139
using v8::String;
140
using v8::Undefined;
141
using v8::V8;
142
using v8::Value;
143
144
namespace per_process {
145
146
// node_revert.h
147
// Bit flag used to track security reverts.
148
unsigned int reverted_cve = 0;
149
150
// util.h
151
// Tells whether the per-process V8::Initialize() is called and
152
// if it is safe to call v8::Isolate::GetCurrent().
153
bool v8_initialized = false;
154
155
// node_internals.h
156
// process-relative uptime base in nanoseconds, initialized in node::Start()
157
uint64_t node_start_time;
158
// Tells whether --prof is passed.
159
bool v8_is_profiling = false;
160
161
// node_v8_platform-inl.h
162
5034
struct V8Platform v8_platform;
163
}  // namespace per_process
164
165
#ifdef __POSIX__
166
static const unsigned kMaxSignal = 32;
167
#endif
168
169
4816
void WaitForInspectorDisconnect(Environment* env) {
170
#if HAVE_INSPECTOR
171
4816
  profiler::EndStartedProfilers(env);
172
173
4816
  if (env->inspector_agent()->IsActive()) {
174
    // Restore signal dispositions, the app is done and is no longer
175
    // capable of handling signals.
176
#if defined(__POSIX__) && !defined(NODE_SHARED_MODE)
177
    struct sigaction act;
178
4812
    memset(&act, 0, sizeof(act));
179
153984
    for (unsigned nr = 1; nr < kMaxSignal; nr += 1) {
180

149172
      if (nr == SIGKILL || nr == SIGSTOP || nr == SIGPROF)
181
14436
        continue;
182
134736
      act.sa_handler = (nr == SIGPIPE) ? SIG_IGN : SIG_DFL;
183
134736
      CHECK_EQ(0, sigaction(nr, &act, nullptr));
184
    }
185
#endif
186
4812
    env->inspector_agent()->WaitForDisconnect();
187
  }
188
#endif
189
4816
}
190
191
#ifdef __POSIX__
192
void SignalExit(int signo, siginfo_t* info, void* ucontext) {
193
  ResetStdio();
194
  raise(signo);
195
}
196
#endif  // __POSIX__
197
198
15538
MaybeLocal<Value> ExecuteBootstrapper(Environment* env,
199
                                      const char* id,
200
                                      std::vector<Local<String>>* parameters,
201
                                      std::vector<Local<Value>>* arguments) {
202
15538
  EscapableHandleScope scope(env->isolate());
203
  MaybeLocal<Function> maybe_fn =
204
15538
      NativeModuleEnv::LookupAndCompile(env->context(), id, parameters, env);
205
206
15539
  if (maybe_fn.IsEmpty()) {
207
    return MaybeLocal<Value>();
208
  }
209
210
15539
  Local<Function> fn = maybe_fn.ToLocalChecked();
211
  MaybeLocal<Value> result = fn->Call(env->context(),
212
                                      Undefined(env->isolate()),
213
15539
                                      arguments->size(),
214
62156
                                      arguments->data());
215
216
  // If there was an error during bootstrap, it must be unrecoverable
217
  // (e.g. max call stack exceeded). Clear the stack so that the
218
  // AsyncCallbackScope destructor doesn't fail on the id check.
219
  // There are only two ways to have a stack size > 1: 1) the user manually
220
  // called MakeCallback or 2) user awaited during bootstrap, which triggered
221
  // _tickCallback().
222
15320
  if (result.IsEmpty()) {
223
35
    env->async_hooks()->clear_async_id_stack();
224
  }
225
226
15320
  return scope.EscapeMaybe(result);
227
}
228
229
#if HAVE_INSPECTOR && NODE_USE_V8_PLATFORM
230
5182
int Environment::InitializeInspector(
231
    inspector::ParentInspectorHandle* parent_handle) {
232
5182
  std::string inspector_path;
233
5183
  if (parent_handle != nullptr) {
234
    DCHECK(!is_main_thread());
235
209
    inspector_path = parent_handle->url();
236
    inspector_agent_->SetParentHandle(
237
209
        std::unique_ptr<inspector::ParentInspectorHandle>(parent_handle));
238
  } else {
239
4974
    inspector_path = argv_.size() > 1 ? argv_[1].c_str() : "";
240
  }
241
242
5182
  CHECK(!inspector_agent_->IsListening());
243
  // Inspector agent can't fail to start, but if it was configured to listen
244
  // right away on the websocket port and fails to bind/etc, this will return
245
  // false.
246
  inspector_agent_->Start(inspector_path,
247
5183
                          options_->debug_options(),
248
                          inspector_host_port(),
249
10364
                          is_main_thread());
250

5262
  if (options_->debug_options().inspector_enabled &&
251
79
      !inspector_agent_->IsListening()) {
252
5
    return 12;  // Signal internal error
253
  }
254
255
5178
  profiler::StartProfilers(this);
256
257
5178
  if (inspector_agent_->options().break_node_first_line) {
258
    inspector_agent_->PauseOnNextJavascriptStatement("Break at bootstrap");
259
  }
260
261
5178
  return 0;
262
}
263
#endif  // HAVE_INSPECTOR && NODE_USE_V8_PLATFORM
264
265
5182
void Environment::InitializeDiagnostics() {
266
  isolate_->GetHeapProfiler()->AddBuildEmbedderGraphCallback(
267
5182
      Environment::BuildEmbedderGraph, this);
268
269
#if defined HAVE_DTRACE || defined HAVE_ETW
270
  InitDTrace(this);
271
#endif
272
5183
}
273
274
5182
MaybeLocal<Value> Environment::BootstrapInternalLoaders() {
275
5182
  EscapableHandleScope scope(isolate_);
276
277
  // Create binding loaders
278
  std::vector<Local<String>> loaders_params = {
279
      process_string(),
280
5182
      FIXED_ONE_BYTE_STRING(isolate_, "getLinkedBinding"),
281
5182
      FIXED_ONE_BYTE_STRING(isolate_, "getInternalBinding"),
282
20728
      primordials_string()};
283
  std::vector<Local<Value>> loaders_args = {
284
      process_object(),
285
5182
      NewFunctionTemplate(binding::GetLinkedBinding)
286
20728
          ->GetFunction(context())
287
          .ToLocalChecked(),
288
5182
      NewFunctionTemplate(binding::GetInternalBinding)
289
20727
          ->GetFunction(context())
290
          .ToLocalChecked(),
291
36273
      primordials()};
292
293
  // Bootstrap internal loaders
294
  Local<Value> loader_exports;
295
10364
  if (!ExecuteBootstrapper(
296
           this, "internal/bootstrap/loaders", &loaders_params, &loaders_args)
297
15546
           .ToLocal(&loader_exports)) {
298
1
    return MaybeLocal<Value>();
299
  }
300
5181
  CHECK(loader_exports->IsObject());
301
5181
  Local<Object> loader_exports_obj = loader_exports.As<Object>();
302
  Local<Value> internal_binding_loader =
303
20724
      loader_exports_obj->Get(context(), internal_binding_string())
304
10362
          .ToLocalChecked();
305
5181
  CHECK(internal_binding_loader->IsFunction());
306
5181
  set_internal_binding_loader(internal_binding_loader.As<Function>());
307
  Local<Value> require =
308
20724
      loader_exports_obj->Get(context(), require_string()).ToLocalChecked();
309
5181
  CHECK(require->IsFunction());
310
5181
  set_native_module_require(require.As<Function>());
311
312
5181
  return scope.Escape(loader_exports);
313
}
314
315
5181
MaybeLocal<Value> Environment::BootstrapNode() {
316
5181
  EscapableHandleScope scope(isolate_);
317
318
10362
  Local<Object> global = context()->Global();
319
  // TODO(joyeecheung): this can be done in JS land now.
320
20724
  global->Set(context(), FIXED_ONE_BYTE_STRING(isolate_, "global"), global)
321
10362
      .Check();
322
323
  // process, require, internalBinding, isMainThread,
324
  // ownsProcessState, primordials
325
  std::vector<Local<String>> node_params = {
326
      process_string(),
327
      require_string(),
328
      internal_binding_string(),
329
5181
      FIXED_ONE_BYTE_STRING(isolate_, "isMainThread"),
330
5181
      FIXED_ONE_BYTE_STRING(isolate_, "ownsProcessState"),
331
20724
      primordials_string()};
332
  std::vector<Local<Value>> node_args = {
333
      process_object(),
334
      native_module_require(),
335
      internal_binding_loader(),
336
5181
      Boolean::New(isolate_, is_main_thread()),
337
5181
      Boolean::New(isolate_, owns_process_state()),
338
41448
      primordials()};
339
340
  MaybeLocal<Value> result = ExecuteBootstrapper(
341
5181
      this, "internal/bootstrap/node", &node_params, &node_args);
342
343
  Local<Object> env_var_proxy;
344
15543
  if (!CreateEnvVarProxy(context(), isolate_, as_callback_data())
345

36267
           .ToLocal(&env_var_proxy) ||
346
      process_object()
347
          ->Set(
348

20724
              context(), FIXED_ONE_BYTE_STRING(isolate_, "env"), env_var_proxy)
349
31086
          .IsNothing()) {
350
    return MaybeLocal<Value>();
351
  }
352
353
5181
  return scope.EscapeMaybe(result);
354
}
355
356
5182
MaybeLocal<Value> Environment::RunBootstrapping() {
357
5182
  EscapableHandleScope scope(isolate_);
358
359
5182
  CHECK(!has_run_bootstrapping_code());
360
361
10364
  if (BootstrapInternalLoaders().IsEmpty()) {
362
1
    return MaybeLocal<Value>();
363
  }
364
365
  Local<Value> result;
366
10362
  if (!BootstrapNode().ToLocal(&result)) {
367
5
    return MaybeLocal<Value>();
368
  }
369
370
  // Make sure that no request or handle is created during bootstrap -
371
  // if necessary those should be done in pre-execution.
372
  // TODO(joyeecheung): print handles/requests before aborting
373
5176
  CHECK(req_wrap_queue()->IsEmpty());
374
5176
  CHECK(handle_wrap_queue()->IsEmpty());
375
376
5176
  set_has_run_bootstrapping_code(true);
377
378
5176
  return scope.Escape(result);
379
}
380
381
5161
void MarkBootstrapComplete(const FunctionCallbackInfo<Value>& args) {
382
5161
  Environment* env = Environment::GetCurrent(args);
383
  env->performance_state()->Mark(
384
5161
      performance::NODE_PERFORMANCE_MILESTONE_BOOTSTRAP_COMPLETE);
385
5161
}
386
387
5176
MaybeLocal<Value> StartExecution(Environment* env, const char* main_script_id) {
388
5176
  EscapableHandleScope scope(env->isolate());
389
5176
  CHECK_NOT_NULL(main_script_id);
390
391
  std::vector<Local<String>> parameters = {
392
      env->process_string(),
393
      env->require_string(),
394
      env->internal_binding_string(),
395
      env->primordials_string(),
396
10101
      FIXED_ONE_BYTE_STRING(env->isolate(), "markBootstrapComplete")};
397
398
  std::vector<Local<Value>> arguments = {
399
      env->process_object(),
400
      env->native_module_require(),
401
      env->internal_binding_loader(),
402
      env->primordials(),
403
5176
      env->NewFunctionTemplate(MarkBootstrapComplete)
404
20704
          ->GetFunction(env->context())
405
35981
          .ToLocalChecked()};
406
407
  Local<Value> result;
408
15026
  if (!ExecuteBootstrapper(env, main_script_id, &parameters, &arguments)
409

30055
           .ToLocal(&result) ||
410
4928
      !task_queue::RunNextTicksNative(env)) {
411
44
    return MaybeLocal<Value>();
412
  }
413
4881
  return scope.Escape(result);
414
}
415
416
4973
MaybeLocal<Value> StartMainThreadExecution(Environment* env) {
417
  // To allow people to extend Node in different ways, this hook allows
418
  // one to drop a file lib/_third_party_main.js into the build
419
  // directory which will be executed instead of Node's normal loading.
420
4973
  if (NativeModuleEnv::Exists("_third_party_main")) {
421
    return StartExecution(env, "internal/main/run_third_party_main");
422
  }
423
424
4973
  std::string first_argv;
425
4973
  if (env->argv().size() > 1) {
426
4614
    first_argv = env->argv()[1];
427
  }
428
429

4973
  if (first_argv == "inspect" || first_argv == "debug") {
430
4
    return StartExecution(env, "internal/main/inspect");
431
  }
432
433
4969
  if (per_process::cli_options->print_help) {
434
1
    return StartExecution(env, "internal/main/print_help");
435
  }
436
437
4968
  if (per_process::cli_options->print_bash_completion) {
438
1
    return StartExecution(env, "internal/main/print_bash_completion");
439
  }
440
441
4967
  if (env->options()->prof_process) {
442
360
    return StartExecution(env, "internal/main/prof_process");
443
  }
444
445
  // -e/--eval without -i/--interactive
446


4607
  if (env->options()->has_eval_string && !env->options()->force_repl) {
447
334
    return StartExecution(env, "internal/main/eval_string");
448
  }
449
450
4273
  if (env->options()->syntax_check_only) {
451
34
    return StartExecution(env, "internal/main/check_syntax");
452
  }
453
454

4239
  if (!first_argv.empty() && first_argv != "-") {
455
4206
    return StartExecution(env, "internal/main/run_main_module");
456
  }
457
458


33
  if (env->options()->force_repl || uv_guess_handle(STDIN_FILENO) == UV_TTY) {
459
16
    return StartExecution(env, "internal/main/repl");
460
  }
461
462
17
  return StartExecution(env, "internal/main/eval_stdin");
463
}
464
465
4973
void LoadEnvironment(Environment* env) {
466
4973
  CHECK(env->is_main_thread());
467
  // TODO(joyeecheung): Not all of the execution modes in
468
  // StartMainThreadExecution() make sense for embedders. Pick the
469
  // useful ones out, and allow embedders to customize the entry
470
  // point more directly without using _third_party_main.js
471
4973
  USE(StartMainThreadExecution(env));
472
4722
}
473
474
#ifdef __POSIX__
475
typedef void (*sigaction_cb)(int signo, siginfo_t* info, void* ucontext);
476
#endif
477
#if NODE_USE_V8_WASM_TRAP_HANDLER
478
5034
static std::atomic<sigaction_cb> previous_sigsegv_action;
479
480
6
void TrapWebAssemblyOrContinue(int signo, siginfo_t* info, void* ucontext) {
481
6
  if (!v8::TryHandleWebAssemblyTrapPosix(signo, info, ucontext)) {
482
6
    sigaction_cb prev = previous_sigsegv_action.load();
483
6
    if (prev != nullptr) {
484
6
      prev(signo, info, ucontext);
485
    } else {
486
      // Reset to the default signal handler, i.e. cause a hard crash.
487
      struct sigaction sa;
488
      memset(&sa, 0, sizeof(sa));
489
      sa.sa_handler = SIG_DFL;
490
      CHECK_EQ(sigaction(signo, &sa, nullptr), 0);
491
492
      ResetStdio();
493
      raise(signo);
494
    }
495
  }
496
6
}
497
#endif  // NODE_USE_V8_WASM_TRAP_HANDLER
498
499
#ifdef __POSIX__
500
15248
void RegisterSignalHandler(int signal,
501
                           sigaction_cb handler,
502
                           bool reset_handler) {
503
15248
  CHECK_NOT_NULL(handler);
504
#if NODE_USE_V8_WASM_TRAP_HANDLER
505
15248
  if (signal == SIGSEGV) {
506
4
    CHECK(previous_sigsegv_action.is_lock_free());
507
4
    CHECK(!reset_handler);
508
4
    previous_sigsegv_action.store(handler);
509
4
    return;
510
  }
511
#endif  // NODE_USE_V8_WASM_TRAP_HANDLER
512
  struct sigaction sa;
513
15244
  memset(&sa, 0, sizeof(sa));
514
15244
  sa.sa_sigaction = handler;
515
15244
  sa.sa_flags = reset_handler ? SA_RESETHAND : 0;
516
15244
  sigfillset(&sa.sa_mask);
517
15244
  CHECK_EQ(sigaction(signal, &sa, nullptr), 0);
518
}
519
520
#endif  // __POSIX__
521
522
#ifdef __POSIX__
523
static struct {
524
  int flags;
525
  bool isatty;
526
  struct stat stat;
527
  struct termios termios;
528
} stdio[1 + STDERR_FILENO];
529
#endif  // __POSIX__
530
531
532
5033
inline void PlatformInit() {
533
#ifdef __POSIX__
534
#if HAVE_INSPECTOR
535
  sigset_t sigmask;
536
5033
  sigemptyset(&sigmask);
537
5033
  sigaddset(&sigmask, SIGUSR1);
538
5033
  const int err = pthread_sigmask(SIG_SETMASK, &sigmask, nullptr);
539
#endif  // HAVE_INSPECTOR
540
541
  // Make sure file descriptors 0-2 are valid before we start logging anything.
542
20132
  for (auto& s : stdio) {
543
15099
    const int fd = &s - stdio;
544
15099
    if (fstat(fd, &s.stat) == 0)
545
15097
      continue;
546
    // Anything but EBADF means something is seriously wrong.  We don't
547
    // have to special-case EINTR, fstat() is not interruptible.
548
2
    if (errno != EBADF)
549
      ABORT();
550
2
    if (fd != open("/dev/null", O_RDWR))
551
      ABORT();
552
2
    if (fstat(fd, &s.stat) != 0)
553
      ABORT();
554
  }
555
556
#if HAVE_INSPECTOR
557
5033
  CHECK_EQ(err, 0);
558
#endif  // HAVE_INSPECTOR
559
560
#ifndef NODE_SHARED_MODE
561
  // Restore signal dispositions, the parent process may have changed them.
562
  struct sigaction act;
563
5033
  memset(&act, 0, sizeof(act));
564
565
  // The hard-coded upper limit is because NSIG is not very reliable; on Linux,
566
  // it evaluates to 32, 34 or 64, depending on whether RT signals are enabled.
567
  // Counting up to SIGRTMIN doesn't work for the same reason.
568
161056
  for (unsigned nr = 1; nr < kMaxSignal; nr += 1) {
569

156023
    if (nr == SIGKILL || nr == SIGSTOP)
570
10066
      continue;
571

145957
    act.sa_handler = (nr == SIGPIPE || nr == SIGXFSZ) ? SIG_IGN : SIG_DFL;
572
145957
    CHECK_EQ(0, sigaction(nr, &act, nullptr));
573
  }
574
#endif  // !NODE_SHARED_MODE
575
576
  // Record the state of the stdio file descriptors so we can restore it
577
  // on exit.  Needs to happen before installing signal handlers because
578
  // they make use of that information.
579
20132
  for (auto& s : stdio) {
580
15099
    const int fd = &s - stdio;
581
    int err;
582
583
15099
    do
584
15099
      s.flags = fcntl(fd, F_GETFL);
585
15099
    while (s.flags == -1 && errno == EINTR);  // NOLINT
586
15099
    CHECK_NE(s.flags, -1);
587
588
15099
    if (!isatty(fd)) continue;
589
96
    s.isatty = true;
590
591
96
    do
592
96
      err = tcgetattr(fd, &s.termios);
593
96
    while (err == -1 && errno == EINTR);  // NOLINT
594
96
    CHECK_EQ(err, 0);
595
  }
596
597
5033
  RegisterSignalHandler(SIGINT, SignalExit, true);
598
5033
  RegisterSignalHandler(SIGTERM, SignalExit, true);
599
600
#if NODE_USE_V8_WASM_TRAP_HANDLER
601
  // Tell V8 to disable emitting WebAssembly
602
  // memory bounds checks. This means that we have
603
  // to catch the SIGSEGV in TrapWebAssemblyOrContinue
604
  // and pass the signal context to V8.
605
  {
606
    struct sigaction sa;
607
5033
    memset(&sa, 0, sizeof(sa));
608
5033
    sa.sa_sigaction = TrapWebAssemblyOrContinue;
609
5033
    CHECK_EQ(sigaction(SIGSEGV, &sa, nullptr), 0);
610
  }
611
5033
  V8::EnableWebAssemblyTrapHandler(false);
612
#endif  // NODE_USE_V8_WASM_TRAP_HANDLER
613
614
  // Raise the open file descriptor limit.
615
  struct rlimit lim;
616

5033
  if (getrlimit(RLIMIT_NOFILE, &lim) == 0 && lim.rlim_cur != lim.rlim_max) {
617
    // Do a binary search for the limit.
618
    rlim_t min = lim.rlim_cur;
619
    rlim_t max = 1 << 20;
620
    // But if there's a defined upper bound, don't search, just set it.
621
    if (lim.rlim_max != RLIM_INFINITY) {
622
      min = lim.rlim_max;
623
      max = lim.rlim_max;
624
    }
625
    do {
626
      lim.rlim_cur = min + (max - min) / 2;
627
      if (setrlimit(RLIMIT_NOFILE, &lim)) {
628
        max = lim.rlim_cur;
629
      } else {
630
        min = lim.rlim_cur;
631
      }
632
    } while (min + 1 < max);
633
  }
634
#endif  // __POSIX__
635
#ifdef _WIN32
636
  for (int fd = 0; fd <= 2; ++fd) {
637
    auto handle = reinterpret_cast<HANDLE>(_get_osfhandle(fd));
638
    if (handle == INVALID_HANDLE_VALUE ||
639
        GetFileType(handle) == FILE_TYPE_UNKNOWN) {
640
      // Ignore _close result. If it fails or not depends on used Windows
641
      // version. We will just check _open result.
642
      _close(fd);
643
      if (fd != _open("nul", _O_RDWR))
644
        ABORT();
645
    }
646
  }
647
#endif  // _WIN32
648
5033
}
649
650
651
// Safe to call more than once and from signal handlers.
652
9613
void ResetStdio() {
653
9613
  uv_tty_reset_mode();
654
#ifdef __POSIX__
655
38452
  for (auto& s : stdio) {
656
28839
    const int fd = &s - stdio;
657
658
    struct stat tmp;
659
28839
    if (-1 == fstat(fd, &tmp)) {
660
      CHECK_EQ(errno, EBADF);  // Program closed file descriptor.
661
6
      continue;
662
    }
663
664
    bool is_same_file =
665

28839
        (s.stat.st_dev == tmp.st_dev && s.stat.st_ino == tmp.st_ino);
666
28839
    if (!is_same_file) continue;  // Program reopened file descriptor.
667
668
    int flags;
669
28833
    do
670
28833
      flags = fcntl(fd, F_GETFL);
671
28833
    while (flags == -1 && errno == EINTR);  // NOLINT
672
28833
    CHECK_NE(flags, -1);
673
674
    // Restore the O_NONBLOCK flag if it changed.
675
28833
    if (O_NONBLOCK & (flags ^ s.flags)) {
676
1117
      flags &= ~O_NONBLOCK;
677
1117
      flags |= s.flags & O_NONBLOCK;
678
679
      int err;
680
1117
      do
681
1117
        err = fcntl(fd, F_SETFL, flags);
682
1117
      while (err == -1 && errno == EINTR);  // NOLINT
683
1117
      CHECK_NE(err, -1);
684
    }
685
686
28833
    if (s.isatty) {
687
      sigset_t sa;
688
      int err;
689
690
      // We might be a background job that doesn't own the TTY so block SIGTTOU
691
      // before making the tcsetattr() call, otherwise that signal suspends us.
692
183
      sigemptyset(&sa);
693
183
      sigaddset(&sa, SIGTTOU);
694
695
183
      CHECK_EQ(0, pthread_sigmask(SIG_BLOCK, &sa, nullptr));
696
183
      do
697
183
        err = tcsetattr(fd, TCSANOW, &s.termios);
698
183
      while (err == -1 && errno == EINTR);  // NOLINT
699
183
      CHECK_EQ(0, pthread_sigmask(SIG_UNBLOCK, &sa, nullptr));
700
183
      CHECK_EQ(0, err);
701
    }
702
  }
703
#endif  // __POSIX__
704
9613
}
705
706
707
9899
int ProcessGlobalArgs(std::vector<std::string>* args,
708
                      std::vector<std::string>* exec_args,
709
                      std::vector<std::string>* errors,
710
                      bool is_env) {
711
  // Parse a few arguments which are specific to Node.
712
9899
  std::vector<std::string> v8_args;
713
714
19798
  Mutex::ScopedLock lock(per_process::cli_options_mutex);
715
  options_parser::Parse(
716
      args,
717
      exec_args,
718
      &v8_args,
719
      per_process::cli_options.get(),
720
      is_env ? kAllowedInEnvironment : kDisallowedInEnvironment,
721
9899
      errors);
722
723
9899
  if (!errors->empty()) return 9;
724
725
19718
  std::string revert_error;
726
9859
  for (const std::string& cve : per_process::cli_options->security_reverts) {
727
1
    Revert(cve.c_str(), &revert_error);
728
1
    if (!revert_error.empty()) {
729
1
      errors->emplace_back(std::move(revert_error));
730
1
      return 12;
731
    }
732
  }
733
734
19716
  auto env_opts = per_process::cli_options->per_isolate->per_env;
735
19716
  if (std::find(v8_args.begin(), v8_args.end(),
736


59097
                "--abort-on-uncaught-exception") != v8_args.end() ||
737
      std::find(v8_args.begin(), v8_args.end(),
738

39381
                "--abort_on_uncaught_exception") != v8_args.end()) {
739
20
    env_opts->abort_on_uncaught_exception = true;
740
  }
741
742
  // TODO(bnoordhuis) Intercept --prof arguments and start the CPU profiler
743
  // manually?  That would give us a little more control over its runtime
744
  // behavior but it could also interfere with the user's intentions in ways
745
  // we fail to anticipate.  Dillema.
746
9858
  if (std::find(v8_args.begin(), v8_args.end(), "--prof") != v8_args.end()) {
747
2
    per_process::v8_is_profiling = true;
748
  }
749
750
#ifdef __POSIX__
751
  // Block SIGPROF signals when sleeping in epoll_wait/kevent/etc.  Avoids the
752
  // performance penalty of frequent EINTR wakeups when the profiler is running.
753
  // Only do this for v8.log profiling, as it breaks v8::CpuProfiler users.
754
9858
  if (per_process::v8_is_profiling) {
755
2
    uv_loop_configure(uv_default_loop(), UV_LOOP_BLOCK_SIGNAL, SIGPROF);
756
  }
757
#endif
758
759
19716
  std::vector<char*> v8_args_as_char_ptr(v8_args.size());
760
9858
  if (v8_args.size() > 0) {
761
19849
    for (size_t i = 0; i < v8_args.size(); ++i)
762
9991
      v8_args_as_char_ptr[i] = &v8_args[i][0];
763
9858
    int argc = v8_args.size();
764
9858
    V8::SetFlagsFromCommandLine(&argc, &v8_args_as_char_ptr[0], true);
765
9858
    v8_args_as_char_ptr.resize(argc);
766
  }
767
768
  // Anything that's still in v8_argv is not a V8 or a node option.
769
9871
  for (size_t i = 1; i < v8_args_as_char_ptr.size(); i++)
770
13
    errors->push_back("bad option: " + std::string(v8_args_as_char_ptr[i]));
771
772
9858
  if (v8_args_as_char_ptr.size() > 1) return 9;
773
774
19746
  return 0;
775
}
776
777
static std::atomic_bool init_called{false};
778
779
5033
int InitializeNodeWithArgs(std::vector<std::string>* argv,
780
                           std::vector<std::string>* exec_argv,
781
                           std::vector<std::string>* errors) {
782
  // Make sure InitializeNodeWithArgs() is called only once.
783
5033
  CHECK(!init_called.exchange(true));
784
785
  // Initialize node_start_time to get relative uptime.
786
5033
  per_process::node_start_time = uv_hrtime();
787
788
  // Register built-in modules
789
5033
  binding::RegisterBuiltinModules();
790
791
  // Make inherited handles noninheritable.
792
5033
  uv_disable_stdio_inheritance();
793
794
#ifdef NODE_REPORT
795
  // Cache the original command line to be
796
  // used in diagnostic reports.
797
5033
  per_process::cli_options->cmdline = *argv;
798
#endif  //  NODE_REPORT
799
800
#if defined(NODE_V8_OPTIONS)
801
  // Should come before the call to V8::SetFlagsFromCommandLine()
802
  // so the user can disable a flag --foo at run-time by passing
803
  // --no_foo from the command line.
804
  V8::SetFlagsFromString(NODE_V8_OPTIONS, sizeof(NODE_V8_OPTIONS) - 1);
805
#endif
806
807
  std::shared_ptr<EnvironmentOptions> default_env_options =
808
5033
      per_process::cli_options->per_isolate->per_env;
809
  {
810
5033
    std::string text;
811
5033
    default_env_options->pending_deprecation =
812

5034
        credentials::SafeGetenv("NODE_PENDING_DEPRECATION", &text) &&
813
5034
        text[0] == '1';
814
  }
815
816
  // Allow for environment set preserving symlinks.
817
  {
818
5033
    std::string text;
819
5033
    default_env_options->preserve_symlinks =
820

5034
        credentials::SafeGetenv("NODE_PRESERVE_SYMLINKS", &text) &&
821
5034
        text[0] == '1';
822
  }
823
824
  {
825
5033
    std::string text;
826
5033
    default_env_options->preserve_symlinks_main =
827

5033
        credentials::SafeGetenv("NODE_PRESERVE_SYMLINKS_MAIN", &text) &&
828
5033
        text[0] == '1';
829
  }
830
831
5033
  if (default_env_options->redirect_warnings.empty()) {
832
    credentials::SafeGetenv("NODE_REDIRECT_WARNINGS",
833
5033
                            &default_env_options->redirect_warnings);
834
  }
835
836
#if HAVE_OPENSSL
837
5033
  std::string* openssl_config = &per_process::cli_options->openssl_config;
838
5033
  if (openssl_config->empty()) {
839
5033
    credentials::SafeGetenv("OPENSSL_CONF", openssl_config);
840
  }
841
#endif
842
843
#if !defined(NODE_WITHOUT_NODE_OPTIONS)
844
10066
  std::string node_options;
845
846
5033
  if (credentials::SafeGetenv("NODE_OPTIONS", &node_options)) {
847
4881
    std::vector<std::string> env_argv;
848
    // [0] is expected to be the program name, fill it in from the real argv.
849
4881
    env_argv.push_back(argv->at(0));
850
851
4881
    bool is_in_string = false;
852
4881
    bool will_start_new_arg = true;
853
14898
    for (std::string::size_type index = 0;
854
7449
         index < node_options.size();
855
         ++index) {
856
2568
      char c = node_options.at(index);
857
858
      // Backslashes escape the following character
859

2568
      if (c == '\\' && is_in_string) {
860
        if (index + 1 == node_options.size()) {
861
          errors->push_back("invalid value for NODE_OPTIONS "
862
                            "(invalid escape)\n");
863
          return 9;
864
        } else {
865
          c = node_options.at(++index);
866
        }
867

2568
      } else if (c == ' ' && !is_in_string) {
868
47
        will_start_new_arg = true;
869
47
        continue;
870
2521
      } else if (c == '"') {
871
4
        is_in_string = !is_in_string;
872
4
        continue;
873
      }
874
875
2517
      if (will_start_new_arg) {
876
99
        env_argv.push_back(std::string(1, c));
877
99
        will_start_new_arg = false;
878
      } else {
879
2418
        env_argv.back() += c;
880
      }
881
    }
882
883
4881
    if (is_in_string) {
884
      errors->push_back("invalid value for NODE_OPTIONS "
885
                        "(unterminated string)\n");
886
      return 9;
887
    }
888
889
4881
    const int exit_code = ProcessGlobalArgs(&env_argv, nullptr, errors, true);
890

4881
    if (exit_code != 0) return exit_code;
891
  }
892
#endif
893
894
5018
  const int exit_code = ProcessGlobalArgs(argv, exec_argv, errors, false);
895
5018
  if (exit_code != 0) return exit_code;
896
897
  // Set the process.title immediately after processing argv if --title is set.
898
4981
  if (!per_process::cli_options->title.empty())
899
2
    uv_set_process_title(per_process::cli_options->title.c_str());
900
901
#if defined(NODE_HAVE_I18N_SUPPORT)
902
  // If the parameter isn't given, use the env variable.
903
4981
  if (per_process::cli_options->icu_data_dir.empty())
904
    credentials::SafeGetenv("NODE_ICU_DATA",
905
4980
                            &per_process::cli_options->icu_data_dir);
906
  // Initialize ICU.
907
  // If icu_data_dir is empty here, it will load the 'minimal' data.
908
4981
  if (!i18n::InitializeICUDirectory(per_process::cli_options->icu_data_dir)) {
909
    errors->push_back("could not initialize ICU "
910
2
                      "(check NODE_ICU_DATA or --icu-data-dir parameters)\n");
911
2
    return 9;
912
  }
913
4979
  per_process::metadata.versions.InitializeIntlVersions();
914
#endif
915
916
4979
  NativeModuleEnv::InitializeCodeCache();
917
918
  // We should set node_is_initialized here instead of in node::Start,
919
  // otherwise embedders using node::Init to initialize everything will not be
920
  // able to set it and native modules will not load for them.
921
4979
  node_is_initialized = true;
922
10012
  return 0;
923
}
924
925
// TODO(addaleax): Deprecate and eventually remove this.
926
void Init(int* argc,
927
          const char** argv,
928
          int* exec_argc,
929
          const char*** exec_argv) {
930
  std::vector<std::string> argv_(argv, argv + *argc);  // NOLINT
931
  std::vector<std::string> exec_argv_;
932
  std::vector<std::string> errors;
933
934
  // This (approximately) duplicates some logic that has been moved to
935
  // node::Start(), with the difference that here we explicitly call `exit()`.
936
  int exit_code = InitializeNodeWithArgs(&argv_, &exec_argv_, &errors);
937
938
  for (const std::string& error : errors)
939
    fprintf(stderr, "%s: %s\n", argv_.at(0).c_str(), error.c_str());
940
  if (exit_code != 0) exit(exit_code);
941
942
  if (per_process::cli_options->print_version) {
943
    printf("%s\n", NODE_VERSION);
944
    exit(0);
945
  }
946
947
  if (per_process::cli_options->print_v8_help) {
948
    // Doesn't return.
949
    V8::SetFlagsFromString("--help", static_cast<size_t>(6));
950
    UNREACHABLE();
951
  }
952
953
  *argc = argv_.size();
954
  *exec_argc = exec_argv_.size();
955
  // These leak memory, because, in the original code of this function, no
956
  // extra allocations were visible. This should be okay because this function
957
  // is only supposed to be called once per process, though.
958
  *exec_argv = Malloc<const char*>(*exec_argc);
959
  for (int i = 0; i < *exec_argc; ++i)
960
    (*exec_argv)[i] = strdup(exec_argv_[i].c_str());
961
  for (int i = 0; i < *argc; ++i)
962
    argv[i] = strdup(argv_[i].c_str());
963
}
964
965
5033
InitializationResult InitializeOncePerProcess(int argc, char** argv) {
966
5033
  atexit(ResetStdio);
967
5033
  PlatformInit();
968
969
5033
  CHECK_GT(argc, 0);
970
971
#ifdef NODE_ENABLE_LARGE_CODE_PAGES
972
  if (node::IsLargePagesEnabled()) {
973
    if (node::MapStaticCodeToLargePages() != 0) {
974
      fprintf(stderr, "Reverting to default page size\n");
975
    }
976
  }
977
#endif
978
979
  // Hack around with the argv pointer. Used for process.title = "blah".
980
5033
  argv = uv_setup_args(argc, argv);
981
982
5033
  InitializationResult result;
983
5033
  result.args = std::vector<std::string>(argv, argv + argc);
984
10065
  std::vector<std::string> errors;
985
986
  // This needs to run *before* V8::Initialize().
987
  {
988
    result.exit_code =
989
5033
        InitializeNodeWithArgs(&(result.args), &(result.exec_args), &errors);
990
5089
    for (const std::string& error : errors)
991
56
      fprintf(stderr, "%s: %s\n", result.args.at(0).c_str(), error.c_str());
992
5033
    if (result.exit_code != 0) {
993
54
      result.early_return = true;
994
54
      return result;
995
    }
996
  }
997
998
4979
  if (per_process::cli_options->print_version) {
999
3
    printf("%s\n", NODE_VERSION);
1000
3
    result.exit_code = 0;
1001
3
    result.early_return = true;
1002
3
    return result;
1003
  }
1004
1005
4976
  if (per_process::cli_options->print_v8_help) {
1006
    // Doesn't return.
1007
1
    V8::SetFlagsFromString("--help", static_cast<size_t>(6));
1008
    UNREACHABLE();
1009
  }
1010
1011
#if HAVE_OPENSSL
1012
  {
1013
4975
    std::string extra_ca_certs;
1014
4975
    if (credentials::SafeGetenv("NODE_EXTRA_CA_CERTS", &extra_ca_certs))
1015
3
      crypto::UseExtraCaCerts(extra_ca_certs);
1016
  }
1017
#ifdef NODE_FIPS_MODE
1018
  // In the case of FIPS builds we should make sure
1019
  // the random source is properly initialized first.
1020
  OPENSSL_init();
1021
#endif  // NODE_FIPS_MODE
1022
  // V8 on Windows doesn't have a good source of entropy. Seed it from
1023
  // OpenSSL's pool.
1024
4975
  V8::SetEntropySource(crypto::EntropySource);
1025
#endif  // HAVE_OPENSSL
1026
1027
4975
  InitializeV8Platform(per_process::cli_options->v8_thread_pool_size);
1028
4975
  V8::Initialize();
1029
4975
  performance::performance_v8_start = PERFORMANCE_NOW();
1030
4975
  per_process::v8_initialized = true;
1031
4975
  return result;
1032
}
1033
1034
4569
void TearDownOncePerProcess() {
1035
4569
  per_process::v8_initialized = false;
1036
4569
  V8::Dispose();
1037
1038
  // uv_run cannot be called from the time before the beforeExit callback
1039
  // runs until the program exits unless the event loop has any referenced
1040
  // handles after beforeExit terminates. This prevents unrefed timers
1041
  // that happen to terminate during shutdown from being run unsafely.
1042
  // Since uv_run cannot be called, uv_async handles held by the platform
1043
  // will never be fully cleaned up.
1044
4569
  per_process::v8_platform.Dispose();
1045
4569
}
1046
1047
5032
int Start(int argc, char** argv) {
1048
5032
  InitializationResult result = InitializeOncePerProcess(argc, argv);
1049
5031
  if (result.early_return) {
1050
57
    return result.exit_code;
1051
  }
1052
1053
  {
1054
4974
    Isolate::CreateParams params;
1055
4974
    const std::vector<size_t>* indexes = nullptr;
1056
4974
    std::vector<intptr_t> external_references;
1057
1058
    bool force_no_snapshot =
1059
4974
        per_process::cli_options->per_isolate->no_node_snapshot;
1060
4974
    if (!force_no_snapshot) {
1061
4973
      v8::StartupData* blob = NodeMainInstance::GetEmbeddedSnapshotBlob();
1062
4973
      if (blob != nullptr) {
1063
        // TODO(joyeecheung): collect external references and set it in
1064
        // params.external_references.
1065
4973
        external_references.push_back(reinterpret_cast<intptr_t>(nullptr));
1066
4973
        params.external_references = external_references.data();
1067
4973
        params.snapshot_blob = blob;
1068
4973
        indexes = NodeMainInstance::GetIsolateDataIndexes();
1069
      }
1070
    }
1071
1072
    NodeMainInstance main_instance(&params,
1073
                                   uv_default_loop(),
1074
4974
                                   per_process::v8_platform.Platform(),
1075
                                   result.args,
1076
                                   result.exec_args,
1077
9542
                                   indexes);
1078
9542
    result.exit_code = main_instance.Run();
1079
  }
1080
1081
4568
  TearDownOncePerProcess();
1082
4568
  return result.exit_code;
1083
}
1084
1085
69
int Stop(Environment* env) {
1086
69
  env->ExitEnv();
1087
69
  return 0;
1088
}
1089
1090

15102
}  // namespace node
1091
1092
#if !HAVE_INSPECTOR
1093
void Initialize() {}
1094
1095
NODE_MODULE_CONTEXT_AWARE_INTERNAL(inspector, Initialize)
1096
#endif  // !HAVE_INSPECTOR