GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage-daily/nodes/benchmark/out/../src/node_main_instance.cc Lines: 101 102 99.0 %
Date: 2020-02-19 22:14:06 Branches: 50 60 83.3 %

Line Branch Exec Source
1
#include <memory>
2
3
#include "node_main_instance.h"
4
#include "node_internals.h"
5
#include "node_options-inl.h"
6
#include "node_v8_platform-inl.h"
7
#include "util-inl.h"
8
#if defined(LEAK_SANITIZER)
9
#include <sanitizer/lsan_interface.h>
10
#endif
11
12
#if HAVE_INSPECTOR
13
#include "inspector/worker_inspector.h"  // ParentInspectorHandle
14
#endif
15
16
namespace node {
17
18
using v8::Context;
19
using v8::HandleScope;
20
using v8::Isolate;
21
using v8::Local;
22
using v8::Locker;
23
using v8::Object;
24
using v8::SealHandleScope;
25
26
1
NodeMainInstance::NodeMainInstance(Isolate* isolate,
27
                                   uv_loop_t* event_loop,
28
                                   MultiIsolatePlatform* platform,
29
                                   const std::vector<std::string>& args,
30
1
                                   const std::vector<std::string>& exec_args)
31
    : args_(args),
32
      exec_args_(exec_args),
33
      array_buffer_allocator_(nullptr),
34
      isolate_(isolate),
35
      platform_(platform),
36
      isolate_data_(nullptr),
37
      owns_isolate_(false),
38
1
      deserialize_mode_(false) {
39
  isolate_data_ =
40
1
      std::make_unique<IsolateData>(isolate_, event_loop, platform, nullptr);
41
42
1
  IsolateSettings misc;
43
1
  SetIsolateMiscHandlers(isolate_, misc);
44
1
}
45
46
1
std::unique_ptr<NodeMainInstance> NodeMainInstance::Create(
47
    Isolate* isolate,
48
    uv_loop_t* event_loop,
49
    MultiIsolatePlatform* platform,
50
    const std::vector<std::string>& args,
51
    const std::vector<std::string>& exec_args) {
52
  return std::unique_ptr<NodeMainInstance>(
53
1
      new NodeMainInstance(isolate, event_loop, platform, args, exec_args));
54
}
55
56
4124
NodeMainInstance::NodeMainInstance(
57
    Isolate::CreateParams* params,
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
4124
    const std::vector<size_t>* per_isolate_data_indexes)
63
    : args_(args),
64
      exec_args_(exec_args),
65
      array_buffer_allocator_(ArrayBufferAllocator::Create()),
66
      isolate_(nullptr),
67
      platform_(platform),
68
      isolate_data_(nullptr),
69
4124
      owns_isolate_(true) {
70
4124
  params->array_buffer_allocator = array_buffer_allocator_.get();
71
4124
  isolate_ = Isolate::Allocate();
72
4124
  CHECK_NOT_NULL(isolate_);
73
  // Register the isolate on the platform before the isolate gets initialized,
74
  // so that the isolate can access the platform during initialization.
75
4124
  platform->RegisterIsolate(isolate_, event_loop);
76
4124
  SetIsolateCreateParamsForNode(params);
77
4124
  Isolate::Initialize(isolate_, *params);
78
79
4124
  deserialize_mode_ = per_isolate_data_indexes != nullptr;
80
  // If the indexes are not nullptr, we are not deserializing
81

4124
  CHECK_IMPLIES(deserialize_mode_, params->external_references != nullptr);
82
8248
  isolate_data_ = std::make_unique<IsolateData>(isolate_,
83
                                                event_loop,
84
                                                platform,
85
8248
                                                array_buffer_allocator_.get(),
86
4124
                                                per_isolate_data_indexes);
87
4124
  IsolateSettings s;
88
4124
  SetIsolateMiscHandlers(isolate_, s);
89
4124
  if (!deserialize_mode_) {
90
    // If in deserialize mode, delay until after the deserialization is
91
    // complete.
92
1
    SetIsolateErrorHandlers(isolate_, s);
93
  }
94
4124
}
95
96
1
void NodeMainInstance::Dispose() {
97
1
  CHECK(!owns_isolate_);
98
1
  platform_->DrainTasks(isolate_);
99
1
}
100
101


7440
NodeMainInstance::~NodeMainInstance() {
102
3720
  if (!owns_isolate_) {
103
1
    return;
104
  }
105
  // TODO(addaleax): Reverse the order of these calls. The fact that we first
106
  // dispose the Isolate is a temporary workaround for
107
  // https://github.com/nodejs/node/issues/31752 -- V8 should not be posting
108
  // platform tasks during Dispose(), but it does in some WASM edge cases.
109
3719
  isolate_->Dispose();
110
3719
  platform_->UnregisterIsolate(isolate_);
111
3720
}
112
113
4124
int NodeMainInstance::Run() {
114
7843
  Locker locker(isolate_);
115
7843
  Isolate::Scope isolate_scope(isolate_);
116
7843
  HandleScope handle_scope(isolate_);
117
118
4124
  int exit_code = 0;
119
7843
  std::unique_ptr<Environment> env = CreateMainEnvironment(&exit_code);
120
121
4124
  CHECK_NOT_NULL(env);
122
4124
  Context::Scope context_scope(env->context());
123
124
4124
  if (exit_code == 0) {
125
    {
126
      InternalCallbackScope callback_scope(
127
          env.get(),
128
          Object::New(isolate_),
129
          { 1, 0 },
130
8008
          InternalCallbackScope::kSkipAsyncHooks);
131
4123
      LoadEnvironment(env.get());
132
    }
133
134
3859
    env->set_trace_sync_io(env->options()->trace_sync_io);
135
136
    {
137
7583
      SealHandleScope seal(isolate_);
138
      bool more;
139
3859
      env->performance_state()->Mark(
140
3859
          node::performance::NODE_PERFORMANCE_MILESTONE_LOOP_START);
141
3739
      do {
142
3874
        uv_run(env->event_loop(), UV_RUN_DEFAULT);
143
144
3741
        per_process::v8_platform.DrainVMTasks(isolate_);
145
146
3740
        more = uv_loop_alive(env->event_loop());
147

3740
        if (more && !env->is_stopping()) continue;
148
149
3739
        if (!uv_loop_alive(env->event_loop())) {
150
3739
          EmitBeforeExit(env.get());
151
        }
152
153
        // Emit `beforeExit` if the loop became alive either after emitting
154
        // event, or after running some callbacks.
155
3738
        more = uv_loop_alive(env->event_loop());
156

3739
      } while (more == true && !env->is_stopping());
157
3724
      env->performance_state()->Mark(
158
3724
          node::performance::NODE_PERFORMANCE_MILESTONE_LOOP_EXIT);
159
    }
160
161
3724
    env->set_trace_sync_io(false);
162
3724
    exit_code = EmitExit(env.get());
163
  }
164
165
3719
  env->set_can_call_into_js(false);
166
3719
  env->stop_sub_worker_contexts();
167
3719
  ResetStdio();
168
3719
  env->RunCleanup();
169
170
  // TODO(addaleax): Neither NODE_SHARED_MODE nor HAVE_INSPECTOR really
171
  // make sense here.
172
#if HAVE_INSPECTOR && defined(__POSIX__) && !defined(NODE_SHARED_MODE)
173
  struct sigaction act;
174
3719
  memset(&act, 0, sizeof(act));
175
119008
  for (unsigned nr = 1; nr < kMaxSignal; nr += 1) {
176

115289
    if (nr == SIGKILL || nr == SIGSTOP || nr == SIGPROF)
177
11157
      continue;
178
104132
    act.sa_handler = (nr == SIGPIPE) ? SIG_IGN : SIG_DFL;
179
104132
    CHECK_EQ(0, sigaction(nr, &act, nullptr));
180
  }
181
#endif
182
183
3719
  RunAtExit(env.get());
184
185
3719
  per_process::v8_platform.DrainVMTasks(isolate_);
186
187
#if defined(LEAK_SANITIZER)
188
  __lsan_do_leak_check();
189
#endif
190
191
7438
  return exit_code;
192
}
193
194
// TODO(joyeecheung): align this with the CreateEnvironment exposed in node.h
195
// and the environment creation routine in workers somehow.
196
4124
std::unique_ptr<Environment> NodeMainInstance::CreateMainEnvironment(
197
    int* exit_code) {
198
4124
  *exit_code = 0;  // Reset the exit code to 0
199
200
8248
  HandleScope handle_scope(isolate_);
201
202
  // TODO(addaleax): This should load a real per-Isolate option, currently
203
  // this is still effectively per-process.
204
4124
  if (isolate_data_->options()->track_heap_objects) {
205
1
    isolate_->GetHeapProfiler()->StartTrackingHeapObjects(true);
206
  }
207
208
  Local<Context> context;
209
4124
  if (deserialize_mode_) {
210
    context =
211
8246
        Context::FromSnapshot(isolate_, kNodeContextIndex).ToLocalChecked();
212
4123
    InitializeContextRuntime(context);
213
4123
    IsolateSettings s;
214
4123
    SetIsolateErrorHandlers(isolate_, s);
215
  } else {
216
1
    context = NewContext(isolate_);
217
  }
218
219
4124
  CHECK(!context.IsEmpty());
220
  Context::Scope context_scope(context);
221
222
  std::unique_ptr<Environment> env = std::make_unique<Environment>(
223
8248
      isolate_data_.get(),
224
      context,
225
      args_,
226
      exec_args_,
227
8248
      static_cast<Environment::Flags>(Environment::kIsMainThread |
228
                                      Environment::kOwnsProcessState |
229
8248
                                      Environment::kOwnsInspector));
230
4124
  env->InitializeLibuv(per_process::v8_is_profiling);
231
4124
  env->InitializeDiagnostics();
232
233
  // TODO(joyeecheung): when we snapshot the bootstrapped context,
234
  // the inspector and diagnostics setup should after after deserialization.
235
#if HAVE_INSPECTOR
236
4124
  *exit_code = env->InitializeInspector({});
237
#endif
238
4124
  if (*exit_code != 0) {
239
1
    return env;
240
  }
241
242
8246
  if (env->RunBootstrapping().IsEmpty()) {
243
    *exit_code = 1;
244
  }
245
246
4123
  return env;
247
}
248
249
}  // namespace node