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: 296 340 87.1 %
Date: 2019-02-23 22:23:05 Branches: 168 226 74.3 %

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

127069
      if (nr == SIGKILL || nr == SIGSTOP || nr == SIGPROF)
171
12297
        continue;
172
114772
      act.sa_handler = (nr == SIGPIPE) ? SIG_IGN : SIG_DFL;
173
114772
      CHECK_EQ(0, sigaction(nr, &act, nullptr));
174
    }
175
#endif
176
4099
    env->inspector_agent()->WaitForDisconnect();
177
  }
178
#endif
179
4102
}
180
181
void SignalExit(int signo) {
182
  uv_tty_reset_mode();
183
#ifdef __FreeBSD__
184
  // FreeBSD has a nasty bug, see RegisterSignalHandler for details
185
  struct sigaction sa;
186
  memset(&sa, 0, sizeof(sa));
187
  sa.sa_handler = SIG_DFL;
188
  CHECK_EQ(sigaction(signo, &sa, nullptr), 0);
189
#endif
190
  raise(signo);
191
}
192
193
17600
static MaybeLocal<Value> ExecuteBootstrapper(
194
    Environment* env,
195
    const char* id,
196
    std::vector<Local<String>>* parameters,
197
    std::vector<Local<Value>>* arguments) {
198
17600
  EscapableHandleScope scope(env->isolate());
199
  MaybeLocal<Function> maybe_fn =
200
      per_process::native_module_loader.LookupAndCompile(
201
17599
          env->context(), id, parameters, env);
202
203
17600
  if (maybe_fn.IsEmpty()) {
204
    return MaybeLocal<Value>();
205
  }
206
207
17600
  Local<Function> fn = maybe_fn.ToLocalChecked();
208
  MaybeLocal<Value> result = fn->Call(env->context(),
209
                                      Undefined(env->isolate()),
210
17600
                                      arguments->size(),
211
70400
                                      arguments->data());
212
213
  // If there was an error during bootstrap then it was either handled by the
214
  // FatalException handler or it's unrecoverable (e.g. max call stack
215
  // exceeded). Either way, clear the stack so that the AsyncCallbackScope
216
  // destructor doesn't fail on the id check.
217
  // There are only two ways to have a stack size > 1: 1) the user manually
218
  // called MakeCallback or 2) user awaited during bootstrap, which triggered
219
  // _tickCallback().
220
17371
  if (result.IsEmpty()) {
221
55
    env->async_hooks()->clear_async_id_stack();
222
  }
223
224
17371
  return scope.EscapeMaybe(result);
225
}
226
227
4404
MaybeLocal<Value> RunBootstrapping(Environment* env) {
228
4404
  CHECK(!env->has_run_bootstrapping_code());
229
230
4404
  EscapableHandleScope scope(env->isolate());
231
4404
  Isolate* isolate = env->isolate();
232
4404
  Local<Context> context = env->context();
233
234
8808
  std::string coverage;
235
4404
  bool rc = credentials::SafeGetenv("NODE_V8_COVERAGE", &coverage);
236

4404
  if (rc && !coverage.empty()) {
237
#if HAVE_INSPECTOR
238
4401
    if (!coverage::StartCoverageCollection(env)) {
239
      return MaybeLocal<Value>();
240
    }
241
#else
242
    fprintf(stderr, "NODE_V8_COVERAGE cannot be used without inspector");
243
#endif  // HAVE_INSPECTOR
244
  }
245
246
  // Add a reference to the global object
247
4404
  Local<Object> global = context->Global();
248
249
#if defined HAVE_DTRACE || defined HAVE_ETW
250
  InitDTrace(env, global);
251
#endif
252
253
4404
  Local<Object> process = env->process_object();
254
255
  // Setting global properties for the bootstrappers to use:
256
  // - global
257
  // Expose the global object as a property on itself
258
  // (Allows you to set stuff on `global` from anywhere in JavaScript.)
259
13212
  global->Set(context, FIXED_ONE_BYTE_STRING(env->isolate(), "global"), global)
260
8808
      .FromJust();
261
262
  // Store primordials
263
4404
  env->set_primordials(Object::New(isolate));
264
  std::vector<Local<String>> primordials_params = {
265
    env->primordials_string()
266
8808
  };
267
  std::vector<Local<Value>> primordials_args = {
268
    env->primordials()
269
13212
  };
270
271
#if HAVE_INSPECTOR
272
4404
  if (env->options()->debug_options().break_node_first_line) {
273
    env->inspector_agent()->PauseOnNextJavascriptStatement(
274
        "Break at bootstrap");
275
  }
276
#endif  // HAVE_INSPECTOR
277
  MaybeLocal<Value> primordials_ret =
278
      ExecuteBootstrapper(env,
279
                          "internal/bootstrap/primordials",
280
                          &primordials_params,
281
4404
                          &primordials_args);
282
4404
  if (primordials_ret.IsEmpty()) {
283
2
    return MaybeLocal<Value>();
284
  }
285
286
  // Create binding loaders
287
  std::vector<Local<String>> loaders_params = {
288
      env->process_string(),
289
      FIXED_ONE_BYTE_STRING(isolate, "getLinkedBinding"),
290
      FIXED_ONE_BYTE_STRING(isolate, "getInternalBinding"),
291
      // --experimental-modules
292
      FIXED_ONE_BYTE_STRING(isolate, "experimentalModules"),
293
      // --expose-internals
294
      FIXED_ONE_BYTE_STRING(isolate, "exposeInternals"),
295
8804
      env->primordials_string()};
296
  std::vector<Local<Value>> loaders_args = {
297
      process,
298
4402
      env->NewFunctionTemplate(binding::GetLinkedBinding)
299
13206
          ->GetFunction(context)
300
          .ToLocalChecked(),
301
4402
      env->NewFunctionTemplate(binding::GetInternalBinding)
302
13206
          ->GetFunction(context)
303
          .ToLocalChecked(),
304
8804
      Boolean::New(isolate, env->options()->experimental_modules),
305
8804
      Boolean::New(isolate, env->options()->expose_internals),
306
39618
      env->primordials()};
307
308
  // Bootstrap internal loaders
309
  MaybeLocal<Value> loader_exports = ExecuteBootstrapper(
310
4402
      env, "internal/bootstrap/loaders", &loaders_params, &loaders_args);
311
4402
  if (loader_exports.IsEmpty()) {
312
    return MaybeLocal<Value>();
313
  }
314
315
  Local<Object> loader_exports_obj =
316
8804
      loader_exports.ToLocalChecked().As<Object>();
317
  Local<Value> internal_binding_loader =
318
13206
      loader_exports_obj->Get(context, env->internal_binding_string())
319
8804
          .ToLocalChecked();
320
4402
  env->set_internal_binding_loader(internal_binding_loader.As<Function>());
321
322
  Local<Value> require =
323
13206
      loader_exports_obj->Get(context, env->require_string()).ToLocalChecked();
324
4402
  env->set_native_module_require(require.As<Function>());
325
326
  // process, loaderExports, isMainThread, ownsProcessState, primordials
327
  std::vector<Local<String>> node_params = {
328
      env->process_string(),
329
      FIXED_ONE_BYTE_STRING(isolate, "loaderExports"),
330
      FIXED_ONE_BYTE_STRING(isolate, "isMainThread"),
331
      FIXED_ONE_BYTE_STRING(isolate, "ownsProcessState"),
332
8804
      env->primordials_string()};
333
  std::vector<Local<Value>> node_args = {
334
      process,
335
      loader_exports_obj,
336
4402
      Boolean::New(isolate, env->is_main_thread()),
337
4402
      Boolean::New(isolate, env->owns_process_state()),
338
22010
      env->primordials()};
339
340
  MaybeLocal<Value> result = ExecuteBootstrapper(
341
4402
      env, "internal/bootstrap/node", &node_params, &node_args);
342
343
4402
  env->set_has_run_bootstrapping_code(true);
344
345
  return scope.EscapeMaybe(result);
346
}
347
348
4381
void MarkBootstrapComplete(const FunctionCallbackInfo<Value>& args) {
349
4381
  Environment* env = Environment::GetCurrent(args);
350
  env->performance_state()->Mark(
351
4381
      performance::NODE_PERFORMANCE_MILESTONE_BOOTSTRAP_COMPLETE);
352
4381
}
353
354
4392
MaybeLocal<Value> StartExecution(Environment* env, const char* main_script_id) {
355
4392
  EscapableHandleScope scope(env->isolate());
356
4392
  CHECK_NOT_NULL(main_script_id);
357
358
  std::vector<Local<String>> parameters = {
359
      env->process_string(),
360
      env->require_string(),
361
      env->internal_binding_string(),
362
8555
      FIXED_ONE_BYTE_STRING(env->isolate(), "markBootstrapComplete")};
363
364
  std::vector<Local<Value>> arguments = {
365
      env->process_object(),
366
      env->native_module_require(),
367
      env->internal_binding_loader(),
368
4392
      env->NewFunctionTemplate(MarkBootstrapComplete)
369
17568
          ->GetFunction(env->context())
370
26123
          .ToLocalChecked()};
371
372
  MaybeLocal<Value> result =
373
4392
      ExecuteBootstrapper(env, main_script_id, &parameters, &arguments);
374
4163
  return scope.EscapeMaybe(result);
375
}
376
377
4239
MaybeLocal<Value> StartMainThreadExecution(Environment* env) {
378
  // To allow people to extend Node in different ways, this hook allows
379
  // one to drop a file lib/_third_party_main.js into the build
380
  // directory which will be executed instead of Node's normal loading.
381
4239
  if (per_process::native_module_loader.Exists("_third_party_main")) {
382
    return StartExecution(env, "internal/main/run_third_party_main");
383
  }
384
385

8476
  if (env->execution_mode() == Environment::ExecutionMode::kInspect ||
386
4237
      env->execution_mode() == Environment::ExecutionMode::kDebug) {
387
4
    return StartExecution(env, "internal/main/inspect");
388
  }
389
390
4235
  if (per_process::cli_options->print_help) {
391
1
    env->set_execution_mode(Environment::ExecutionMode::kPrintHelp);
392
1
    return StartExecution(env, "internal/main/print_help");
393
  }
394
395
4234
  if (per_process::cli_options->print_bash_completion) {
396
1
    env->set_execution_mode(Environment::ExecutionMode::kPrintBashCompletion);
397
1
    return StartExecution(env, "internal/main/print_bash_completion");
398
  }
399
400
4233
  if (env->options()->prof_process) {
401
9
    env->set_execution_mode(Environment::ExecutionMode::kPrintBashCompletion);
402
9
    return StartExecution(env, "internal/main/prof_process");
403
  }
404
405
  // -e/--eval without -i/--interactive
406


4224
  if (env->options()->has_eval_string && !env->options()->force_repl) {
407
286
    env->set_execution_mode(Environment::ExecutionMode::kEvalString);
408
286
    return StartExecution(env, "internal/main/eval_string");
409
  }
410
411
3938
  if (env->options()->syntax_check_only) {
412
30
    env->set_execution_mode(Environment::ExecutionMode::kCheckSyntax);
413
30
    return StartExecution(env, "internal/main/check_syntax");
414
  }
415
416
3908
  if (env->execution_mode() == Environment::ExecutionMode::kRunMainModule) {
417
3882
    return StartExecution(env, "internal/main/run_main_module");
418
  }
419
420


26
  if (env->options()->force_repl || uv_guess_handle(STDIN_FILENO) == UV_TTY) {
421
9
    env->set_execution_mode(Environment::ExecutionMode::kRepl);
422
9
    return StartExecution(env, "internal/main/repl");
423
  }
424
425
17
  env->set_execution_mode(Environment::ExecutionMode::kEvalStdin);
426
17
  return StartExecution(env, "internal/main/eval_stdin");
427
}
428
429
4239
void LoadEnvironment(Environment* env) {
430
4239
  CHECK(env->is_main_thread());
431
  // TODO(joyeecheung): Not all of the execution modes in
432
  // StartMainThreadExecution() make sense for embedders. Pick the
433
  // useful ones out, and allow embedders to customize the entry
434
  // point more directly without using _third_party_main.js
435
8478
  if (!RunBootstrapping(env).IsEmpty()) {
436
4239
    USE(StartMainThreadExecution(env));
437
  }
438
4010
}
439
440
441
#ifdef __POSIX__
442
12994
void RegisterSignalHandler(int signal,
443
                           void (*handler)(int signal),
444
                           bool reset_handler) {
445
  struct sigaction sa;
446
12994
  memset(&sa, 0, sizeof(sa));
447
12994
  sa.sa_handler = handler;
448
#ifndef __FreeBSD__
449
  // FreeBSD has a nasty bug with SA_RESETHAND reseting the SA_SIGINFO, that is
450
  // in turn set for a libthr wrapper. This leads to a crash.
451
  // Work around the issue by manually setting SIG_DFL in the signal handler
452
12994
  sa.sa_flags = reset_handler ? SA_RESETHAND : 0;
453
#endif
454
12994
  sigfillset(&sa.sa_mask);
455
12994
  CHECK_EQ(sigaction(signal, &sa, nullptr), 0);
456
12994
}
457
458
#endif  // __POSIX__
459
460
4288
inline void PlatformInit() {
461
#ifdef __POSIX__
462
#if HAVE_INSPECTOR
463
  sigset_t sigmask;
464
4288
  sigemptyset(&sigmask);
465
4288
  sigaddset(&sigmask, SIGUSR1);
466
4288
  const int err = pthread_sigmask(SIG_SETMASK, &sigmask, nullptr);
467
#endif  // HAVE_INSPECTOR
468
469
  // Make sure file descriptors 0-2 are valid before we start logging anything.
470
17152
  for (int fd = STDIN_FILENO; fd <= STDERR_FILENO; fd += 1) {
471
    struct stat ignored;
472
12864
    if (fstat(fd, &ignored) == 0)
473
12862
      continue;
474
    // Anything but EBADF means something is seriously wrong.  We don't
475
    // have to special-case EINTR, fstat() is not interruptible.
476
2
    if (errno != EBADF)
477
      ABORT();
478
2
    if (fd != open("/dev/null", O_RDWR))
479
      ABORT();
480
  }
481
482
#if HAVE_INSPECTOR
483
4288
  CHECK_EQ(err, 0);
484
#endif  // HAVE_INSPECTOR
485
486
#ifndef NODE_SHARED_MODE
487
  // Restore signal dispositions, the parent process may have changed them.
488
  struct sigaction act;
489
4288
  memset(&act, 0, sizeof(act));
490
491
  // The hard-coded upper limit is because NSIG is not very reliable; on Linux,
492
  // it evaluates to 32, 34 or 64, depending on whether RT signals are enabled.
493
  // Counting up to SIGRTMIN doesn't work for the same reason.
494
137216
  for (unsigned nr = 1; nr < kMaxSignal; nr += 1) {
495

132928
    if (nr == SIGKILL || nr == SIGSTOP)
496
8576
      continue;
497
124352
    act.sa_handler = (nr == SIGPIPE) ? SIG_IGN : SIG_DFL;
498
124352
    CHECK_EQ(0, sigaction(nr, &act, nullptr));
499
  }
500
#endif  // !NODE_SHARED_MODE
501
502
4288
  RegisterSignalHandler(SIGINT, SignalExit, true);
503
4288
  RegisterSignalHandler(SIGTERM, SignalExit, true);
504
505
  // Raise the open file descriptor limit.
506
  struct rlimit lim;
507

4288
  if (getrlimit(RLIMIT_NOFILE, &lim) == 0 && lim.rlim_cur != lim.rlim_max) {
508
    // Do a binary search for the limit.
509
    rlim_t min = lim.rlim_cur;
510
    rlim_t max = 1 << 20;
511
    // But if there's a defined upper bound, don't search, just set it.
512
    if (lim.rlim_max != RLIM_INFINITY) {
513
      min = lim.rlim_max;
514
      max = lim.rlim_max;
515
    }
516
    do {
517
      lim.rlim_cur = min + (max - min) / 2;
518
      if (setrlimit(RLIMIT_NOFILE, &lim)) {
519
        max = lim.rlim_cur;
520
      } else {
521
        min = lim.rlim_cur;
522
      }
523
    } while (min + 1 < max);
524
  }
525
#endif  // __POSIX__
526
#ifdef _WIN32
527
  for (int fd = 0; fd <= 2; ++fd) {
528
    auto handle = reinterpret_cast<HANDLE>(_get_osfhandle(fd));
529
    if (handle == INVALID_HANDLE_VALUE ||
530
        GetFileType(handle) == FILE_TYPE_UNKNOWN) {
531
      // Ignore _close result. If it fails or not depends on used Windows
532
      // version. We will just check _open result.
533
      _close(fd);
534
      if (fd != _open("nul", _O_RDWR))
535
        ABORT();
536
    }
537
  }
538
#endif  // _WIN32
539
4288
}
540
541
8415
int ProcessGlobalArgs(std::vector<std::string>* args,
542
                      std::vector<std::string>* exec_args,
543
                      std::vector<std::string>* errors,
544
                      bool is_env) {
545
  // Parse a few arguments which are specific to Node.
546
8415
  std::vector<std::string> v8_args;
547
548
16830
  Mutex::ScopedLock lock(per_process::cli_options_mutex);
549
  options_parser::PerProcessOptionsParser::instance.Parse(
550
      args,
551
      exec_args,
552
      &v8_args,
553
      per_process::cli_options.get(),
554
      is_env ? kAllowedInEnvironment : kDisallowedInEnvironment,
555
8415
      errors);
556
557
8415
  if (!errors->empty()) return 9;
558
559
16768
  std::string revert_error;
560
8384
  for (const std::string& cve : per_process::cli_options->security_reverts) {
561
1
    Revert(cve.c_str(), &revert_error);
562
1
    if (!revert_error.empty()) {
563
1
      errors->emplace_back(std::move(revert_error));
564
1
      return 12;
565
    }
566
  }
567
568
16766
  auto env_opts = per_process::cli_options->per_isolate->per_env;
569
16766
  if (std::find(v8_args.begin(), v8_args.end(),
570


50247
                "--abort-on-uncaught-exception") != v8_args.end() ||
571
      std::find(v8_args.begin(), v8_args.end(),
572

33481
                "--abort_on_uncaught_exception") != v8_args.end()) {
573
20
    env_opts->abort_on_uncaught_exception = true;
574
  }
575
576
  // TODO(bnoordhuis) Intercept --prof arguments and start the CPU profiler
577
  // manually?  That would give us a little more control over its runtime
578
  // behavior but it could also interfere with the user's intentions in ways
579
  // we fail to anticipate.  Dillema.
580
8383
  if (std::find(v8_args.begin(), v8_args.end(), "--prof") != v8_args.end()) {
581
2
    per_process::v8_is_profiling = true;
582
  }
583
584
#ifdef __POSIX__
585
  // Block SIGPROF signals when sleeping in epoll_wait/kevent/etc.  Avoids the
586
  // performance penalty of frequent EINTR wakeups when the profiler is running.
587
  // Only do this for v8.log profiling, as it breaks v8::CpuProfiler users.
588
8383
  if (per_process::v8_is_profiling) {
589
2
    uv_loop_configure(uv_default_loop(), UV_LOOP_BLOCK_SIGNAL, SIGPROF);
590
  }
591
#endif
592
593
16766
  std::vector<char*> v8_args_as_char_ptr(v8_args.size());
594
8383
  if (v8_args.size() > 0) {
595
16884
    for (size_t i = 0; i < v8_args.size(); ++i)
596
8501
      v8_args_as_char_ptr[i] = &v8_args[i][0];
597
8383
    int argc = v8_args.size();
598
8383
    V8::SetFlagsFromCommandLine(&argc, &v8_args_as_char_ptr[0], true);
599
8383
    v8_args_as_char_ptr.resize(argc);
600
  }
601
602
  // Anything that's still in v8_argv is not a V8 or a node option.
603
8396
  for (size_t i = 1; i < v8_args_as_char_ptr.size(); i++)
604
13
    errors->push_back("bad option: " + std::string(v8_args_as_char_ptr[i]));
605
606
8383
  if (v8_args_as_char_ptr.size() > 1) return 9;
607
608
16787
  return 0;
609
}
610
611
4288
int Init(std::vector<std::string>* argv,
612
         std::vector<std::string>* exec_argv,
613
         std::vector<std::string>* errors) {
614
  // Register built-in modules
615
4288
  binding::RegisterBuiltinModules();
616
617
  // Make inherited handles noninheritable.
618
4288
  uv_disable_stdio_inheritance();
619
620
#ifdef NODE_REPORT
621
  // Cache the original command line to be
622
  // used in diagnostic reports.
623
4288
  per_process::cli_options->cmdline = *argv;
624
#endif  //  NODE_REPORT
625
626
#if defined(NODE_V8_OPTIONS)
627
  // Should come before the call to V8::SetFlagsFromCommandLine()
628
  // so the user can disable a flag --foo at run-time by passing
629
  // --no_foo from the command line.
630
  V8::SetFlagsFromString(NODE_V8_OPTIONS, sizeof(NODE_V8_OPTIONS) - 1);
631
#endif
632
633
  std::shared_ptr<EnvironmentOptions> default_env_options =
634
4288
      per_process::cli_options->per_isolate->per_env;
635
  {
636
4288
    std::string text;
637
4288
    default_env_options->pending_deprecation =
638

4289
        credentials::SafeGetenv("NODE_PENDING_DEPRECATION", &text) &&
639
4289
        text[0] == '1';
640
  }
641
642
  // Allow for environment set preserving symlinks.
643
  {
644
4288
    std::string text;
645
4288
    default_env_options->preserve_symlinks =
646

4289
        credentials::SafeGetenv("NODE_PRESERVE_SYMLINKS", &text) &&
647
4289
        text[0] == '1';
648
  }
649
650
  {
651
4288
    std::string text;
652
4288
    default_env_options->preserve_symlinks_main =
653

4288
        credentials::SafeGetenv("NODE_PRESERVE_SYMLINKS_MAIN", &text) &&
654
4288
        text[0] == '1';
655
  }
656
657
4288
  if (default_env_options->redirect_warnings.empty()) {
658
    credentials::SafeGetenv("NODE_REDIRECT_WARNINGS",
659
4288
                            &default_env_options->redirect_warnings);
660
  }
661
662
#if HAVE_OPENSSL
663
4288
  std::string* openssl_config = &per_process::cli_options->openssl_config;
664
4288
  if (openssl_config->empty()) {
665
4288
    credentials::SafeGetenv("OPENSSL_CONF", openssl_config);
666
  }
667
#endif
668
669
#if !defined(NODE_WITHOUT_NODE_OPTIONS)
670
8576
  std::string node_options;
671
4288
  if (credentials::SafeGetenv("NODE_OPTIONS", &node_options)) {
672
    // [0] is expected to be the program name, fill it in from the real argv
673
    // and use 'x' as a placeholder while parsing.
674
4142
    std::vector<std::string> env_argv = SplitString("x " + node_options, ' ');
675
4142
    env_argv[0] = argv->at(0);
676
677
4142
    const int exit_code = ProcessGlobalArgs(&env_argv, nullptr, errors, true);
678

4142
    if (exit_code != 0) return exit_code;
679
  }
680
#endif
681
682
4273
  const int exit_code = ProcessGlobalArgs(argv, exec_argv, errors, false);
683
4273
  if (exit_code != 0) return exit_code;
684
685
  // Set the process.title immediately after processing argv if --title is set.
686
4245
  if (!per_process::cli_options->title.empty())
687
2
    uv_set_process_title(per_process::cli_options->title.c_str());
688
689
#if defined(NODE_HAVE_I18N_SUPPORT)
690
  // If the parameter isn't given, use the env variable.
691
4245
  if (per_process::cli_options->icu_data_dir.empty())
692
    credentials::SafeGetenv("NODE_ICU_DATA",
693
4244
                            &per_process::cli_options->icu_data_dir);
694
  // Initialize ICU.
695
  // If icu_data_dir is empty here, it will load the 'minimal' data.
696
4245
  if (!i18n::InitializeICUDirectory(per_process::cli_options->icu_data_dir)) {
697
    errors->push_back("could not initialize ICU "
698
2
                      "(check NODE_ICU_DATA or --icu-data-dir parameters)\n");
699
2
    return 9;
700
  }
701
4243
  per_process::metadata.versions.InitializeIntlVersions();
702
#endif
703
704
  // We should set node_is_initialized here instead of in node::Start,
705
  // otherwise embedders using node::Init to initialize everything will not be
706
  // able to set it and native modules will not load for them.
707
4243
  node_is_initialized = true;
708
8531
  return 0;
709
}
710
711
// TODO(addaleax): Deprecate and eventually remove this.
712
void Init(int* argc,
713
          const char** argv,
714
          int* exec_argc,
715
          const char*** exec_argv) {
716
  std::vector<std::string> argv_(argv, argv + *argc);  // NOLINT
717
  std::vector<std::string> exec_argv_;
718
  std::vector<std::string> errors;
719
720
  // This (approximately) duplicates some logic that has been moved to
721
  // node::Start(), with the difference that here we explicitly call `exit()`.
722
  int exit_code = Init(&argv_, &exec_argv_, &errors);
723
724
  for (const std::string& error : errors)
725
    fprintf(stderr, "%s: %s\n", argv_.at(0).c_str(), error.c_str());
726
  if (exit_code != 0) exit(exit_code);
727
728
  if (per_process::cli_options->print_version) {
729
    printf("%s\n", NODE_VERSION);
730
    exit(0);
731
  }
732
733
  if (per_process::cli_options->print_v8_help) {
734
    V8::SetFlagsFromString("--help", 6);  // Doesn't return.
735
    UNREACHABLE();
736
  }
737
738
  *argc = argv_.size();
739
  *exec_argc = exec_argv_.size();
740
  // These leak memory, because, in the original code of this function, no
741
  // extra allocations were visible. This should be okay because this function
742
  // is only supposed to be called once per process, though.
743
  *exec_argv = Malloc<const char*>(*exec_argc);
744
  for (int i = 0; i < *exec_argc; ++i)
745
    (*exec_argv)[i] = strdup(exec_argv_[i].c_str());
746
  for (int i = 0; i < *argc; ++i)
747
    argv[i] = strdup(argv_[i].c_str());
748
}
749
750
3889
void RunBeforeExit(Environment* env) {
751
3889
  env->RunBeforeExitCallbacks();
752
753
3889
  if (!uv_loop_alive(env->event_loop()))
754
3889
    EmitBeforeExit(env);
755
3888
}
756
757
4240
inline int Start(Isolate* isolate, IsolateData* isolate_data,
758
                 const std::vector<std::string>& args,
759
                 const std::vector<std::string>& exec_args) {
760
4240
  HandleScope handle_scope(isolate);
761
4240
  Local<Context> context = NewContext(isolate);
762
  Context::Scope context_scope(context);
763
  Environment env(
764
      isolate_data,
765
      context,
766
      static_cast<Environment::Flags>(Environment::kIsMainThread |
767
                                      Environment::kOwnsProcessState |
768
8111
                                      Environment::kOwnsInspector));
769
4240
  env.Start(per_process::v8_is_profiling);
770
4240
  env.ProcessCliArgs(args, exec_args);
771
772
#if HAVE_INSPECTOR && NODE_USE_V8_PLATFORM
773
4240
  CHECK(!env.inspector_agent()->IsListening());
774
  // Inspector agent can't fail to start, but if it was configured to listen
775
  // right away on the websocket port and fails to bind/etc, this will return
776
  // false.
777
8178
  env.inspector_agent()->Start(args.size() > 1 ? args[1].c_str() : "",
778
8480
                               env.options()->debug_options(),
779
                               env.inspector_host_port(),
780
20898
                               true);
781


4311
  if (env.options()->debug_options().inspector_enabled &&
782
71
      !env.inspector_agent()->IsListening()) {
783
1
    return 12;  // Signal internal error.
784
  }
785
#else
786
  // inspector_enabled can't be true if !HAVE_INSPECTOR or !NODE_USE_V8_PLATFORM
787
  // - the option parser should not allow that.
788
  CHECK(!env.options()->debug_options().inspector_enabled);
789
#endif  // HAVE_INSPECTOR && NODE_USE_V8_PLATFORM
790
791
  {
792
4239
    Environment::AsyncCallbackScope callback_scope(&env);
793
4239
    env.async_hooks()->push_async_ids(1, 0);
794
4239
    LoadEnvironment(&env);
795
4010
    env.async_hooks()->pop_async_id(1);
796
  }
797
798
  {
799
4009
    SealHandleScope seal(isolate);
800
    bool more;
801
    env.performance_state()->Mark(
802
4009
        node::performance::NODE_PERFORMANCE_MILESTONE_LOOP_START);
803
3919
    do {
804
4053
      uv_run(env.event_loop(), UV_RUN_DEFAULT);
805
806
3922
      per_process::v8_platform.DrainVMTasks(isolate);
807
808
3920
      more = uv_loop_alive(env.event_loop());
809
3920
      if (more)
810
31
        continue;
811
812
3889
      RunBeforeExit(&env);
813
814
      // Emit `beforeExit` if the loop became alive either after emitting
815
      // event, or after running some callbacks.
816
3888
      more = uv_loop_alive(env.event_loop());
817
    } while (more == true);
818
    env.performance_state()->Mark(
819
3875
        node::performance::NODE_PERFORMANCE_MILESTONE_LOOP_EXIT);
820
  }
821
822
3875
  env.set_trace_sync_io(false);
823
824
3875
  const int exit_code = EmitExit(&env);
825
826
3870
  WaitForInspectorDisconnect(&env);
827
828
3870
  env.set_can_call_into_js(false);
829
3870
  env.stop_sub_worker_contexts();
830
3870
  uv_tty_reset_mode();
831
3870
  env.RunCleanup();
832
3870
  RunAtExit(&env);
833
834
3870
  per_process::v8_platform.DrainVMTasks(isolate);
835
3870
  per_process::v8_platform.CancelVMTasks(isolate);
836
#if defined(LEAK_SANITIZER)
837
  __lsan_do_leak_check();
838
#endif
839
840
7741
  return exit_code;
841
}
842
843
4243
inline int Start(uv_loop_t* event_loop,
844
                 const std::vector<std::string>& args,
845
                 const std::vector<std::string>& exec_args) {
846
  std::unique_ptr<ArrayBufferAllocator, decltype(&FreeArrayBufferAllocator)>
847
4243
      allocator(CreateArrayBufferAllocator(), &FreeArrayBufferAllocator);
848
4243
  Isolate* const isolate = NewIsolate(allocator.get(), event_loop);
849
4243
  if (isolate == nullptr)
850
    return 12;  // Signal internal error.
851
852
4243
  if (per_process::cli_options->print_version) {
853
2
    printf("%s\n", NODE_VERSION);
854
2
    return 0;
855
  }
856
857
4241
  if (per_process::cli_options->print_v8_help) {
858
1
    V8::SetFlagsFromString("--help", 6);  // Doesn't return.
859
    UNREACHABLE();
860
  }
861
862
  int exit_code;
863
  {
864
    Locker locker(isolate);
865
8111
    Isolate::Scope isolate_scope(isolate);
866
8111
    HandleScope handle_scope(isolate);
867
    std::unique_ptr<IsolateData, decltype(&FreeIsolateData)> isolate_data(
868
        CreateIsolateData(isolate,
869
                          event_loop,
870
4240
                          per_process::v8_platform.Platform(),
871
                          allocator.get()),
872
12351
        &FreeIsolateData);
873
    // TODO(addaleax): This should load a real per-Isolate option, currently
874
    // this is still effectively per-process.
875
4240
    if (isolate_data->options()->track_heap_objects) {
876
1
      isolate->GetHeapProfiler()->StartTrackingHeapObjects(true);
877
    }
878
    exit_code =
879
8111
        Start(isolate, isolate_data.get(), args, exec_args);
880
  }
881
882
3871
  isolate->Dispose();
883
3871
  per_process::v8_platform.Platform()->UnregisterIsolate(isolate);
884
885
3871
  return exit_code;
886
}
887
888
4288
int Start(int argc, char** argv) {
889
17152
  atexit([] () { uv_tty_reset_mode(); });
890
4288
  PlatformInit();
891
4288
  per_process::node_start_time = uv_hrtime();
892
893
4288
  CHECK_GT(argc, 0);
894
895
#ifdef NODE_ENABLE_LARGE_CODE_PAGES
896
  if (node::IsLargePagesEnabled()) {
897
    if (node::MapStaticCodeToLargePages() != 0) {
898
      fprintf(stderr, "Reverting to default page size\n");
899
    }
900
  }
901
#endif
902
903
  // Hack around with the argv pointer. Used for process.title = "blah".
904
4288
  argv = uv_setup_args(argc, argv);
905
906
4288
  std::vector<std::string> args(argv, argv + argc);
907
8206
  std::vector<std::string> exec_args;
908
8206
  std::vector<std::string> errors;
909
  // This needs to run *before* V8::Initialize().
910
  {
911
4288
    const int exit_code = Init(&args, &exec_args, &errors);
912
4335
    for (const std::string& error : errors)
913
47
      fprintf(stderr, "%s: %s\n", args.at(0).c_str(), error.c_str());
914
4288
    if (exit_code != 0) return exit_code;
915
  }
916
917
#if HAVE_OPENSSL
918
  {
919
4243
    std::string extra_ca_certs;
920
4243
    if (credentials::SafeGetenv("NODE_EXTRA_CA_CERTS", &extra_ca_certs))
921
3
      crypto::UseExtraCaCerts(extra_ca_certs);
922
  }
923
#ifdef NODE_FIPS_MODE
924
  // In the case of FIPS builds we should make sure
925
  // the random source is properly initialized first.
926
  OPENSSL_init();
927
#endif  // NODE_FIPS_MODE
928
  // V8 on Windows doesn't have a good source of entropy. Seed it from
929
  // OpenSSL's pool.
930
4243
  V8::SetEntropySource(crypto::EntropySource);
931
#endif  // HAVE_OPENSSL
932
933
4243
  InitializeV8Platform(per_process::cli_options->v8_thread_pool_size);
934
4243
  V8::Initialize();
935
4243
  performance::performance_v8_start = PERFORMANCE_NOW();
936
4243
  per_process::v8_initialized = true;
937
  const int exit_code =
938
4243
      Start(uv_default_loop(), args, exec_args);
939
3873
  per_process::v8_initialized = false;
940
3873
  V8::Dispose();
941
942
  // uv_run cannot be called from the time before the beforeExit callback
943
  // runs until the program exits unless the event loop has any referenced
944
  // handles after beforeExit terminates. This prevents unrefed timers
945
  // that happen to terminate during shutdown from being run unsafely.
946
  // Since uv_run cannot be called, uv_async handles held by the platform
947
  // will never be fully cleaned up.
948
3873
  per_process::v8_platform.Dispose();
949
950
7791
  return exit_code;
951
}
952
953

12864
}  // namespace node
954
955
#if !HAVE_INSPECTOR
956
void Initialize() {}
957
958
NODE_MODULE_CONTEXT_AWARE_INTERNAL(inspector, Initialize)
959
#endif  // !HAVE_INSPECTOR