GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: node_main_instance.cc Lines: 103 104 99.0 %
Date: 2022-04-12 04:14:44 Branches: 43 54 79.6 %

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_snapshotable.h"
11
#include "node_v8_platform-inl.h"
12
#include "util-inl.h"
13
#if defined(LEAK_SANITIZER)
14
#include <sanitizer/lsan_interface.h>
15
#endif
16
17
#if HAVE_INSPECTOR
18
#include "inspector/worker_inspector.h"  // ParentInspectorHandle
19
#endif
20
21
namespace node {
22
23
using v8::Context;
24
using v8::HandleScope;
25
using v8::Isolate;
26
using v8::Local;
27
using v8::Locker;
28
29
std::unique_ptr<ExternalReferenceRegistry> NodeMainInstance::registry_ =
30
    nullptr;
31
6
NodeMainInstance::NodeMainInstance(Isolate* isolate,
32
                                   uv_loop_t* event_loop,
33
                                   MultiIsolatePlatform* platform,
34
                                   const std::vector<std::string>& args,
35
6
                                   const std::vector<std::string>& exec_args)
36
    : args_(args),
37
      exec_args_(exec_args),
38
      array_buffer_allocator_(nullptr),
39
      isolate_(isolate),
40
      platform_(platform),
41
      isolate_data_(nullptr),
42
6
      snapshot_data_(nullptr) {
43
  isolate_data_ =
44
6
      std::make_unique<IsolateData>(isolate_, event_loop, platform, nullptr);
45
46
6
  SetIsolateMiscHandlers(isolate_, {});
47
6
}
48
49
4982
const std::vector<intptr_t>& NodeMainInstance::CollectExternalReferences() {
50
  // Cannot be called more than once.
51
4982
  CHECK_NULL(registry_);
52
4982
  registry_.reset(new ExternalReferenceRegistry());
53
4982
  return registry_->external_references();
54
}
55
56
6
std::unique_ptr<NodeMainInstance> NodeMainInstance::Create(
57
    Isolate* isolate,
58
    uv_loop_t* event_loop,
59
    MultiIsolatePlatform* platform,
60
    const std::vector<std::string>& args,
61
    const std::vector<std::string>& exec_args) {
62
  return std::unique_ptr<NodeMainInstance>(
63
6
      new NodeMainInstance(isolate, event_loop, platform, args, exec_args));
64
}
65
66
4977
NodeMainInstance::NodeMainInstance(const SnapshotData* snapshot_data,
67
                                   uv_loop_t* event_loop,
68
                                   MultiIsolatePlatform* platform,
69
                                   const std::vector<std::string>& args,
70
4977
                                   const std::vector<std::string>& exec_args)
71
    : args_(args),
72
      exec_args_(exec_args),
73
      array_buffer_allocator_(ArrayBufferAllocator::Create()),
74
      isolate_(nullptr),
75
      platform_(platform),
76
      isolate_data_(),
77
      isolate_params_(std::make_unique<Isolate::CreateParams>()),
78
4977
      snapshot_data_(snapshot_data) {
79
4977
  isolate_params_->array_buffer_allocator = array_buffer_allocator_.get();
80
4977
  if (snapshot_data != nullptr) {
81
    // TODO(joyeecheung): collect external references and set it in
82
    // params.external_references.
83
    const std::vector<intptr_t>& external_references =
84
4976
        CollectExternalReferences();
85
4976
    isolate_params_->external_references = external_references.data();
86
4976
    isolate_params_->snapshot_blob =
87
4976
        const_cast<v8::StartupData*>(&(snapshot_data->blob));
88
  }
89
90
4977
  isolate_ = Isolate::Allocate();
91
4977
  CHECK_NOT_NULL(isolate_);
92
  // Register the isolate on the platform before the isolate gets initialized,
93
  // so that the isolate can access the platform during initialization.
94
4977
  platform->RegisterIsolate(isolate_, event_loop);
95
4977
  SetIsolateCreateParamsForNode(isolate_params_.get());
96
4977
  Isolate::Initialize(isolate_, *isolate_params_);
97
98
  // If the indexes are not nullptr, we are not deserializing
99
4977
  isolate_data_ = std::make_unique<IsolateData>(
100
4977
      isolate_,
101
      event_loop,
102
      platform,
103
4977
      array_buffer_allocator_.get(),
104
4977
      snapshot_data == nullptr ? nullptr
105
4977
                               : &(snapshot_data->isolate_data_indices));
106
4977
  IsolateSettings s;
107
4977
  SetIsolateMiscHandlers(isolate_, s);
108
4977
  if (snapshot_data == nullptr) {
109
    // If in deserialize mode, delay until after the deserialization is
110
    // complete.
111
1
    SetIsolateErrorHandlers(isolate_, s);
112
  }
113
4977
  isolate_data_->max_young_gen_size =
114
4977
      isolate_params_->constraints.max_young_generation_size_in_bytes();
115
4977
}
116
117
6
void NodeMainInstance::Dispose() {
118
  // This should only be called on a main instance that does not own its
119
  // isolate.
120
6
  CHECK_NULL(isolate_params_);
121
6
  platform_->DrainTasks(isolate_);
122
6
}
123
124


4516
NodeMainInstance::~NodeMainInstance() {
125
4492
  if (isolate_params_ == nullptr) {
126
6
    return;
127
  }
128
  // This should only be done on a main instance that owns its isolate.
129
4486
  platform_->UnregisterIsolate(isolate_);
130
4486
  isolate_->Dispose();
131
4492
}
132
133
4977
int NodeMainInstance::Run() {
134
9463
  Locker locker(isolate_);
135
9463
  Isolate::Scope isolate_scope(isolate_);
136
9463
  HandleScope handle_scope(isolate_);
137
138
4977
  int exit_code = 0;
139
  DeleteFnPtr<Environment, FreeEnvironment> env =
140
9463
      CreateMainEnvironment(&exit_code);
141
4977
  CHECK_NOT_NULL(env);
142
143
4977
  Context::Scope context_scope(env->context());
144
4977
  Run(&exit_code, env.get());
145
4486
  return exit_code;
146
}
147
148
4977
void NodeMainInstance::Run(int* exit_code, Environment* env) {
149
4977
  if (*exit_code == 0) {
150
4977
    LoadEnvironment(env, StartExecutionCallback{});
151
152
9177
    *exit_code = SpinEventLoop(env).FromMaybe(1);
153
  }
154
155
4486
  ResetStdio();
156
157
  // TODO(addaleax): Neither NODE_SHARED_MODE nor HAVE_INSPECTOR really
158
  // make sense here.
159
#if HAVE_INSPECTOR && defined(__POSIX__) && !defined(NODE_SHARED_MODE)
160
  struct sigaction act;
161
4486
  memset(&act, 0, sizeof(act));
162
143552
  for (unsigned nr = 1; nr < kMaxSignal; nr += 1) {
163

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