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: 292 335 87.2 %
Date: 2019-02-13 22:28:58 Branches: 159 216 73.6 %

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

2170
      if (nr == SIGKILL || nr == SIGSTOP || nr == SIGPROF)
170
210
        continue;
171
1960
      act.sa_handler = (nr == SIGPIPE) ? SIG_IGN : SIG_DFL;
172
1960
      CHECK_EQ(0, sigaction(nr, &act, nullptr));
173
    }
174
#endif
175
70
    env->inspector_agent()->WaitForDisconnect();
176
  }
177
#endif
178
4122
}
179
180
void SignalExit(int signo) {
181
  uv_tty_reset_mode();
182
#ifdef __FreeBSD__
183
  // FreeBSD has a nasty bug, see RegisterSignalHandler for details
184
  struct sigaction sa;
185
  memset(&sa, 0, sizeof(sa));
186
  sa.sa_handler = SIG_DFL;
187
  CHECK_EQ(sigaction(signo, &sa, nullptr), 0);
188
#endif
189
  raise(signo);
190
}
191
192
17654
static MaybeLocal<Value> ExecuteBootstrapper(
193
    Environment* env,
194
    const char* id,
195
    std::vector<Local<String>>* parameters,
196
    std::vector<Local<Value>>* arguments) {
197
17654
  EscapableHandleScope scope(env->isolate());
198
  MaybeLocal<Function> maybe_fn =
199
      per_process::native_module_loader.LookupAndCompile(
200
17653
          env->context(), id, parameters, env);
201
202
17654
  if (maybe_fn.IsEmpty()) {
203
    return MaybeLocal<Value>();
204
  }
205
206
17654
  Local<Function> fn = maybe_fn.ToLocalChecked();
207
  MaybeLocal<Value> result = fn->Call(env->context(),
208
                                      Undefined(env->isolate()),
209
17654
                                      arguments->size(),
210
70616
                                      arguments->data());
211
212
  // If there was an error during bootstrap then it was either handled by the
213
  // FatalException handler or it's unrecoverable (e.g. max call stack
214
  // exceeded). Either way, clear the stack so that the AsyncCallbackScope
215
  // destructor doesn't fail on the id check.
216
  // There are only two ways to have a stack size > 1: 1) the user manually
217
  // called MakeCallback or 2) user awaited during bootstrap, which triggered
218
  // _tickCallback().
219
17425
  if (result.IsEmpty()) {
220
52
    env->async_hooks()->clear_async_id_stack();
221
  }
222
223
17426
  return scope.EscapeMaybe(result);
224
}
225
226
4416
MaybeLocal<Value> RunBootstrapping(Environment* env) {
227
4416
  CHECK(!env->has_run_bootstrapping_code());
228
229
4416
  EscapableHandleScope scope(env->isolate());
230
4416
  Isolate* isolate = env->isolate();
231
4416
  Local<Context> context = env->context();
232
233
  // Add a reference to the global object
234
4416
  Local<Object> global = context->Global();
235
236
#if defined HAVE_DTRACE || defined HAVE_ETW
237
  InitDTrace(env, global);
238
#endif
239
240
4416
  Local<Object> process = env->process_object();
241
242
  // Setting global properties for the bootstrappers to use:
243
  // - global
244
  // Expose the global object as a property on itself
245
  // (Allows you to set stuff on `global` from anywhere in JavaScript.)
246
13248
  global->Set(context, FIXED_ONE_BYTE_STRING(env->isolate(), "global"), global)
247
8832
      .FromJust();
248
249
  // Store primordials
250
4416
  env->set_primordials(Object::New(isolate));
251
  std::vector<Local<String>> primordials_params = {
252
    FIXED_ONE_BYTE_STRING(isolate, "breakAtBootstrap"),
253
    env->primordials_string()
254
8832
  };
255
  std::vector<Local<Value>> primordials_args = {
256
    Boolean::New(isolate,
257
8832
                  env->options()->debug_options().break_node_first_line),
258
    env->primordials()
259
17664
  };
260
  MaybeLocal<Value> primordials_ret =
261
      ExecuteBootstrapper(env,
262
                          "internal/bootstrap/primordials",
263
                          &primordials_params,
264
4416
                          &primordials_args);
265
4416
  if (primordials_ret.IsEmpty()) {
266
    return MaybeLocal<Value>();
267
  }
268
269
  // Create binding loaders
270
  std::vector<Local<String>> loaders_params = {
271
      env->process_string(),
272
      FIXED_ONE_BYTE_STRING(isolate, "getLinkedBinding"),
273
      FIXED_ONE_BYTE_STRING(isolate, "getInternalBinding"),
274
      // --experimental-modules
275
      FIXED_ONE_BYTE_STRING(isolate, "experimentalModules"),
276
      // --expose-internals
277
      FIXED_ONE_BYTE_STRING(isolate, "exposeInternals"),
278
8832
      env->primordials_string()};
279
  std::vector<Local<Value>> loaders_args = {
280
      process,
281
4416
      env->NewFunctionTemplate(binding::GetLinkedBinding)
282
13248
          ->GetFunction(context)
283
          .ToLocalChecked(),
284
4416
      env->NewFunctionTemplate(binding::GetInternalBinding)
285
13248
          ->GetFunction(context)
286
          .ToLocalChecked(),
287
8832
      Boolean::New(isolate, env->options()->experimental_modules),
288
8832
      Boolean::New(isolate, env->options()->expose_internals),
289
39744
      env->primordials()};
290
291
  // Bootstrap internal loaders
292
  MaybeLocal<Value> loader_exports = ExecuteBootstrapper(
293
4416
      env, "internal/bootstrap/loaders", &loaders_params, &loaders_args);
294
4415
  if (loader_exports.IsEmpty()) {
295
    return MaybeLocal<Value>();
296
  }
297
298
  Local<Object> loader_exports_obj =
299
8830
      loader_exports.ToLocalChecked().As<Object>();
300
  Local<Value> internal_binding_loader =
301
13245
      loader_exports_obj->Get(context, env->internal_binding_string())
302
8830
          .ToLocalChecked();
303
4415
  env->set_internal_binding_loader(internal_binding_loader.As<Function>());
304
305
  Local<Value> require =
306
13248
      loader_exports_obj->Get(context, env->require_string()).ToLocalChecked();
307
4416
  env->set_native_module_require(require.As<Function>());
308
309
  // process, loaderExports, isMainThread, ownsProcessState, primordials
310
  std::vector<Local<String>> node_params = {
311
      env->process_string(),
312
      FIXED_ONE_BYTE_STRING(isolate, "loaderExports"),
313
      FIXED_ONE_BYTE_STRING(isolate, "isMainThread"),
314
      FIXED_ONE_BYTE_STRING(isolate, "ownsProcessState"),
315
8832
      env->primordials_string()};
316
  std::vector<Local<Value>> node_args = {
317
      process,
318
      loader_exports_obj,
319
4416
      Boolean::New(isolate, env->is_main_thread()),
320
4416
      Boolean::New(isolate, env->owns_process_state()),
321
22078
      env->primordials()};
322
323
  MaybeLocal<Value> result = ExecuteBootstrapper(
324
4416
      env, "internal/bootstrap/node", &node_params, &node_args);
325
326
4416
  env->set_has_run_bootstrapping_code(true);
327
328
  return scope.EscapeMaybe(result);
329
}
330
331
4396
void MarkBootstrapComplete(const FunctionCallbackInfo<Value>& args) {
332
4396
  Environment* env = Environment::GetCurrent(args);
333
  env->performance_state()->Mark(
334
4396
      performance::NODE_PERFORMANCE_MILESTONE_BOOTSTRAP_COMPLETE);
335
4396
}
336
337
4406
MaybeLocal<Value> StartExecution(Environment* env, const char* main_script_id) {
338
4406
  EscapableHandleScope scope(env->isolate());
339
4406
  CHECK_NOT_NULL(main_script_id);
340
341
  std::vector<Local<String>> parameters = {
342
      env->process_string(),
343
      env->require_string(),
344
      env->internal_binding_string(),
345
8584
      FIXED_ONE_BYTE_STRING(env->isolate(), "markBootstrapComplete")};
346
347
  std::vector<Local<Value>> arguments = {
348
      env->process_object(),
349
      env->native_module_require(),
350
      env->internal_binding_loader(),
351
4406
      env->NewFunctionTemplate(MarkBootstrapComplete)
352
17624
          ->GetFunction(env->context())
353
26208
          .ToLocalChecked()};
354
355
  MaybeLocal<Value> result =
356
4406
      ExecuteBootstrapper(env, main_script_id, &parameters, &arguments);
357
4178
  return scope.EscapeMaybe(result);
358
}
359
360
4265
MaybeLocal<Value> StartMainThreadExecution(Environment* env) {
361
  // To allow people to extend Node in different ways, this hook allows
362
  // one to drop a file lib/_third_party_main.js into the build
363
  // directory which will be executed instead of Node's normal loading.
364
4265
  if (per_process::native_module_loader.Exists("_third_party_main")) {
365
    return StartExecution(env, "internal/main/run_third_party_main");
366
  }
367
368

8528
  if (env->execution_mode() == Environment::ExecutionMode::kInspect ||
369
4263
      env->execution_mode() == Environment::ExecutionMode::kDebug) {
370
4
    return StartExecution(env, "internal/main/inspect");
371
  }
372
373
4261
  if (per_process::cli_options->print_help) {
374
1
    env->set_execution_mode(Environment::ExecutionMode::kPrintHelp);
375
1
    return StartExecution(env, "internal/main/print_help");
376
  }
377
378
4260
  if (per_process::cli_options->print_bash_completion) {
379
1
    env->set_execution_mode(Environment::ExecutionMode::kPrintBashCompletion);
380
1
    return StartExecution(env, "internal/main/print_bash_completion");
381
  }
382
383
4259
  if (env->options()->prof_process) {
384
53
    env->set_execution_mode(Environment::ExecutionMode::kPrintBashCompletion);
385
53
    return StartExecution(env, "internal/main/prof_process");
386
  }
387
388
  // -e/--eval without -i/--interactive
389


4206
  if (env->options()->has_eval_string && !env->options()->force_repl) {
390
284
    env->set_execution_mode(Environment::ExecutionMode::kEvalString);
391
284
    return StartExecution(env, "internal/main/eval_string");
392
  }
393
394
3922
  if (env->options()->syntax_check_only) {
395
30
    env->set_execution_mode(Environment::ExecutionMode::kCheckSyntax);
396
30
    return StartExecution(env, "internal/main/check_syntax");
397
  }
398
399
3892
  if (env->execution_mode() == Environment::ExecutionMode::kRunMainModule) {
400
3866
    return StartExecution(env, "internal/main/run_main_module");
401
  }
402
403


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

133734
    if (nr == SIGKILL || nr == SIGSTOP)
479
8628
      continue;
480
125106
    act.sa_handler = (nr == SIGPIPE) ? SIG_IGN : SIG_DFL;
481
125106
    CHECK_EQ(0, sigaction(nr, &act, nullptr));
482
  }
483
#endif  // !NODE_SHARED_MODE
484
485
4314
  RegisterSignalHandler(SIGINT, SignalExit, true);
486
4314
  RegisterSignalHandler(SIGTERM, SignalExit, true);
487
488
  // Raise the open file descriptor limit.
489
  struct rlimit lim;
490

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


50568
                "--abort-on-uncaught-exception") != v8_args.end() ||
554
      std::find(v8_args.begin(), v8_args.end(),
555

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

4315
        credentials::SafeGetenv("NODE_PENDING_DEPRECATION", &text) &&
625
4315
        text[0] == '1';
626
  }
627
628
  // Allow for environment set preserving symlinks.
629
  {
630
4314
    std::string text;
631
4314
    default_env_options->preserve_symlinks =
632

4315
        credentials::SafeGetenv("NODE_PRESERVE_SYMLINKS", &text) &&
633
4315
        text[0] == '1';
634
  }
635
636
  {
637
4314
    std::string text;
638
4314
    default_env_options->preserve_symlinks_main =
639

4314
        credentials::SafeGetenv("NODE_PRESERVE_SYMLINKS_MAIN", &text) &&
640
4314
        text[0] == '1';
641
  }
642
643
4314
  if (default_env_options->redirect_warnings.empty()) {
644
    credentials::SafeGetenv("NODE_REDIRECT_WARNINGS",
645
4314
                            &default_env_options->redirect_warnings);
646
  }
647
648
#if HAVE_OPENSSL
649
4314
  std::string* openssl_config = &per_process::cli_options->openssl_config;
650
4314
  if (openssl_config->empty()) {
651
4314
    credentials::SafeGetenv("OPENSSL_CONF", openssl_config);
652
  }
653
#endif
654
655
#if !defined(NODE_WITHOUT_NODE_OPTIONS)
656
8628
  std::string node_options;
657
4314
  if (credentials::SafeGetenv("NODE_OPTIONS", &node_options)) {
658
    // [0] is expected to be the program name, fill it in from the real argv
659
    // and use 'x' as a placeholder while parsing.
660
4169
    std::vector<std::string> env_argv = SplitString("x " + node_options, ' ');
661
4169
    env_argv[0] = argv->at(0);
662
663
4169
    const int exit_code = ProcessGlobalArgs(&env_argv, nullptr, errors, true);
664

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


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

12942
}  // namespace node
940
941
#if !HAVE_INSPECTOR
942
void Initialize() {}
943
944
NODE_MODULE_CONTEXT_AWARE_INTERNAL(inspector, Initialize)
945
#endif  // !HAVE_INSPECTOR