GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: node_main_instance.cc Lines: 101 102 99.0 %
Date: 2022-03-16 03:14:48 Branches: 45 58 77.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
      owns_isolate_(false),
43
6
      deserialize_mode_(false) {
44
  isolate_data_ =
45
6
      std::make_unique<IsolateData>(isolate_, event_loop, platform, nullptr);
46
47
6
  SetIsolateMiscHandlers(isolate_, {});
48
6
}
49
50
4959
const std::vector<intptr_t>& NodeMainInstance::CollectExternalReferences() {
51
  // Cannot be called more than once.
52
4959
  CHECK_NULL(registry_);
53
4959
  registry_.reset(new ExternalReferenceRegistry());
54
4959
  return registry_->external_references();
55
}
56
57
6
std::unique_ptr<NodeMainInstance> NodeMainInstance::Create(
58
    Isolate* isolate,
59
    uv_loop_t* event_loop,
60
    MultiIsolatePlatform* platform,
61
    const std::vector<std::string>& args,
62
    const std::vector<std::string>& exec_args) {
63
  return std::unique_ptr<NodeMainInstance>(
64
6
      new NodeMainInstance(isolate, event_loop, platform, args, exec_args));
65
}
66
67
4954
NodeMainInstance::NodeMainInstance(
68
    Isolate::CreateParams* params,
69
    uv_loop_t* event_loop,
70
    MultiIsolatePlatform* platform,
71
    const std::vector<std::string>& args,
72
    const std::vector<std::string>& exec_args,
73
4954
    const std::vector<size_t>* per_isolate_data_indexes)
74
    : args_(args),
75
      exec_args_(exec_args),
76
      array_buffer_allocator_(ArrayBufferAllocator::Create()),
77
      isolate_(nullptr),
78
      platform_(platform),
79
      isolate_data_(nullptr),
80
4954
      owns_isolate_(true) {
81
4954
  params->array_buffer_allocator = array_buffer_allocator_.get();
82
4954
  deserialize_mode_ = per_isolate_data_indexes != nullptr;
83
4954
  if (deserialize_mode_) {
84
    // TODO(joyeecheung): collect external references and set it in
85
    // params.external_references.
86
    const std::vector<intptr_t>& external_references =
87
4953
        CollectExternalReferences();
88
4953
    params->external_references = external_references.data();
89
  }
90
91
4954
  isolate_ = Isolate::Allocate();
92
4954
  CHECK_NOT_NULL(isolate_);
93
  // Register the isolate on the platform before the isolate gets initialized,
94
  // so that the isolate can access the platform during initialization.
95
4954
  platform->RegisterIsolate(isolate_, event_loop);
96
4954
  SetIsolateCreateParamsForNode(params);
97
4954
  Isolate::Initialize(isolate_, *params);
98
99
  // If the indexes are not nullptr, we are not deserializing
100

4954
  CHECK_IMPLIES(deserialize_mode_, params->external_references != nullptr);
101
4954
  isolate_data_ = std::make_unique<IsolateData>(isolate_,
102
                                                event_loop,
103
                                                platform,
104
4954
                                                array_buffer_allocator_.get(),
105
4954
                                                per_isolate_data_indexes);
106
4954
  IsolateSettings s;
107
4954
  SetIsolateMiscHandlers(isolate_, s);
108
4954
  if (!deserialize_mode_) {
109
    // If in deserialize mode, delay until after the deserialization is
110
    // complete.
111
1
    SetIsolateErrorHandlers(isolate_, s);
112
  }
113
4954
  isolate_data_->max_young_gen_size =
114
4954
      params->constraints.max_young_generation_size_in_bytes();
115
4954
}
116
117
6
void NodeMainInstance::Dispose() {
118
6
  CHECK(!owns_isolate_);
119
6
  platform_->DrainTasks(isolate_);
120
6
}
121
122


4490
NodeMainInstance::~NodeMainInstance() {
123
4472
  if (!owns_isolate_) {
124
6
    return;
125
  }
126
4466
  platform_->UnregisterIsolate(isolate_);
127
4466
  isolate_->Dispose();
128
4472
}
129
130
4954
int NodeMainInstance::Run(const EnvSerializeInfo* env_info) {
131
9420
  Locker locker(isolate_);
132
9420
  Isolate::Scope isolate_scope(isolate_);
133
9420
  HandleScope handle_scope(isolate_);
134
135
4954
  int exit_code = 0;
136
  DeleteFnPtr<Environment, FreeEnvironment> env =
137
9420
      CreateMainEnvironment(&exit_code, env_info);
138
4954
  CHECK_NOT_NULL(env);
139
140
4954
  Context::Scope context_scope(env->context());
141
4954
  Run(&exit_code, env.get());
142
4466
  return exit_code;
143
}
144
145
4954
void NodeMainInstance::Run(int* exit_code, Environment* env) {
146
4954
  if (*exit_code == 0) {
147
4954
    LoadEnvironment(env, StartExecutionCallback{});
148
149
9134
    *exit_code = SpinEventLoop(env).FromMaybe(1);
150
  }
151
152
4466
  ResetStdio();
153
154
  // TODO(addaleax): Neither NODE_SHARED_MODE nor HAVE_INSPECTOR really
155
  // make sense here.
156
#if HAVE_INSPECTOR && defined(__POSIX__) && !defined(NODE_SHARED_MODE)
157
  struct sigaction act;
158
4466
  memset(&act, 0, sizeof(act));
159
142912
  for (unsigned nr = 1; nr < kMaxSignal; nr += 1) {
160

138446
    if (nr == SIGKILL || nr == SIGSTOP || nr == SIGPROF)
161
13398
      continue;
162
125048
    act.sa_handler = (nr == SIGPIPE) ? SIG_IGN : SIG_DFL;
163
125048
    CHECK_EQ(0, sigaction(nr, &act, nullptr));
164
  }
165
#endif
166
167
#if defined(LEAK_SANITIZER)
168
  __lsan_do_leak_check();
169
#endif
170
4466
}
171
172
DeleteFnPtr<Environment, FreeEnvironment>
173
4954
NodeMainInstance::CreateMainEnvironment(int* exit_code,
174
                                        const EnvSerializeInfo* env_info) {
175
4954
  *exit_code = 0;  // Reset the exit code to 0
176
177
9908
  HandleScope handle_scope(isolate_);
178
179
  // TODO(addaleax): This should load a real per-Isolate option, currently
180
  // this is still effectively per-process.
181
4954
  if (isolate_data_->options()->track_heap_objects) {
182
1
    isolate_->GetHeapProfiler()->StartTrackingHeapObjects(true);
183
  }
184
185

4954
  CHECK_IMPLIES(deserialize_mode_, env_info != nullptr);
186
  Local<Context> context;
187
4954
  DeleteFnPtr<Environment, FreeEnvironment> env;
188
189
4954
  if (deserialize_mode_) {
190
9906
    env.reset(new Environment(isolate_data_.get(),
191
                              isolate_,
192
4953
                              args_,
193
4953
                              exec_args_,
194
                              env_info,
195
                              EnvironmentFlags::kDefaultFlags,
196
4953
                              {}));
197
4953
    context = Context::FromSnapshot(isolate_,
198
                                    kNodeContextIndex,
199
4953
                                    {DeserializeNodeInternalFields, env.get()})
200
4953
                  .ToLocalChecked();
201
202
4953
    CHECK(!context.IsEmpty());
203
4953
    Context::Scope context_scope(context);
204
9906
    CHECK(InitializeContextRuntime(context).IsJust());
205
4953
    SetIsolateErrorHandlers(isolate_, {});
206
4953
    env->InitializeMainContext(context, env_info);
207
#if HAVE_INSPECTOR
208
4953
    env->InitializeInspector({});
209
#endif
210
4953
    env->DoneBootstrapping();
211
212
#if HAVE_OPENSSL
213
4953
    crypto::InitCryptoOnce(isolate_);
214
#endif  // HAVE_OPENSSL
215
  } else {
216
1
    context = NewContext(isolate_);
217
1
    CHECK(!context.IsEmpty());
218
1
    Context::Scope context_scope(context);
219
2
    env.reset(new Environment(isolate_data_.get(),
220
                              context,
221
1
                              args_,
222
1
                              exec_args_,
223
                              nullptr,
224
                              EnvironmentFlags::kDefaultFlags,
225
1
                              {}));
226
#if HAVE_INSPECTOR
227
1
    env->InitializeInspector({});
228
#endif
229
2
    if (env->RunBootstrapping().IsEmpty()) {
230
      return nullptr;
231
    }
232
  }
233
234
4954
  return env;
235
}
236
237
}  // namespace node