GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: node_main_instance.cc Lines: 96 97 99.0 %
Date: 2022-04-20 04:15:34 Branches: 42 52 80.8 %

Line Branch Exec Source
1
#include "node_main_instance.h"
2
#include <memory>
3
#if HAVE_OPENSSL
4
#include "crypto/crypto_util.h"
5
#endif  // HAVE_OPENSSL
6
#include "debug_utils-inl.h"
7
#include "node_external_reference.h"
8
#include "node_internals.h"
9
#include "node_options-inl.h"
10
#include "node_snapshot_builder.h"
11
#include "node_snapshotable.h"
12
#include "node_v8_platform-inl.h"
13
#include "util-inl.h"
14
#if defined(LEAK_SANITIZER)
15
#include <sanitizer/lsan_interface.h>
16
#endif
17
18
#if HAVE_INSPECTOR
19
#include "inspector/worker_inspector.h"  // ParentInspectorHandle
20
#endif
21
22
namespace node {
23
24
using v8::Context;
25
using v8::HandleScope;
26
using v8::Isolate;
27
using v8::Local;
28
using v8::Locker;
29
30
6
NodeMainInstance::NodeMainInstance(Isolate* isolate,
31
                                   uv_loop_t* event_loop,
32
                                   MultiIsolatePlatform* platform,
33
                                   const std::vector<std::string>& args,
34
6
                                   const std::vector<std::string>& exec_args)
35
    : args_(args),
36
      exec_args_(exec_args),
37
      array_buffer_allocator_(nullptr),
38
      isolate_(isolate),
39
      platform_(platform),
40
      isolate_data_(nullptr),
41
6
      snapshot_data_(nullptr) {
42
  isolate_data_ =
43
6
      std::make_unique<IsolateData>(isolate_, event_loop, platform, nullptr);
44
45
6
  SetIsolateMiscHandlers(isolate_, {});
46
6
}
47
48
6
std::unique_ptr<NodeMainInstance> NodeMainInstance::Create(
49
    Isolate* isolate,
50
    uv_loop_t* event_loop,
51
    MultiIsolatePlatform* platform,
52
    const std::vector<std::string>& args,
53
    const std::vector<std::string>& exec_args) {
54
  return std::unique_ptr<NodeMainInstance>(
55
6
      new NodeMainInstance(isolate, event_loop, platform, args, exec_args));
56
}
57
58
5006
NodeMainInstance::NodeMainInstance(const SnapshotData* snapshot_data,
59
                                   uv_loop_t* event_loop,
60
                                   MultiIsolatePlatform* platform,
61
                                   const std::vector<std::string>& args,
62
5006
                                   const std::vector<std::string>& exec_args)
63
    : args_(args),
64
      exec_args_(exec_args),
65
      array_buffer_allocator_(ArrayBufferAllocator::Create()),
66
      isolate_(nullptr),
67
      platform_(platform),
68
      isolate_data_(),
69
      isolate_params_(std::make_unique<Isolate::CreateParams>()),
70
5006
      snapshot_data_(snapshot_data) {
71
5006
  isolate_params_->array_buffer_allocator = array_buffer_allocator_.get();
72
5006
  if (snapshot_data != nullptr) {
73
5005
    SnapshotBuilder::InitializeIsolateParams(snapshot_data,
74
                                             isolate_params_.get());
75
  }
76
77
5006
  isolate_ = Isolate::Allocate();
78
5006
  CHECK_NOT_NULL(isolate_);
79
  // Register the isolate on the platform before the isolate gets initialized,
80
  // so that the isolate can access the platform during initialization.
81
5006
  platform->RegisterIsolate(isolate_, event_loop);
82
5006
  SetIsolateCreateParamsForNode(isolate_params_.get());
83
5006
  Isolate::Initialize(isolate_, *isolate_params_);
84
85
  // If the indexes are not nullptr, we are not deserializing
86
5006
  isolate_data_ = std::make_unique<IsolateData>(
87
5006
      isolate_,
88
      event_loop,
89
      platform,
90
5006
      array_buffer_allocator_.get(),
91
5006
      snapshot_data == nullptr ? nullptr
92
5006
                               : &(snapshot_data->isolate_data_indices));
93
5006
  IsolateSettings s;
94
5006
  SetIsolateMiscHandlers(isolate_, s);
95
5006
  if (snapshot_data == nullptr) {
96
    // If in deserialize mode, delay until after the deserialization is
97
    // complete.
98
1
    SetIsolateErrorHandlers(isolate_, s);
99
  }
100
5006
  isolate_data_->max_young_gen_size =
101
5006
      isolate_params_->constraints.max_young_generation_size_in_bytes();
102
5006
}
103
104
6
void NodeMainInstance::Dispose() {
105
  // This should only be called on a main instance that does not own its
106
  // isolate.
107
6
  CHECK_NULL(isolate_params_);
108
6
  platform_->DrainTasks(isolate_);
109
6
}
110
111


4452
NodeMainInstance::~NodeMainInstance() {
112
4428
  if (isolate_params_ == nullptr) {
113
6
    return;
114
  }
115
  // This should only be done on a main instance that owns its isolate.
116
4422
  platform_->UnregisterIsolate(isolate_);
117
4422
  isolate_->Dispose();
118
4428
}
119
120
5006
int NodeMainInstance::Run() {
121
9428
  Locker locker(isolate_);
122
9428
  Isolate::Scope isolate_scope(isolate_);
123
9428
  HandleScope handle_scope(isolate_);
124
125
5006
  int exit_code = 0;
126
  DeleteFnPtr<Environment, FreeEnvironment> env =
127
9428
      CreateMainEnvironment(&exit_code);
128
5006
  CHECK_NOT_NULL(env);
129
130
5006
  Context::Scope context_scope(env->context());
131
5006
  Run(&exit_code, env.get());
132
4422
  return exit_code;
133
}
134
135
5006
void NodeMainInstance::Run(int* exit_code, Environment* env) {
136
5006
  if (*exit_code == 0) {
137
5006
    LoadEnvironment(env, StartExecutionCallback{});
138
139
9137
    *exit_code = SpinEventLoop(env).FromMaybe(1);
140
  }
141
142
4422
  ResetStdio();
143
144
  // TODO(addaleax): Neither NODE_SHARED_MODE nor HAVE_INSPECTOR really
145
  // make sense here.
146
#if HAVE_INSPECTOR && defined(__POSIX__) && !defined(NODE_SHARED_MODE)
147
  struct sigaction act;
148
4422
  memset(&act, 0, sizeof(act));
149
141504
  for (unsigned nr = 1; nr < kMaxSignal; nr += 1) {
150

137082
    if (nr == SIGKILL || nr == SIGSTOP || nr == SIGPROF)
151
13266
      continue;
152
123816
    act.sa_handler = (nr == SIGPIPE) ? SIG_IGN : SIG_DFL;
153
123816
    CHECK_EQ(0, sigaction(nr, &act, nullptr));
154
  }
155
#endif
156
157
#if defined(LEAK_SANITIZER)
158
  __lsan_do_leak_check();
159
#endif
160
4422
}
161
162
DeleteFnPtr<Environment, FreeEnvironment>
163
5006
NodeMainInstance::CreateMainEnvironment(int* exit_code) {
164
5006
  *exit_code = 0;  // Reset the exit code to 0
165
166
10012
  HandleScope handle_scope(isolate_);
167
168
  // TODO(addaleax): This should load a real per-Isolate option, currently
169
  // this is still effectively per-process.
170
5006
  if (isolate_data_->options()->track_heap_objects) {
171
1
    isolate_->GetHeapProfiler()->StartTrackingHeapObjects(true);
172
  }
173
174
  Local<Context> context;
175
5006
  DeleteFnPtr<Environment, FreeEnvironment> env;
176
177
5006
  if (snapshot_data_ != nullptr) {
178
10010
    env.reset(new Environment(isolate_data_.get(),
179
                              isolate_,
180
5005
                              args_,
181
5005
                              exec_args_,
182
5005
                              &(snapshot_data_->env_info),
183
                              EnvironmentFlags::kDefaultFlags,
184
5005
                              {}));
185
5005
    context = Context::FromSnapshot(isolate_,
186
                                    kNodeContextIndex,
187
5005
                                    {DeserializeNodeInternalFields, env.get()})
188
5005
                  .ToLocalChecked();
189
190
5005
    CHECK(!context.IsEmpty());
191
5005
    Context::Scope context_scope(context);
192
10010
    CHECK(InitializeContextRuntime(context).IsJust());
193
5005
    SetIsolateErrorHandlers(isolate_, {});
194
5005
    env->InitializeMainContext(context, &(snapshot_data_->env_info));
195
#if HAVE_INSPECTOR
196
5005
    env->InitializeInspector({});
197
#endif
198
5005
    env->DoneBootstrapping();
199
200
#if HAVE_OPENSSL
201
5005
    crypto::InitCryptoOnce(isolate_);
202
#endif  // HAVE_OPENSSL
203
  } else {
204
1
    context = NewContext(isolate_);
205
1
    CHECK(!context.IsEmpty());
206
1
    Context::Scope context_scope(context);
207
2
    env.reset(new Environment(isolate_data_.get(),
208
                              context,
209
1
                              args_,
210
1
                              exec_args_,
211
                              nullptr,
212
                              EnvironmentFlags::kDefaultFlags,
213
1
                              {}));
214
#if HAVE_INSPECTOR
215
1
    env->InitializeInspector({});
216
#endif
217
2
    if (env->RunBootstrapping().IsEmpty()) {
218
      return nullptr;
219
    }
220
  }
221
222
5006
  return env;
223
}
224
225
}  // namespace node