GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage/nodes/benchmark/out/../src/node.cc Lines: 603 695 86.8 %
Date: 2019-01-07 12:15:22 Branches: 288 417 69.1 %

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_revert.h"
34
#include "node_version.h"
35
#include "tracing/traced_value.h"
36
37
#if HAVE_OPENSSL
38
#include "node_crypto.h"
39
#endif
40
41
#if defined(NODE_HAVE_I18N_SUPPORT)
42
#include "node_i18n.h"
43
#endif
44
45
#if HAVE_INSPECTOR
46
#include "inspector_io.h"
47
#endif
48
49
#if defined HAVE_DTRACE || defined HAVE_ETW
50
#include "node_dtrace.h"
51
#endif
52
53
#include "async_wrap-inl.h"
54
#include "env-inl.h"
55
#include "handle_wrap.h"
56
#include "req_wrap-inl.h"
57
#include "string_bytes.h"
58
#include "tracing/agent.h"
59
#include "tracing/node_trace_writer.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
#if defined(LEAK_SANITIZER)
92
#include <sanitizer/lsan_interface.h>
93
#endif
94
95
#if defined(_MSC_VER)
96
#include <direct.h>
97
#include <io.h>
98
#else
99
#include <pthread.h>
100
#include <sys/resource.h>  // getrlimit, setrlimit
101
#include <unistd.h>        // STDIN_FILENO, STDERR_FILENO
102
#endif
103
104
namespace node {
105
106
using options_parser::kAllowedInEnvironment;
107
using options_parser::kDisallowedInEnvironment;
108
using v8::Array;
109
using v8::Boolean;
110
using v8::Context;
111
using v8::DEFAULT;
112
using v8::EscapableHandleScope;
113
using v8::Exception;
114
using v8::Function;
115
using v8::FunctionCallbackInfo;
116
using v8::HandleScope;
117
using v8::Int32;
118
using v8::Integer;
119
using v8::Isolate;
120
using v8::Just;
121
using v8::Local;
122
using v8::Locker;
123
using v8::Maybe;
124
using v8::MaybeLocal;
125
using v8::Message;
126
using v8::MicrotasksPolicy;
127
using v8::NewStringType;
128
using v8::None;
129
using v8::Nothing;
130
using v8::Object;
131
using v8::ObjectTemplate;
132
using v8::Script;
133
using v8::ScriptOrigin;
134
using v8::SealHandleScope;
135
using v8::SideEffectType;
136
using v8::String;
137
using v8::TracingController;
138
using v8::Undefined;
139
using v8::V8;
140
using v8::Value;
141
142
static bool v8_is_profiling = false;
143
144
// Bit flag used to track security reverts (see node_revert.h)
145
unsigned int reverted = 0;
146
147
bool v8_initialized = false;
148
149
// process-relative uptime base, initialized at start-up
150
double prog_start_time;
151
152
3597
Mutex per_process_opts_mutex;
153
3597
std::shared_ptr<PerProcessOptions> per_process_opts {
154
3597
    new PerProcessOptions() };
155
3597
static Mutex node_isolate_mutex;
156
static Isolate* node_isolate;
157
158
// Ensures that __metadata trace events are only emitted
159
// when tracing is enabled.
160
class NodeTraceStateObserver :
161
    public TracingController::TraceStateObserver {
162
 public:
163
67
  void OnTraceEnabled() override {
164
    char name_buffer[512];
165
67
    if (uv_get_process_title(name_buffer, sizeof(name_buffer)) == 0) {
166
      // Only emit the metadata event if the title can be retrieved
167
      // successfully. Ignore it otherwise.
168

132
      TRACE_EVENT_METADATA1("__metadata", "process_name",
169
                            "name", TRACE_STR_COPY(name_buffer));
170
    }
171

134
    TRACE_EVENT_METADATA1("__metadata",
172
                          "version",
173
                          "node",
174
                          per_process::metadata.versions.node.c_str());
175

67
    TRACE_EVENT_METADATA1("__metadata", "thread_name",
176
                          "name", "JavaScriptMainThread");
177
178
67
    auto trace_process = tracing::TracedValue::Create();
179
67
    trace_process->BeginDictionary("versions");
180
181
#define V(key)                                                                 \
182
  trace_process->SetString(#key, per_process::metadata.versions.key.c_str());
183
184
67
    NODE_VERSIONS_KEYS(V)
185
#undef V
186
187
67
    trace_process->EndDictionary();
188
189
67
    trace_process->SetString("arch", per_process::metadata.arch.c_str());
190
    trace_process->SetString("platform",
191
67
                             per_process::metadata.platform.c_str());
192
193
67
    trace_process->BeginDictionary("release");
194
    trace_process->SetString("name",
195
67
                             per_process::metadata.release.name.c_str());
196
#if NODE_VERSION_IS_LTS
197
    trace_process->SetString("lts", per_process::metadata.release.lts.c_str());
198
#endif
199
67
    trace_process->EndDictionary();
200

67
    TRACE_EVENT_METADATA1("__metadata", "node",
201
                          "process", std::move(trace_process));
202
203
    // This only runs the first time tracing is enabled
204
67
    controller_->RemoveTraceStateObserver(this);
205
67
  }
206
207
  void OnTraceDisabled() override {
208
    // Do nothing here. This should never be called because the
209
    // observer removes itself when OnTraceEnabled() is called.
210
    UNREACHABLE();
211
  }
212
213
3558
  explicit NodeTraceStateObserver(TracingController* controller) :
214
3558
      controller_(controller) {}
215
7116
  ~NodeTraceStateObserver() override {}
216
217
 private:
218
  TracingController* controller_;
219
};
220
221
7194
static struct {
222
#if NODE_USE_V8_PLATFORM
223
3558
  void Initialize(int thread_pool_size) {
224
3558
    tracing_agent_.reset(new tracing::Agent());
225
3558
    node::tracing::TraceEventHelper::SetAgent(tracing_agent_.get());
226
    node::tracing::TracingController* controller =
227
3558
        tracing_agent_->GetTracingController();
228
3558
    trace_state_observer_.reset(new NodeTraceStateObserver(controller));
229
3558
    controller->AddTraceStateObserver(trace_state_observer_.get());
230
3558
    StartTracingAgent();
231
    // Tracing must be initialized before platform threads are created.
232
3558
    platform_ = new NodePlatform(thread_pool_size, controller);
233
3558
    V8::InitializePlatform(platform_);
234
3558
  }
235
236
3207
  void Dispose() {
237
3207
    platform_->Shutdown();
238
3207
    delete platform_;
239
3207
    platform_ = nullptr;
240
    // Destroy tracing after the platform (and platform threads) have been
241
    // stopped.
242
3207
    tracing_agent_.reset(nullptr);
243
3207
    trace_state_observer_.reset(nullptr);
244
3207
  }
245
246
6464
  void DrainVMTasks(Isolate* isolate) {
247
6464
    platform_->DrainTasks(isolate);
248
6464
  }
249
250
3206
  void CancelVMTasks(Isolate* isolate) {
251
3206
    platform_->CancelPendingDelayedTasks(isolate);
252
3206
  }
253
254
#if HAVE_INSPECTOR
255
3554
  bool StartInspector(Environment* env, const char* script_path) {
256
    // Inspector agent can't fail to start, but if it was configured to listen
257
    // right away on the websocket port and fails to bind/etc, this will return
258
    // false.
259
    return env->inspector_agent()->Start(
260
        script_path == nullptr ? "" : script_path,
261
7108
        env->options()->debug_options(),
262
        env->inspector_host_port(),
263
10662
        true);
264
  }
265
266
72
  bool InspectorStarted(Environment* env) {
267
72
    return env->inspector_agent()->IsListening();
268
  }
269
#endif  // HAVE_INSPECTOR
270
271
3558
  void StartTracingAgent() {
272
3558
    if (per_process_opts->trace_event_categories.empty()) {
273
3493
      tracing_file_writer_ = tracing_agent_->DefaultHandle();
274
    } else {
275
260
      tracing_file_writer_ = tracing_agent_->AddClient(
276
65
          ParseCommaSeparatedSet(per_process_opts->trace_event_categories),
277
          std::unique_ptr<tracing::AsyncTraceWriter>(
278
              new tracing::NodeTraceWriter(
279
130
                  per_process_opts->trace_event_file_pattern)),
280
65
          tracing::Agent::kUseDefaultCategories);
281
    }
282
3558
  }
283
284
3436
  void StopTracingAgent() {
285
3436
    tracing_file_writer_.reset();
286
3436
  }
287
288
7072
  tracing::AgentWriterHandle* GetTracingAgentWriter() {
289
7072
    return &tracing_file_writer_;
290
  }
291
292
14019
  NodePlatform* Platform() {
293
14019
    return platform_;
294
  }
295
296
  std::unique_ptr<NodeTraceStateObserver> trace_state_observer_;
297
  std::unique_ptr<tracing::Agent> tracing_agent_;
298
  tracing::AgentWriterHandle tracing_file_writer_;
299
  NodePlatform* platform_;
300
#else  // !NODE_USE_V8_PLATFORM
301
  void Initialize(int thread_pool_size) {}
302
  void Dispose() {}
303
  void DrainVMTasks(Isolate* isolate) {}
304
  void CancelVMTasks(Isolate* isolate) {}
305
  bool StartInspector(Environment* env, const char* script_path) {
306
    env->ThrowError("Node compiled with NODE_USE_V8_PLATFORM=0");
307
    return true;
308
  }
309
310
  void StartTracingAgent() {
311
    if (!trace_enabled_categories.empty()) {
312
      fprintf(stderr, "Node compiled with NODE_USE_V8_PLATFORM=0, "
313
                      "so event tracing is not available.\n");
314
    }
315
  }
316
  void StopTracingAgent() {}
317
318
  tracing::AgentWriterHandle* GetTracingAgentWriter() {
319
    return nullptr;
320
  }
321
322
  NodePlatform* Platform() {
323
    return nullptr;
324
  }
325
#endif  // !NODE_USE_V8_PLATFORM
326
327
#if !NODE_USE_V8_PLATFORM || !HAVE_INSPECTOR
328
  bool InspectorStarted(Environment* env) {
329
    return false;
330
  }
331
#endif  //  !NODE_USE_V8_PLATFORM || !HAVE_INSPECTOR
332
3597
} v8_platform;
333
334
7072
tracing::AgentWriterHandle* GetTracingAgentWriter() {
335
7072
  return v8_platform.GetTracingAgentWriter();
336
}
337
338
#ifdef __POSIX__
339
static const unsigned kMaxSignal = 32;
340
#endif
341
342
1279
const char* signo_string(int signo) {
343
#define SIGNO_CASE(e)  case e: return #e;
344








1279
  switch (signo) {
345
#ifdef SIGHUP
346
  SIGNO_CASE(SIGHUP);
347
#endif
348
349
#ifdef SIGINT
350
7
  SIGNO_CASE(SIGINT);
351
#endif
352
353
#ifdef SIGQUIT
354
  SIGNO_CASE(SIGQUIT);
355
#endif
356
357
#ifdef SIGILL
358
2
  SIGNO_CASE(SIGILL);
359
#endif
360
361
#ifdef SIGTRAP
362
  SIGNO_CASE(SIGTRAP);
363
#endif
364
365
#ifdef SIGABRT
366
8
  SIGNO_CASE(SIGABRT);
367
#endif
368
369
#ifdef SIGIOT
370
# if SIGABRT != SIGIOT
371
  SIGNO_CASE(SIGIOT);
372
# endif
373
#endif
374
375
#ifdef SIGBUS
376
  SIGNO_CASE(SIGBUS);
377
#endif
378
379
#ifdef SIGFPE
380
  SIGNO_CASE(SIGFPE);
381
#endif
382
383
#ifdef SIGKILL
384
7
  SIGNO_CASE(SIGKILL);
385
#endif
386
387
#ifdef SIGUSR1
388
  SIGNO_CASE(SIGUSR1);
389
#endif
390
391
#ifdef SIGSEGV
392
  SIGNO_CASE(SIGSEGV);
393
#endif
394
395
#ifdef SIGUSR2
396
  SIGNO_CASE(SIGUSR2);
397
#endif
398
399
#ifdef SIGPIPE
400
  SIGNO_CASE(SIGPIPE);
401
#endif
402
403
#ifdef SIGALRM
404
  SIGNO_CASE(SIGALRM);
405
#endif
406
407
162
  SIGNO_CASE(SIGTERM);
408
409
#ifdef SIGCHLD
410
  SIGNO_CASE(SIGCHLD);
411
#endif
412
413
#ifdef SIGSTKFLT
414
  SIGNO_CASE(SIGSTKFLT);
415
#endif
416
417
418
#ifdef SIGCONT
419
  SIGNO_CASE(SIGCONT);
420
#endif
421
422
#ifdef SIGSTOP
423
  SIGNO_CASE(SIGSTOP);
424
#endif
425
426
#ifdef SIGTSTP
427
  SIGNO_CASE(SIGTSTP);
428
#endif
429
430
#ifdef SIGBREAK
431
  SIGNO_CASE(SIGBREAK);
432
#endif
433
434
#ifdef SIGTTIN
435
  SIGNO_CASE(SIGTTIN);
436
#endif
437
438
#ifdef SIGTTOU
439
  SIGNO_CASE(SIGTTOU);
440
#endif
441
442
#ifdef SIGURG
443
  SIGNO_CASE(SIGURG);
444
#endif
445
446
#ifdef SIGXCPU
447
  SIGNO_CASE(SIGXCPU);
448
#endif
449
450
#ifdef SIGXFSZ
451
  SIGNO_CASE(SIGXFSZ);
452
#endif
453
454
#ifdef SIGVTALRM
455
  SIGNO_CASE(SIGVTALRM);
456
#endif
457
458
#ifdef SIGPROF
459
  SIGNO_CASE(SIGPROF);
460
#endif
461
462
#ifdef SIGWINCH
463
  SIGNO_CASE(SIGWINCH);
464
#endif
465
466
#ifdef SIGIO
467
  SIGNO_CASE(SIGIO);
468
#endif
469
470
#ifdef SIGPOLL
471
# if SIGPOLL != SIGIO
472
  SIGNO_CASE(SIGPOLL);
473
# endif
474
#endif
475
476
#ifdef SIGLOST
477
# if SIGLOST != SIGABRT
478
  SIGNO_CASE(SIGLOST);
479
# endif
480
#endif
481
482
#ifdef SIGPWR
483
# if SIGPWR != SIGLOST
484
  SIGNO_CASE(SIGPWR);
485
# endif
486
#endif
487
488
#ifdef SIGINFO
489
# if !defined(SIGPWR) || SIGINFO != SIGPWR
490
  SIGNO_CASE(SIGINFO);
491
# endif
492
#endif
493
494
#ifdef SIGSYS
495
  SIGNO_CASE(SIGSYS);
496
#endif
497
498
1093
  default: return "";
499
  }
500
}
501
502
67756
void* ArrayBufferAllocator::Allocate(size_t size) {
503

67756
  if (zero_fill_field_ || per_process_opts->zero_fill_all_buffers)
504
37883
    return UncheckedCalloc(size);
505
  else
506
29873
    return UncheckedMalloc(size);
507
}
508
509
namespace {
510
511
31
bool ShouldAbortOnUncaughtException(Isolate* isolate) {
512
31
  HandleScope scope(isolate);
513
31
  Environment* env = Environment::GetCurrent(isolate);
514
62
  return env != nullptr &&
515

125
         env->should_abort_on_uncaught_toggle()[0] &&
516
63
         !env->inside_should_not_abort_on_uncaught_scope();
517
}
518
519
}  // anonymous namespace
520
521
522
void AddPromiseHook(Isolate* isolate, promise_hook_func fn, void* arg) {
523
  Environment* env = Environment::GetCurrent(isolate);
524
  CHECK_NOT_NULL(env);
525
  env->AddPromiseHook(fn, arg);
526
}
527
528
18
void AddEnvironmentCleanupHook(Isolate* isolate,
529
                               void (*fun)(void* arg),
530
                               void* arg) {
531
18
  Environment* env = Environment::GetCurrent(isolate);
532
18
  CHECK_NOT_NULL(env);
533
18
  env->AddCleanupHook(fun, arg);
534
18
}
535
536
537
16
void RemoveEnvironmentCleanupHook(Isolate* isolate,
538
                                  void (*fun)(void* arg),
539
                                  void* arg) {
540
16
  Environment* env = Environment::GetCurrent(isolate);
541
16
  CHECK_NOT_NULL(env);
542
16
  env->RemoveCleanupHook(fun, arg);
543
16
}
544
545
730873
MaybeLocal<Value> InternalMakeCallback(Environment* env,
546
                                       Local<Object> recv,
547
                                       const Local<Function> callback,
548
                                       int argc,
549
                                       Local<Value> argv[],
550
                                       async_context asyncContext) {
551
730873
  CHECK(!recv.IsEmpty());
552
730873
  InternalCallbackScope scope(env, recv, asyncContext);
553
731071
  if (scope.Failed()) {
554
239
    return MaybeLocal<Value>();
555
  }
556
557
730826
  Local<Function> domain_cb = env->domain_callback();
558
  MaybeLocal<Value> ret;
559


792369
  if (asyncContext.async_id != 0 || domain_cb.IsEmpty() || recv.IsEmpty()) {
560
1457759
    ret = callback->Call(env->context(), recv, argc, argv);
561
  } else {
562
1943
    std::vector<Local<Value>> args(1 + argc);
563
3886
    args[0] = callback;
564
1943
    std::copy(&argv[0], &argv[argc], args.begin() + 1);
565
5829
    ret = domain_cb->Call(env->context(), recv, args.size(), &args[0]);
566
  }
567
568
730795
  if (ret.IsEmpty()) {
569
65
    scope.MarkAsFailed();
570
65
    return MaybeLocal<Value>();
571
  }
572
573
730730
  scope.Close();
574
730650
  if (scope.Failed()) {
575
1040
    return MaybeLocal<Value>();
576
  }
577
578
729610
  return ret;
579
}
580
581
582
// Public MakeCallback()s
583
584
585
6654
MaybeLocal<Value> MakeCallback(Isolate* isolate,
586
                               Local<Object> recv,
587
                               const char* method,
588
                               int argc,
589
                               Local<Value> argv[],
590
                               async_context asyncContext) {
591
  Local<String> method_string =
592
      String::NewFromUtf8(isolate, method, NewStringType::kNormal)
593
13308
          .ToLocalChecked();
594
6654
  return MakeCallback(isolate, recv, method_string, argc, argv, asyncContext);
595
}
596
597
598
6662
MaybeLocal<Value> MakeCallback(Isolate* isolate,
599
                               Local<Object> recv,
600
                               Local<String> symbol,
601
                               int argc,
602
                               Local<Value> argv[],
603
                               async_context asyncContext) {
604
  Local<Value> callback_v = recv->Get(isolate->GetCurrentContext(),
605
19986
                                      symbol).ToLocalChecked();
606
6662
  if (callback_v.IsEmpty()) return Local<Value>();
607
6662
  if (!callback_v->IsFunction()) return Local<Value>();
608
6662
  Local<Function> callback = callback_v.As<Function>();
609
6662
  return MakeCallback(isolate, recv, callback, argc, argv, asyncContext);
610
}
611
612
613
59625
MaybeLocal<Value> MakeCallback(Isolate* isolate,
614
                               Local<Object> recv,
615
                               Local<Function> callback,
616
                               int argc,
617
                               Local<Value> argv[],
618
                               async_context asyncContext) {
619
  // Observe the following two subtleties:
620
  //
621
  // 1. The environment is retrieved from the callback function's context.
622
  // 2. The context to enter is retrieved from the environment.
623
  //
624
  // Because of the AssignToContext() call in src/node_contextify.cc,
625
  // the two contexts need not be the same.
626
59625
  Environment* env = Environment::GetCurrent(callback->CreationContext());
627
59625
  CHECK_NOT_NULL(env);
628
59625
  Context::Scope context_scope(env->context());
629
  MaybeLocal<Value> ret = InternalMakeCallback(env, recv, callback,
630
59625
                                               argc, argv, asyncContext);
631

59610
  if (ret.IsEmpty() && env->makecallback_depth() == 0) {
632
    // This is only for legacy compatiblity and we may want to look into
633
    // removing/adjusting it.
634
2086
    return Undefined(env->isolate());
635
  }
636
58567
  return ret;
637
}
638
639
640
// Legacy MakeCallback()s
641
642
Local<Value> MakeCallback(Isolate* isolate,
643
                          Local<Object> recv,
644
                          const char* method,
645
                          int argc,
646
                          Local<Value>* argv) {
647
  EscapableHandleScope handle_scope(isolate);
648
  return handle_scope.Escape(
649
      MakeCallback(isolate, recv, method, argc, argv, {0, 0})
650
          .FromMaybe(Local<Value>()));
651
}
652
653
654
Local<Value> MakeCallback(Isolate* isolate,
655
    Local<Object> recv,
656
    Local<String> symbol,
657
    int argc,
658
    Local<Value>* argv) {
659
  EscapableHandleScope handle_scope(isolate);
660
  return handle_scope.Escape(
661
      MakeCallback(isolate, recv, symbol, argc, argv, {0, 0})
662
          .FromMaybe(Local<Value>()));
663
}
664
665
666
Local<Value> MakeCallback(Isolate* isolate,
667
    Local<Object> recv,
668
    Local<Function> callback,
669
    int argc,
670
    Local<Value>* argv) {
671
  EscapableHandleScope handle_scope(isolate);
672
  return handle_scope.Escape(
673
      MakeCallback(isolate, recv, callback, argc, argv, {0, 0})
674
          .FromMaybe(Local<Value>()));
675
}
676
677
3435
static void WaitForInspectorDisconnect(Environment* env) {
678
#if HAVE_INSPECTOR
679
3435
  if (env->inspector_agent()->IsActive()) {
680
    // Restore signal dispositions, the app is done and is no longer
681
    // capable of handling signals.
682
#if defined(__POSIX__) && !defined(NODE_SHARED_MODE)
683
    struct sigaction act;
684
71
    memset(&act, 0, sizeof(act));
685
2272
    for (unsigned nr = 1; nr < kMaxSignal; nr += 1) {
686

2201
      if (nr == SIGKILL || nr == SIGSTOP || nr == SIGPROF)
687
213
        continue;
688
1988
      act.sa_handler = (nr == SIGPIPE) ? SIG_IGN : SIG_DFL;
689
1988
      CHECK_EQ(0, sigaction(nr, &act, nullptr));
690
    }
691
#endif
692
71
    env->inspector_agent()->WaitForDisconnect();
693
  }
694
#endif
695
3435
}
696
697
229
void Exit(const FunctionCallbackInfo<Value>& args) {
698
229
  Environment* env = Environment::GetCurrent(args);
699
229
  WaitForInspectorDisconnect(env);
700
229
  v8_platform.StopTracingAgent();
701
916
  int code = args[0]->Int32Value(env->context()).FromMaybe(0);
702
229
  env->Exit(code);
703
10
}
704
705
29
static Maybe<bool> ProcessEmitWarningGeneric(Environment* env,
706
                                             const char* warning,
707
                                             const char* type = nullptr,
708
                                             const char* code = nullptr) {
709
29
  HandleScope handle_scope(env->isolate());
710
29
  Context::Scope context_scope(env->context());
711
712
29
  Local<Object> process = env->process_object();
713
  Local<Value> emit_warning;
714
58
  if (!process->Get(env->context(),
715
145
                    env->emit_warning_string()).ToLocal(&emit_warning)) {
716
1
    return Nothing<bool>();
717
  }
718
719
28
  if (!emit_warning->IsFunction()) return Just(false);
720
721
28
  int argc = 0;
722
112
  Local<Value> args[3];  // warning, type, code
723
724
  // The caller has to be able to handle a failure anyway, so we might as well
725
  // do proper error checking for string creation.
726
56
  if (!String::NewFromUtf8(env->isolate(),
727
                           warning,
728
84
                           NewStringType::kNormal).ToLocal(&args[argc++])) {
729
    return Nothing<bool>();
730
  }
731
28
  if (type != nullptr) {
732
6
    if (!String::NewFromOneByte(env->isolate(),
733
                                reinterpret_cast<const uint8_t*>(type),
734
3
                                NewStringType::kNormal)
735
12
                                    .ToLocal(&args[argc++])) {
736
      return Nothing<bool>();
737
    }
738

11
    if (code != nullptr &&
739
        !String::NewFromOneByte(env->isolate(),
740
                                reinterpret_cast<const uint8_t*>(code),
741
2
                                NewStringType::kNormal)
742
11
                                    .ToLocal(&args[argc++])) {
743
      return Nothing<bool>();
744
    }
745
  }
746
747
  // MakeCallback() unneeded because emitWarning is internal code, it calls
748
  // process.emit('warning', ...), but does so on the nextTick.
749
56
  if (emit_warning.As<Function>()->Call(env->context(),
750
                                        process,
751
                                        argc,
752
112
                                        args).IsEmpty()) {
753
1
    return Nothing<bool>();
754
  }
755
56
  return Just(true);
756
}
757
758
759
// Call process.emitWarning(str), fmt is a snprintf() format string
760
26
Maybe<bool> ProcessEmitWarning(Environment* env, const char* fmt, ...) {
761
  char warning[1024];
762
  va_list ap;
763
764
26
  va_start(ap, fmt);
765
26
  vsnprintf(warning, sizeof(warning), fmt, ap);
766
26
  va_end(ap);
767
768
26
  return ProcessEmitWarningGeneric(env, warning);
769
}
770
771
772
2
Maybe<bool> ProcessEmitDeprecationWarning(Environment* env,
773
                                          const char* warning,
774
                                          const char* deprecation_code) {
775
  return ProcessEmitWarningGeneric(env,
776
                                   warning,
777
                                   "DeprecationWarning",
778
2
                                   deprecation_code);
779
}
780
781
1294
static void OnMessage(Local<Message> message, Local<Value> error) {
782
1294
  Isolate* isolate = message->GetIsolate();
783
1294
  switch (message->ErrorLevel()) {
784
    case Isolate::MessageErrorLevel::kMessageWarning: {
785
1
      Environment* env = Environment::GetCurrent(isolate);
786
1
      if (!env) {
787
        break;
788
      }
789
      Utf8Value filename(isolate,
790
2
          message->GetScriptOrigin().ResourceName());
791
      // (filename):(line) (message)
792
2
      std::stringstream warning;
793
1
      warning << *filename;
794
1
      warning << ":";
795
3
      warning << message->GetLineNumber(env->context()).FromMaybe(-1);
796
1
      warning << " ";
797
3
      v8::String::Utf8Value msg(isolate, message->Get());
798
1
      warning << *msg;
799
1
      USE(ProcessEmitWarningGeneric(env, warning.str().c_str(), "V8"));
800
2
      break;
801
    }
802
    case Isolate::MessageErrorLevel::kMessageError:
803
1293
      FatalException(isolate, error, message);
804
1169
      break;
805
  }
806
1170
}
807
808
3685
void SetupProcessObject(Environment* env,
809
                        const std::vector<std::string>& args,
810
                        const std::vector<std::string>& exec_args) {
811
3685
  Isolate* isolate = env->isolate();
812
3685
  HandleScope scope(isolate);
813
3685
  Local<Context> context = env->context();
814
815
3685
  Local<Object> process = env->process_object();
816
817
3685
  auto title_string = FIXED_ONE_BYTE_STRING(env->isolate(), "title");
818

18425
  CHECK(process->SetAccessor(
819
      env->context(),
820
      title_string,
821
      ProcessTitleGetter,
822
      env->is_main_thread() ? ProcessTitleSetter : nullptr,
823
      env->as_external(),
824
      DEFAULT,
825
      None,
826
      SideEffectType::kHasNoSideEffect).FromJust());
827
828
  // process.version
829
14740
  READONLY_PROPERTY(process,
830
                    "version",
831
                    FIXED_ONE_BYTE_STRING(env->isolate(), NODE_VERSION));
832
833
  // process.versions
834
3685
  Local<Object> versions = Object::New(env->isolate());
835
11055
  READONLY_PROPERTY(process, "versions", versions);
836
837
#define V(key)                                                                 \
838
  if (!per_process::metadata.versions.key.empty()) {                           \
839
    READONLY_STRING_PROPERTY(                                                  \
840
        versions, #key, per_process::metadata.versions.key);                   \
841
  }
842








180493
  NODE_VERSIONS_KEYS(V)
843
#undef V
844
845
  // process.arch
846
14740
  READONLY_STRING_PROPERTY(process, "arch", per_process::metadata.arch);
847
848
  // process.platform
849
14740
  READONLY_STRING_PROPERTY(process, "platform", per_process::metadata.platform);
850
851
  // process.release
852
3685
  Local<Object> release = Object::New(env->isolate());
853
11055
  READONLY_PROPERTY(process, "release", release);
854
14740
  READONLY_STRING_PROPERTY(release, "name", per_process::metadata.release.name);
855
#if NODE_VERSION_IS_LTS
856
  READONLY_STRING_PROPERTY(release, "lts", per_process::metadata.release.lts);
857
#endif  // NODE_VERSION_IS_LTS
858
859
#ifdef NODE_HAS_RELEASE_URLS
860
  READONLY_STRING_PROPERTY(
861
      release, "sourceUrl", per_process::metadata.release.source_url);
862
  READONLY_STRING_PROPERTY(
863
      release, "headersUrl", per_process::metadata.release.headers_url);
864
#ifdef _WIN32
865
  READONLY_STRING_PROPERTY(
866
      release, "libUrl", per_process::metadata.release.lib_url);
867
#endif  // _WIN32
868
#endif  // NODE_HAS_RELEASE_URLS
869
870
  // process.argv
871
  process->Set(env->context(),
872
               FIXED_ONE_BYTE_STRING(env->isolate(), "argv"),
873
18425
               ToV8Value(env->context(), args).ToLocalChecked()).FromJust();
874
875
  // process.execArgv
876
  process->Set(env->context(),
877
               FIXED_ONE_BYTE_STRING(env->isolate(), "execArgv"),
878
3685
               ToV8Value(env->context(), exec_args)
879
18425
                   .ToLocalChecked()).FromJust();
880
881
  // create process.env
882
  process
883
      ->Set(env->context(),
884
            FIXED_ONE_BYTE_STRING(env->isolate(), "env"),
885
22110
            CreateEnvVarProxy(context, isolate, env->as_external()))
886
7370
      .FromJust();
887
888
14740
  READONLY_PROPERTY(process, "pid",
889
                    Integer::New(env->isolate(), uv_os_getpid()));
890
891
14740
  CHECK(process->SetAccessor(env->context(),
892
                             FIXED_ONE_BYTE_STRING(env->isolate(), "ppid"),
893
                             GetParentProcessId).FromJust());
894
895
  // -e, --eval
896
  // TODO(addaleax): Remove this.
897
3685
  if (env->options()->has_eval_string) {
898
1036
    READONLY_PROPERTY(process,
899
                      "_eval",
900
                      String::NewFromUtf8(
901
                          env->isolate(),
902
                          env->options()->eval_string.c_str(),
903
                          NewStringType::kNormal).ToLocalChecked());
904
  }
905
906
  // -p, --print
907
  // TODO(addaleax): Remove this.
908
3685
  if (env->options()->print_eval) {
909
416
    READONLY_PROPERTY(process, "_print_eval", True(env->isolate()));
910
  }
911
912
  // -c, --check
913
  // TODO(addaleax): Remove this.
914
3685
  if (env->options()->syntax_check_only) {
915
120
    READONLY_PROPERTY(process, "_syntax_check_only", True(env->isolate()));
916
  }
917
918
  // -i, --interactive
919
  // TODO(addaleax): Remove this.
920
3685
  if (env->options()->force_repl) {
921
36
    READONLY_PROPERTY(process, "_forceRepl", True(env->isolate()));
922
  }
923
924
  // -r, --require
925
  // TODO(addaleax): Remove this.
926
  const std::vector<std::string>& preload_modules =
927
3685
      env->options()->preload_modules;
928
3685
  if (!preload_modules.empty()) {
929
84
    READONLY_PROPERTY(process,
930
                      "_preload_modules",
931
                      ToV8Value(env->context(), preload_modules)
932
                          .ToLocalChecked());
933
  }
934
935
  // --no-deprecation
936
3685
  if (env->options()->no_deprecation) {
937
16
    READONLY_PROPERTY(process, "noDeprecation", True(env->isolate()));
938
  }
939
940
  // --no-warnings
941
3685
  if (env->options()->no_warnings) {
942
116
    READONLY_PROPERTY(process, "noProcessWarnings", True(env->isolate()));
943
  }
944
945
  // --trace-warnings
946
3685
  if (env->options()->trace_warnings) {
947
12
    READONLY_PROPERTY(process, "traceProcessWarnings", True(env->isolate()));
948
  }
949
950
  // --throw-deprecation
951
3685
  if (env->options()->throw_deprecation) {
952
4
    READONLY_PROPERTY(process, "throwDeprecation", True(env->isolate()));
953
  }
954
955
#ifdef NODE_NO_BROWSER_GLOBALS
956
  // configure --no-browser-globals
957
  READONLY_PROPERTY(process, "_noBrowserGlobals", True(env->isolate()));
958
#endif  // NODE_NO_BROWSER_GLOBALS
959
960
  // --prof-process
961
  // TODO(addaleax): Remove this.
962
3685
  if (env->options()->prof_process) {
963
4
    READONLY_PROPERTY(process, "profProcess", True(env->isolate()));
964
  }
965
966
  // --trace-deprecation
967
3685
  if (env->options()->trace_deprecation) {
968
8
    READONLY_PROPERTY(process, "traceDeprecation", True(env->isolate()));
969
  }
970
971
  // TODO(refack): move the following 4 to `node_config`
972
  // --inspect-brk
973
3685
  if (env->options()->debug_options().wait_for_connect()) {
974
52
    READONLY_DONT_ENUM_PROPERTY(process,
975
                                "_breakFirstLine", True(env->isolate()));
976
  }
977
978
3685
  if (env->options()->debug_options().break_node_first_line) {
979
    READONLY_DONT_ENUM_PROPERTY(process,
980
                                "_breakNodeFirstLine", True(env->isolate()));
981
  }
982
983
  // --inspect --debug-brk
984
3685
  if (env->options()->debug_options().deprecated_invocation()) {
985
4
    READONLY_DONT_ENUM_PROPERTY(process,
986
                                "_deprecatedDebugBrk", True(env->isolate()));
987
  }
988
989
  // --debug or, --debug-brk without --inspect
990
3685
  if (env->options()->debug_options().invalid_invocation()) {
991
8
    READONLY_DONT_ENUM_PROPERTY(process,
992
                                "_invalidDebug", True(env->isolate()));
993
  }
994
995
  // --security-revert flags
996
#define V(code, _, __)                                                        \
997
  do {                                                                        \
998
    if (IsReverted(SECURITY_REVERT_ ## code)) {                               \
999
      READONLY_PROPERTY(process, "REVERT_" #code, True(env->isolate()));      \
1000
    }                                                                         \
1001
  } while (0);
1002
  SECURITY_REVERSIONS(V)
1003
#undef V
1004
1005
  {
1006
3685
    size_t exec_path_len = 2 * PATH_MAX;
1007
3685
    std::vector<char> exec_path(exec_path_len);
1008
    Local<String> exec_path_value;
1009
3685
    if (uv_exepath(exec_path.data(), &exec_path_len) == 0) {
1010
      exec_path_value = String::NewFromUtf8(env->isolate(),
1011
3685
                                            exec_path.data(),
1012
                                            NewStringType::kInternalized,
1013
11055
                                            exec_path_len).ToLocalChecked();
1014
    } else {
1015
      exec_path_value = String::NewFromUtf8(env->isolate(), args[0].c_str(),
1016
          NewStringType::kInternalized).ToLocalChecked();
1017
    }
1018
    process->Set(env->context(),
1019
                 FIXED_ONE_BYTE_STRING(env->isolate(), "execPath"),
1020
14740
                 exec_path_value).FromJust();
1021
  }
1022
1023
3685
  auto debug_port_string = FIXED_ONE_BYTE_STRING(env->isolate(), "debugPort");
1024

18425
  CHECK(process->SetAccessor(env->context(),
1025
                             debug_port_string,
1026
                             DebugPortGetter,
1027
                             env->is_main_thread() ? DebugPortSetter : nullptr,
1028
3685
                             env->as_external()).FromJust());
1029
3685
}
1030
1031
1032
void SignalExit(int signo) {
1033
  uv_tty_reset_mode();
1034
#ifdef __FreeBSD__
1035
  // FreeBSD has a nasty bug, see RegisterSignalHandler for details
1036
  struct sigaction sa;
1037
  memset(&sa, 0, sizeof(sa));
1038
  sa.sa_handler = SIG_DFL;
1039
  CHECK_EQ(sigaction(signo, &sa, nullptr), 0);
1040
#endif
1041
  raise(signo);
1042
}
1043
1044
7342
static MaybeLocal<Value> ExecuteBootstrapper(
1045
    Environment* env,
1046
    const char* id,
1047
    std::vector<Local<String>>* parameters,
1048
    std::vector<Local<Value>>* arguments) {
1049
  MaybeLocal<Value> ret = per_process::native_module_loader.CompileAndCall(
1050
7342
      env->context(), id, parameters, arguments, env);
1051
1052
  // If there was an error during bootstrap then it was either handled by the
1053
  // FatalException handler or it's unrecoverable (e.g. max call stack
1054
  // exceeded). Either way, clear the stack so that the AsyncCallbackScope
1055
  // destructor doesn't fail on the id check.
1056
  // There are only two ways to have a stack size > 1: 1) the user manually
1057
  // called MakeCallback or 2) user awaited during bootstrap, which triggered
1058
  // _tickCallback().
1059
7340
  if (ret.IsEmpty()) {
1060
10
    env->async_hooks()->clear_async_id_stack();
1061
  }
1062
1063
7340
  return ret;
1064
}
1065
1066
3671
void LoadEnvironment(Environment* env) {
1067
3671
  RunBootstrapping(env);
1068
3669
  StartExecution(env);
1069
3451
}
1070
1071
3671
void RunBootstrapping(Environment* env) {
1072
3671
  CHECK(!env->has_run_bootstrapping_code());
1073
3671
  env->set_has_run_bootstrapping_code(true);
1074
1075
3671
  HandleScope handle_scope(env->isolate());
1076
3671
  Isolate* isolate = env->isolate();
1077
3671
  Local<Context> context = env->context();
1078
1079
  // Add a reference to the global object
1080
3671
  Local<Object> global = context->Global();
1081
1082
#if defined HAVE_DTRACE || defined HAVE_ETW
1083
  InitDTrace(env, global);
1084
#endif
1085
1086
3671
  Local<Object> process = env->process_object();
1087
1088
  // Setting global properties for the bootstrappers to use:
1089
  // - global
1090
  // - process._rawDebug
1091
  // Expose the global object as a property on itself
1092
  // (Allows you to set stuff on `global` from anywhere in JavaScript.)
1093
11013
  global->Set(context, FIXED_ONE_BYTE_STRING(env->isolate(), "global"), global)
1094
7342
      .FromJust();
1095
3671
  env->SetMethod(process, "_rawDebug", RawDebug);
1096
1097
  // Create binding loaders
1098
  std::vector<Local<String>> loaders_params = {
1099
      env->process_string(),
1100
      FIXED_ONE_BYTE_STRING(isolate, "getBinding"),
1101
      FIXED_ONE_BYTE_STRING(isolate, "getLinkedBinding"),
1102
      FIXED_ONE_BYTE_STRING(isolate, "getInternalBinding"),
1103
7330
      FIXED_ONE_BYTE_STRING(isolate, "debugBreak")};
1104
  std::vector<Local<Value>> loaders_args = {
1105
      process,
1106
3671
      env->NewFunctionTemplate(binding::GetBinding)
1107
11013
          ->GetFunction(context)
1108
          .ToLocalChecked(),
1109
3671
      env->NewFunctionTemplate(binding::GetLinkedBinding)
1110
11013
          ->GetFunction(context)
1111
          .ToLocalChecked(),
1112
3671
      env->NewFunctionTemplate(binding::GetInternalBinding)
1113
11013
          ->GetFunction(context)
1114
          .ToLocalChecked(),
1115
      Boolean::New(isolate,
1116
29356
                   env->options()->debug_options().break_node_first_line)};
1117
1118
  MaybeLocal<Value> loader_exports;
1119
  // Bootstrap internal loaders
1120
  loader_exports = ExecuteBootstrapper(
1121
3671
      env, "internal/bootstrap/loaders", &loaders_params, &loaders_args);
1122
3671
  if (loader_exports.IsEmpty()) {
1123
    return;
1124
  }
1125
1126
  // process, loaderExports, isMainThread
1127
  std::vector<Local<String>> node_params = {
1128
      env->process_string(),
1129
      FIXED_ONE_BYTE_STRING(isolate, "loaderExports"),
1130
7330
      FIXED_ONE_BYTE_STRING(isolate, "isMainThread")};
1131
  std::vector<Local<Value>> node_args = {
1132
      process,
1133
      loader_exports.ToLocalChecked(),
1134
11001
      Boolean::New(isolate, env->is_main_thread())};
1135
1136
  Local<Value> start_execution;
1137
7338
  if (!ExecuteBootstrapper(
1138
          env, "internal/bootstrap/node", &node_params, &node_args)
1139
11009
          .ToLocal(&start_execution)) {
1140
10
    return;
1141
  }
1142
1143
3659
  if (start_execution->IsFunction())
1144
7318
    env->set_start_execution_function(start_execution.As<Function>());
1145
}
1146
1147
3669
void StartExecution(Environment* env) {
1148
3669
  HandleScope handle_scope(env->isolate());
1149
  // We have to use Local<>::New because of the optimized way in which we access
1150
  // the object in the env->...() getters, which does not play well with
1151
  // resetting the handle while we're accessing the object through the Local<>.
1152
  Local<Function> start_execution =
1153
7338
      Local<Function>::New(env->isolate(), env->start_execution_function());
1154
3669
  env->set_start_execution_function(Local<Function>());
1155
1156
7120
  if (start_execution.IsEmpty()) return;
1157
  USE(start_execution->Call(
1158
10977
      env->context(), Undefined(env->isolate()), 0, nullptr));
1159
}
1160
1161
3554
static void StartInspector(Environment* env, const char* path) {
1162
#if HAVE_INSPECTOR
1163
3554
  CHECK(!env->inspector_agent()->IsListening());
1164
3554
  v8_platform.StartInspector(env, path);
1165
#endif  // HAVE_INSPECTOR
1166
3554
}
1167
1168
1169
#ifdef __POSIX__
1170
10924
void RegisterSignalHandler(int signal,
1171
                           void (*handler)(int signal),
1172
                           bool reset_handler) {
1173
  struct sigaction sa;
1174
10924
  memset(&sa, 0, sizeof(sa));
1175
10924
  sa.sa_handler = handler;
1176
#ifndef __FreeBSD__
1177
  // FreeBSD has a nasty bug with SA_RESETHAND reseting the SA_SIGINFO, that is
1178
  // in turn set for a libthr wrapper. This leads to a crash.
1179
  // Work around the issue by manually setting SIG_DFL in the signal handler
1180
10924
  sa.sa_flags = reset_handler ? SA_RESETHAND : 0;
1181
#endif
1182
10924
  sigfillset(&sa.sa_mask);
1183
10924
  CHECK_EQ(sigaction(signal, &sa, nullptr), 0);
1184
10924
}
1185
1186
#endif  // __POSIX__
1187
1188
3596
inline void PlatformInit() {
1189
#ifdef __POSIX__
1190
#if HAVE_INSPECTOR
1191
  sigset_t sigmask;
1192
3596
  sigemptyset(&sigmask);
1193
3596
  sigaddset(&sigmask, SIGUSR1);
1194
3596
  const int err = pthread_sigmask(SIG_SETMASK, &sigmask, nullptr);
1195
#endif  // HAVE_INSPECTOR
1196
1197
  // Make sure file descriptors 0-2 are valid before we start logging anything.
1198
14384
  for (int fd = STDIN_FILENO; fd <= STDERR_FILENO; fd += 1) {
1199
    struct stat ignored;
1200
10788
    if (fstat(fd, &ignored) == 0)
1201
10786
      continue;
1202
    // Anything but EBADF means something is seriously wrong.  We don't
1203
    // have to special-case EINTR, fstat() is not interruptible.
1204
2
    if (errno != EBADF)
1205
      ABORT();
1206
2
    if (fd != open("/dev/null", O_RDWR))
1207
      ABORT();
1208
  }
1209
1210
#if HAVE_INSPECTOR
1211
3596
  CHECK_EQ(err, 0);
1212
#endif  // HAVE_INSPECTOR
1213
1214
#ifndef NODE_SHARED_MODE
1215
  // Restore signal dispositions, the parent process may have changed them.
1216
  struct sigaction act;
1217
3596
  memset(&act, 0, sizeof(act));
1218
1219
  // The hard-coded upper limit is because NSIG is not very reliable; on Linux,
1220
  // it evaluates to 32, 34 or 64, depending on whether RT signals are enabled.
1221
  // Counting up to SIGRTMIN doesn't work for the same reason.
1222
115072
  for (unsigned nr = 1; nr < kMaxSignal; nr += 1) {
1223

111476
    if (nr == SIGKILL || nr == SIGSTOP)
1224
7192
      continue;
1225
104284
    act.sa_handler = (nr == SIGPIPE) ? SIG_IGN : SIG_DFL;
1226
104284
    CHECK_EQ(0, sigaction(nr, &act, nullptr));
1227
  }
1228
#endif  // !NODE_SHARED_MODE
1229
1230
3596
  RegisterSignalHandler(SIGINT, SignalExit, true);
1231
3596
  RegisterSignalHandler(SIGTERM, SignalExit, true);
1232
1233
  // Raise the open file descriptor limit.
1234
  struct rlimit lim;
1235

3596
  if (getrlimit(RLIMIT_NOFILE, &lim) == 0 && lim.rlim_cur != lim.rlim_max) {
1236
    // Do a binary search for the limit.
1237
    rlim_t min = lim.rlim_cur;
1238
    rlim_t max = 1 << 20;
1239
    // But if there's a defined upper bound, don't search, just set it.
1240
    if (lim.rlim_max != RLIM_INFINITY) {
1241
      min = lim.rlim_max;
1242
      max = lim.rlim_max;
1243
    }
1244
    do {
1245
      lim.rlim_cur = min + (max - min) / 2;
1246
      if (setrlimit(RLIMIT_NOFILE, &lim)) {
1247
        max = lim.rlim_cur;
1248
      } else {
1249
        min = lim.rlim_cur;
1250
      }
1251
    } while (min + 1 < max);
1252
  }
1253
#endif  // __POSIX__
1254
#ifdef _WIN32
1255
  for (int fd = 0; fd <= 2; ++fd) {
1256
    auto handle = reinterpret_cast<HANDLE>(_get_osfhandle(fd));
1257
    if (handle == INVALID_HANDLE_VALUE ||
1258
        GetFileType(handle) == FILE_TYPE_UNKNOWN) {
1259
      // Ignore _close result. If it fails or not depends on used Windows
1260
      // version. We will just check _open result.
1261
      _close(fd);
1262
      if (fd != _open("nul", _O_RDWR))
1263
        ABORT();
1264
    }
1265
  }
1266
#endif  // _WIN32
1267
3596
}
1268
1269
7027
void ProcessArgv(std::vector<std::string>* args,
1270
                 std::vector<std::string>* exec_args,
1271
                 bool is_env) {
1272
  // Parse a few arguments which are specific to Node.
1273
7027
  std::vector<std::string> v8_args;
1274
14014
  std::vector<std::string> errors{};
1275
1276
  {
1277
    // TODO(addaleax): The mutex here should ideally be held during the
1278
    // entire function, but that doesn't play well with the exit() calls below.
1279
7027
    Mutex::ScopedLock lock(per_process_opts_mutex);
1280
    options_parser::PerProcessOptionsParser::instance.Parse(
1281
        args,
1282
        exec_args,
1283
        &v8_args,
1284
        per_process_opts.get(),
1285
        is_env ? kAllowedInEnvironment : kDisallowedInEnvironment,
1286
7027
        &errors);
1287
  }
1288
1289
7027
  if (!errors.empty()) {
1290
52
    for (auto const& error : errors) {
1291
26
      fprintf(stderr, "%s: %s\n", args->at(0).c_str(), error.c_str());
1292
    }
1293
26
    exit(9);
1294
  }
1295
1296
7001
  if (per_process_opts->print_version) {
1297
2
    printf("%s\n", NODE_VERSION);
1298
2
    exit(0);
1299
  }
1300
1301
6999
  if (per_process_opts->print_v8_help) {
1302
1
    V8::SetFlagsFromString("--help", 6);
1303
    exit(0);
1304
  }
1305
1306
6998
  for (const std::string& cve : per_process_opts->security_reverts)
1307
    Revert(cve.c_str());
1308
1309
13985
  auto env_opts = per_process_opts->per_isolate->per_env;
1310
13996
  if (std::find(v8_args.begin(), v8_args.end(),
1311


41940
                "--abort-on-uncaught-exception") != v8_args.end() ||
1312
      std::find(v8_args.begin(), v8_args.end(),
1313

27944
                "--abort_on_uncaught_exception") != v8_args.end()) {
1314
19
    env_opts->abort_on_uncaught_exception = true;
1315
  }
1316
1317
  // TODO(bnoordhuis) Intercept --prof arguments and start the CPU profiler
1318
  // manually?  That would give us a little more control over its runtime
1319
  // behavior but it could also interfere with the user's intentions in ways
1320
  // we fail to anticipate.  Dillema.
1321
6998
  if (std::find(v8_args.begin(), v8_args.end(), "--prof") != v8_args.end()) {
1322
1
    v8_is_profiling = true;
1323
  }
1324
1325
#ifdef __POSIX__
1326
  // Block SIGPROF signals when sleeping in epoll_wait/kevent/etc.  Avoids the
1327
  // performance penalty of frequent EINTR wakeups when the profiler is running.
1328
  // Only do this for v8.log profiling, as it breaks v8::CpuProfiler users.
1329
6998
  if (v8_is_profiling) {
1330
1
    uv_loop_configure(uv_default_loop(), UV_LOOP_BLOCK_SIGNAL, SIGPROF);
1331
  }
1332
#endif
1333
1334
13985
  std::vector<char*> v8_args_as_char_ptr(v8_args.size());
1335
6998
  if (v8_args.size() > 0) {
1336
14103
    for (size_t i = 0; i < v8_args.size(); ++i)
1337
7105
      v8_args_as_char_ptr[i] = &v8_args[i][0];
1338
6998
    int argc = v8_args.size();
1339
6998
    V8::SetFlagsFromCommandLine(&argc, &v8_args_as_char_ptr[0], true);
1340
6998
    v8_args_as_char_ptr.resize(argc);
1341
  }
1342
1343
  // Anything that's still in v8_argv is not a V8 or a node option.
1344
7011
  for (size_t i = 1; i < v8_args_as_char_ptr.size(); i++) {
1345
    fprintf(stderr, "%s: bad option: %s\n",
1346
13
            args->at(0).c_str(), v8_args_as_char_ptr[i]);
1347
  }
1348
1349
6998
  if (v8_args_as_char_ptr.size() > 1) {
1350
11
    exit(9);
1351
6987
  }
1352
6987
}
1353
1354
1355
3596
void Init(std::vector<std::string>* argv,
1356
          std::vector<std::string>* exec_argv) {
1357
  // Initialize prog_start_time to get relative uptime.
1358
3596
  prog_start_time = static_cast<double>(uv_now(uv_default_loop()));
1359
1360
  // Register built-in modules
1361
3596
  binding::RegisterBuiltinModules();
1362
1363
  // Make inherited handles noninheritable.
1364
3596
  uv_disable_stdio_inheritance();
1365
1366
#if defined(NODE_V8_OPTIONS)
1367
  // Should come before the call to V8::SetFlagsFromCommandLine()
1368
  // so the user can disable a flag --foo at run-time by passing
1369
  // --no_foo from the command line.
1370
  V8::SetFlagsFromString(NODE_V8_OPTIONS, sizeof(NODE_V8_OPTIONS) - 1);
1371
#endif
1372
1373
  std::shared_ptr<EnvironmentOptions> default_env_options =
1374
3596
      per_process_opts->per_isolate->per_env;
1375
  {
1376
3596
    std::string text;
1377
3596
    default_env_options->pending_deprecation =
1378

3597
        credentials::SafeGetenv("NODE_PENDING_DEPRECATION", &text) &&
1379
3597
        text[0] == '1';
1380
  }
1381
1382
  // Allow for environment set preserving symlinks.
1383
  {
1384
3596
    std::string text;
1385
3596
    default_env_options->preserve_symlinks =
1386

3597
        credentials::SafeGetenv("NODE_PRESERVE_SYMLINKS", &text) &&
1387
3597
        text[0] == '1';
1388
  }
1389
1390
  {
1391
3596
    std::string text;
1392
3596
    default_env_options->preserve_symlinks_main =
1393

3596
        credentials::SafeGetenv("NODE_PRESERVE_SYMLINKS_MAIN", &text) &&
1394
3596
        text[0] == '1';
1395
  }
1396
1397
3596
  if (default_env_options->redirect_warnings.empty()) {
1398
    credentials::SafeGetenv("NODE_REDIRECT_WARNINGS",
1399
3596
                            &default_env_options->redirect_warnings);
1400
  }
1401
1402
#if HAVE_OPENSSL
1403
3596
  std::string* openssl_config = &per_process_opts->openssl_config;
1404
3596
  if (openssl_config->empty()) {
1405
3596
    credentials::SafeGetenv("OPENSSL_CONF", openssl_config);
1406
  }
1407
#endif
1408
1409
#if !defined(NODE_WITHOUT_NODE_OPTIONS)
1410
7150
  std::string node_options;
1411
3596
  if (credentials::SafeGetenv("NODE_OPTIONS", &node_options)) {
1412
3446
    std::vector<std::string> env_argv;
1413
    // [0] is expected to be the program name, fill it in from the real argv.
1414
3446
    env_argv.push_back(argv->at(0));
1415
1416
    // Split NODE_OPTIONS at each ' ' character.
1417
3446
    std::string::size_type index = std::string::npos;
1418
3455
    do {
1419
3455
      std::string::size_type prev_index = index;
1420
3455
      index = node_options.find(' ', index + 1);
1421
3455
      if (index - prev_index == 1) continue;
1422
1423
      const std::string option = node_options.substr(
1424
3455
          prev_index + 1, index - prev_index - 1);
1425
3455
      if (!option.empty())
1426
51
        env_argv.emplace_back(std::move(option));
1427
    } while (index != std::string::npos);
1428
1429
1430
3446
    ProcessArgv(&env_argv, nullptr, true);
1431
  }
1432
#endif
1433
1434
3581
  ProcessArgv(argv, exec_argv, false);
1435
1436
  // Set the process.title immediately after processing argv if --title is set.
1437
3556
  if (!per_process_opts->title.empty())
1438
2
    uv_set_process_title(per_process_opts->title.c_str());
1439
1440
#if defined(NODE_HAVE_I18N_SUPPORT)
1441
  // If the parameter isn't given, use the env variable.
1442
3556
  if (per_process_opts->icu_data_dir.empty())
1443
3555
    credentials::SafeGetenv("NODE_ICU_DATA", &per_process_opts->icu_data_dir);
1444
  // Initialize ICU.
1445
  // If icu_data_dir is empty here, it will load the 'minimal' data.
1446
3556
  if (!i18n::InitializeICUDirectory(per_process_opts->icu_data_dir)) {
1447
    fprintf(stderr,
1448
            "%s: could not initialize ICU "
1449
            "(check NODE_ICU_DATA or --icu-data-dir parameters)\n",
1450
2
            argv->at(0).c_str());
1451
2
    exit(9);
1452
  }
1453
3554
  per_process::metadata.versions.InitializeIntlVersions();
1454
#endif
1455
1456
  // We should set node_is_initialized here instead of in node::Start,
1457
  // otherwise embedders using node::Init to initialize everything will not be
1458
  // able to set it and native modules will not load for them.
1459
7108
  node_is_initialized = true;
1460
3554
}
1461
1462
// TODO(addaleax): Deprecate and eventually remove this.
1463
void Init(int* argc,
1464
          const char** argv,
1465
          int* exec_argc,
1466
          const char*** exec_argv) {
1467
  std::vector<std::string> argv_(argv, argv + *argc);  // NOLINT
1468
  std::vector<std::string> exec_argv_;
1469
1470
  Init(&argv_, &exec_argv_);
1471
1472
  *argc = argv_.size();
1473
  *exec_argc = exec_argv_.size();
1474
  // These leak memory, because, in the original code of this function, no
1475
  // extra allocations were visible. This should be okay because this function
1476
  // is only supposed to be called once per process, though.
1477
  *exec_argv = Malloc<const char*>(*exec_argc);
1478
  for (int i = 0; i < *exec_argc; ++i)
1479
    (*exec_argv)[i] = strdup(exec_argv_[i].c_str());
1480
  for (int i = 0; i < *argc; ++i)
1481
    argv[i] = strdup(argv_[i].c_str());
1482
}
1483
1484
3329
void RunAtExit(Environment* env) {
1485
3329
  env->RunAtExitCallbacks();
1486
3329
}
1487
1488
1489
7
uv_loop_t* GetCurrentEventLoop(Isolate* isolate) {
1490
7
  HandleScope handle_scope(isolate);
1491
7
  Local<Context> context = isolate->GetCurrentContext();
1492
7
  if (context.IsEmpty())
1493
    return nullptr;
1494
7
  Environment* env = Environment::GetCurrent(context);
1495
7
  if (env == nullptr)
1496
    return nullptr;
1497
7
  return env->event_loop();
1498
}
1499
1500
1501
8
void AtExit(void (*cb)(void* arg), void* arg) {
1502
8
  auto env = Environment::GetThreadLocalEnv();
1503
8
  AtExit(env, cb, arg);
1504
8
}
1505
1506
1507
12
void AtExit(Environment* env, void (*cb)(void* arg), void* arg) {
1508
12
  CHECK_NOT_NULL(env);
1509
12
  env->AtExit(cb, arg);
1510
12
}
1511
1512
1513
3258
void RunBeforeExit(Environment* env) {
1514
3258
  env->RunBeforeExitCallbacks();
1515
1516
3258
  if (!uv_loop_alive(env->event_loop()))
1517
3258
    EmitBeforeExit(env);
1518
3255
}
1519
1520
1521
3349
void EmitBeforeExit(Environment* env) {
1522
3349
  HandleScope handle_scope(env->isolate());
1523
3349
  Context::Scope context_scope(env->context());
1524
3349
  Local<Object> process_object = env->process_object();
1525
3349
  Local<String> exit_code = env->exit_code_string();
1526
  Local<Value> args[] = {
1527
    FIXED_ONE_BYTE_STRING(env->isolate(), "beforeExit"),
1528
10047
    process_object->Get(env->context(), exit_code).ToLocalChecked()
1529
13396
        ->ToInteger(env->context()).ToLocalChecked()
1530
16745
  };
1531
  MakeCallback(env->isolate(),
1532
3349
               process_object, "emit", arraysize(args), args,
1533
13390
               {0, 0}).ToLocalChecked();
1534
3346
}
1535
1536
1537
3303
int EmitExit(Environment* env) {
1538
  // process.emit('exit')
1539
3303
  HandleScope handle_scope(env->isolate());
1540
3303
  Context::Scope context_scope(env->context());
1541
3303
  Local<Object> process_object = env->process_object();
1542
  process_object->Set(env->context(),
1543
                      FIXED_ONE_BYTE_STRING(env->isolate(), "_exiting"),
1544
16515
                      True(env->isolate())).FromJust();
1545
1546
3303
  Local<String> exit_code = env->exit_code_string();
1547
9909
  int code = process_object->Get(env->context(), exit_code).ToLocalChecked()
1548
13212
      ->Int32Value(env->context()).ToChecked();
1549
1550
  Local<Value> args[] = {
1551
    FIXED_ONE_BYTE_STRING(env->isolate(), "exit"),
1552
    Integer::New(env->isolate(), code)
1553
9909
  };
1554
1555
  MakeCallback(env->isolate(),
1556
3303
               process_object, "emit", arraysize(args), args,
1557
9903
               {0, 0}).ToLocalChecked();
1558
1559
  // Reload exit code, it may be changed by `emit('exit')`
1560
9891
  return process_object->Get(env->context(), exit_code).ToLocalChecked()
1561
16485
      ->Int32Value(env->context()).ToChecked();
1562
}
1563
1564
1565
3700
ArrayBufferAllocator* CreateArrayBufferAllocator() {
1566
3700
  return new ArrayBufferAllocator();
1567
}
1568
1569
1570
3352
void FreeArrayBufferAllocator(ArrayBufferAllocator* allocator) {
1571
3352
  delete allocator;
1572
3352
}
1573
1574
1575
3685
IsolateData* CreateIsolateData(
1576
    Isolate* isolate,
1577
    uv_loop_t* loop,
1578
    MultiIsolatePlatform* platform,
1579
    ArrayBufferAllocator* allocator) {
1580
  return new IsolateData(
1581
        isolate,
1582
        loop,
1583
        platform,
1584
3685
        allocator != nullptr ? allocator->zero_fill_field() : nullptr);
1585
}
1586
1587
1588
3338
void FreeIsolateData(IsolateData* isolate_data) {
1589
3338
  delete isolate_data;
1590
3338
}
1591
1592
1593
12
Environment* CreateEnvironment(IsolateData* isolate_data,
1594
                               Local<Context> context,
1595
                               int argc,
1596
                               const char* const* argv,
1597
                               int exec_argc,
1598
                               const char* const* exec_argv) {
1599
12
  Isolate* isolate = context->GetIsolate();
1600
12
  HandleScope handle_scope(isolate);
1601
  Context::Scope context_scope(context);
1602
  // TODO(addaleax): This is a much better place for parsing per-Environment
1603
  // options than the global parse call.
1604
24
  std::vector<std::string> args(argv, argv + argc);
1605
24
  std::vector<std::string> exec_args(exec_argv, exec_argv + exec_argc);
1606
12
  Environment* env = new Environment(isolate_data, context);
1607
12
  env->Start(args, exec_args, v8_is_profiling);
1608
24
  return env;
1609
}
1610
1611
1612
131
void FreeEnvironment(Environment* env) {
1613
131
  env->RunCleanup();
1614
131
  delete env;
1615
131
}
1616
1617
1618
3
Environment* GetCurrentEnvironment(Local<Context> context) {
1619
3
  return Environment::GetCurrent(context);
1620
}
1621
1622
1623
MultiIsolatePlatform* GetMainThreadMultiIsolatePlatform() {
1624
  return v8_platform.Platform();
1625
}
1626
1627
1628
MultiIsolatePlatform* CreatePlatform(
1629
    int thread_pool_size,
1630
    node::tracing::TracingController* tracing_controller) {
1631
  return new NodePlatform(thread_pool_size, tracing_controller);
1632
}
1633
1634
1635
3558
MultiIsolatePlatform* InitializeV8Platform(int thread_pool_size) {
1636
3558
  v8_platform.Initialize(thread_pool_size);
1637
3558
  return v8_platform.Platform();
1638
}
1639
1640
1641
void FreePlatform(MultiIsolatePlatform* platform) {
1642
  delete platform;
1643
}
1644
1645
4151
Local<Context> NewContext(Isolate* isolate,
1646
                          Local<ObjectTemplate> object_template) {
1647
8302
  auto context = Context::New(isolate, nullptr, object_template);
1648
4151
  if (context.IsEmpty()) return context;
1649
4151
  HandleScope handle_scope(isolate);
1650
1651
  context->SetEmbedderData(
1652
4151
      ContextEmbedderIndex::kAllowWasmCodeGeneration, True(isolate));
1653
1654
  {
1655
    // Run lib/internal/per_context.js
1656
    Context::Scope context_scope(context);
1657
1658
    std::vector<Local<String>> parameters = {
1659
8233
        FIXED_ONE_BYTE_STRING(isolate, "global")};
1660
12384
    std::vector<Local<Value>> arguments = {context->Global()};
1661
    MaybeLocal<Value> result = per_process::native_module_loader.CompileAndCall(
1662
4151
        context, "internal/per_context", &parameters, &arguments, nullptr);
1663
4151
    if (result.IsEmpty()) {
1664
      // Execution failed during context creation.
1665
      // TODO(joyeecheung): deprecate this signature and return a MaybeLocal.
1666
69
      return Local<Context>();
1667
4082
    }
1668
  }
1669
1670
4082
  return context;
1671
}
1672
1673
1674
3554
inline int Start(Isolate* isolate, IsolateData* isolate_data,
1675
                 const std::vector<std::string>& args,
1676
                 const std::vector<std::string>& exec_args) {
1677
3554
  HandleScope handle_scope(isolate);
1678
3554
  Local<Context> context = NewContext(isolate);
1679
  Context::Scope context_scope(context);
1680
6761
  Environment env(isolate_data, context);
1681
3554
  env.Start(args, exec_args, v8_is_profiling);
1682
1683
3554
  const char* path = args.size() > 1 ? args[1].c_str() : nullptr;
1684
3554
  StartInspector(&env, path);
1685
1686


3626
  if (env.options()->debug_options().inspector_enabled &&
1687
72
      !v8_platform.InspectorStarted(&env)) {
1688
1
    return 12;  // Signal internal error.
1689
  }
1690
1691
  {
1692
3553
    Environment::AsyncCallbackScope callback_scope(&env);
1693
3553
    env.async_hooks()->push_async_ids(1, 0);
1694
3553
    LoadEnvironment(&env);
1695
3333
    env.async_hooks()->pop_async_id(1);
1696
  }
1697
1698
  {
1699
3332
    SealHandleScope seal(isolate);
1700
    bool more;
1701
    env.performance_state()->Mark(
1702
3332
        node::performance::NODE_PERFORMANCE_MILESTONE_LOOP_START);
1703
3255
    do {
1704
3375
      uv_run(env.event_loop(), UV_RUN_DEFAULT);
1705
1706
3258
      v8_platform.DrainVMTasks(isolate);
1707
1708
3258
      more = uv_loop_alive(env.event_loop());
1709
3258
      if (more)
1710
        continue;
1711
1712
3258
      RunBeforeExit(&env);
1713
1714
      // Emit `beforeExit` if the loop became alive either after emitting
1715
      // event, or after running some callbacks.
1716
3255
      more = uv_loop_alive(env.event_loop());
1717
    } while (more == true);
1718
    env.performance_state()->Mark(
1719
3212
        node::performance::NODE_PERFORMANCE_MILESTONE_LOOP_EXIT);
1720
  }
1721
1722
3212
  env.set_trace_sync_io(false);
1723
1724
3212
  const int exit_code = EmitExit(&env);
1725
1726
3206
  WaitForInspectorDisconnect(&env);
1727
1728
3206
  env.set_can_call_into_js(false);
1729
3206
  env.stop_sub_worker_contexts();
1730
3206
  uv_tty_reset_mode();
1731
3206
  env.RunCleanup();
1732
3206
  RunAtExit(&env);
1733
1734
3206
  v8_platform.DrainVMTasks(isolate);
1735
3206
  v8_platform.CancelVMTasks(isolate);
1736
#if defined(LEAK_SANITIZER)
1737
  __lsan_do_leak_check();
1738
#endif
1739
1740
6413
  return exit_code;
1741
}
1742
1743
21
bool AllowWasmCodeGenerationCallback(
1744
    Local<Context> context, Local<String>) {
1745
  Local<Value> wasm_code_gen =
1746
42
    context->GetEmbedderData(ContextEmbedderIndex::kAllowWasmCodeGeneration);
1747

63
  return wasm_code_gen->IsUndefined() || wasm_code_gen->IsTrue();
1748
}
1749
1750
3700
Isolate* NewIsolate(ArrayBufferAllocator* allocator, uv_loop_t* event_loop) {
1751
3700
  Isolate::CreateParams params;
1752
3700
  params.array_buffer_allocator = allocator;
1753
#ifdef NODE_ENABLE_VTUNE_PROFILING
1754
  params.code_event_handler = vTune::GetVtuneCodeEventHandler();
1755
#endif
1756
1757
3700
  Isolate* isolate = Isolate::Allocate();
1758
3700
  if (isolate == nullptr)
1759
    return nullptr;
1760
1761
  // Register the isolate on the platform before the isolate gets initialized,
1762
  // so that the isolate can access the platform during initialization.
1763
3700
  v8_platform.Platform()->RegisterIsolate(isolate, event_loop);
1764
3700
  Isolate::Initialize(isolate, params);
1765
1766
  isolate->AddMessageListenerWithErrorLevel(OnMessage,
1767
      Isolate::MessageErrorLevel::kMessageError |
1768
3700
      Isolate::MessageErrorLevel::kMessageWarning);
1769
3700
  isolate->SetAbortOnUncaughtExceptionCallback(ShouldAbortOnUncaughtException);
1770
3700
  isolate->SetMicrotasksPolicy(MicrotasksPolicy::kExplicit);
1771
3700
  isolate->SetFatalErrorHandler(OnFatalError);
1772
3700
  isolate->SetAllowWasmCodeGenerationCallback(AllowWasmCodeGenerationCallback);
1773
3700
  v8::CpuProfiler::UseDetailedSourcePositionsForProfiling(isolate);
1774
1775
3700
  return isolate;
1776
}
1777
1778
3554
inline int Start(uv_loop_t* event_loop,
1779
                 const std::vector<std::string>& args,
1780
                 const std::vector<std::string>& exec_args) {
1781
  std::unique_ptr<ArrayBufferAllocator, decltype(&FreeArrayBufferAllocator)>
1782
3554
      allocator(CreateArrayBufferAllocator(), &FreeArrayBufferAllocator);
1783
3554
  Isolate* const isolate = NewIsolate(allocator.get(), event_loop);
1784
3554
  if (isolate == nullptr)
1785
    return 12;  // Signal internal error.
1786
1787
  {
1788
3554
    Mutex::ScopedLock scoped_lock(node_isolate_mutex);
1789
3554
    CHECK_NULL(node_isolate);
1790
3554
    node_isolate = isolate;
1791
  }
1792
1793
  int exit_code;
1794
  {
1795
3554
    Locker locker(isolate);
1796
6761
    Isolate::Scope isolate_scope(isolate);
1797
6761
    HandleScope handle_scope(isolate);
1798
    std::unique_ptr<IsolateData, decltype(&FreeIsolateData)> isolate_data(
1799
        CreateIsolateData(
1800
            isolate,
1801
            event_loop,
1802
3554
            v8_platform.Platform(),
1803
            allocator.get()),
1804
10315
        &FreeIsolateData);
1805
    // TODO(addaleax): This should load a real per-Isolate option, currently
1806
    // this is still effectively per-process.
1807
3554
    if (isolate_data->options()->track_heap_objects) {
1808
1
      isolate->GetHeapProfiler()->StartTrackingHeapObjects(true);
1809
    }
1810
    exit_code =
1811
6761
        Start(isolate, isolate_data.get(), args, exec_args);
1812
  }
1813
1814
  {
1815
3207
    Mutex::ScopedLock scoped_lock(node_isolate_mutex);
1816
3207
    CHECK_EQ(node_isolate, isolate);
1817
3207
    node_isolate = nullptr;
1818
  }
1819
1820
3207
  isolate->Dispose();
1821
3207
  v8_platform.Platform()->UnregisterIsolate(isolate);
1822
1823
3207
  return exit_code;
1824
}
1825
1826
3596
int Start(int argc, char** argv) {
1827
14384
  atexit([] () { uv_tty_reset_mode(); });
1828
3596
  PlatformInit();
1829
3596
  performance::performance_node_start = PERFORMANCE_NOW();
1830
1831
3596
  CHECK_GT(argc, 0);
1832
1833
#ifdef NODE_ENABLE_LARGE_CODE_PAGES
1834
  if (node::IsLargePagesEnabled()) {
1835
    if (node::MapStaticCodeToLargePages() != 0) {
1836
      fprintf(stderr, "Reverting to default page size\n");
1837
    }
1838
  }
1839
#endif
1840
1841
  // Hack around with the argv pointer. Used for process.title = "blah".
1842
3596
  argv = uv_setup_args(argc, argv);
1843
1844
3596
  std::vector<std::string> args(argv, argv + argc);
1845
6803
  std::vector<std::string> exec_args;
1846
  // This needs to run *before* V8::Initialize().
1847
3596
  Init(&args, &exec_args);
1848
1849
#if HAVE_OPENSSL
1850
  {
1851
3554
    std::string extra_ca_certs;
1852
3554
    if (credentials::SafeGetenv("NODE_EXTRA_CA_CERTS", &extra_ca_certs))
1853
3
      crypto::UseExtraCaCerts(extra_ca_certs);
1854
  }
1855
#ifdef NODE_FIPS_MODE
1856
  // In the case of FIPS builds we should make sure
1857
  // the random source is properly initialized first.
1858
  OPENSSL_init();
1859
#endif  // NODE_FIPS_MODE
1860
  // V8 on Windows doesn't have a good source of entropy. Seed it from
1861
  // OpenSSL's pool.
1862
3554
  V8::SetEntropySource(crypto::EntropySource);
1863
#endif  // HAVE_OPENSSL
1864
1865
3554
  InitializeV8Platform(per_process_opts->v8_thread_pool_size);
1866
3554
  V8::Initialize();
1867
3554
  performance::performance_v8_start = PERFORMANCE_NOW();
1868
3554
  v8_initialized = true;
1869
  const int exit_code =
1870
3554
      Start(uv_default_loop(), args, exec_args);
1871
3207
  v8_platform.StopTracingAgent();
1872
3207
  v8_initialized = false;
1873
3207
  V8::Dispose();
1874
1875
  // uv_run cannot be called from the time before the beforeExit callback
1876
  // runs until the program exits unless the event loop has any referenced
1877
  // handles after beforeExit terminates. This prevents unrefed timers
1878
  // that happen to terminate during shutdown from being run unsafely.
1879
  // Since uv_run cannot be called, uv_async handles held by the platform
1880
  // will never be fully cleaned up.
1881
3207
  v8_platform.Dispose();
1882
1883
6414
  return exit_code;
1884
}
1885
1886

10791
}  // namespace node
1887
1888
#if !HAVE_INSPECTOR
1889
void Initialize() {}
1890
1891
NODE_MODULE_CONTEXT_AWARE_INTERNAL(inspector, Initialize)
1892
#endif  // !HAVE_INSPECTOR