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: 100 101 99.0 %
Date: 2020-02-27 22:14:15 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
4140
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
4140
    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
4140
      owns_isolate_(true) {
70
4140
  params->array_buffer_allocator = array_buffer_allocator_.get();
71
4140
  isolate_ = Isolate::Allocate();
72
4140
  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
4140
  platform->RegisterIsolate(isolate_, event_loop);
76
4140
  SetIsolateCreateParamsForNode(params);
77
4140
  Isolate::Initialize(isolate_, *params);
78
79
4140
  deserialize_mode_ = per_isolate_data_indexes != nullptr;
80
  // If the indexes are not nullptr, we are not deserializing
81

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


7472
NodeMainInstance::~NodeMainInstance() {
102
3736
  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
3735
  isolate_->Dispose();
110
3735
  platform_->UnregisterIsolate(isolate_);
111
3736
}
112
113
4140
int NodeMainInstance::Run() {
114
7875
  Locker locker(isolate_);
115
7875
  Isolate::Scope isolate_scope(isolate_);
116
7875
  HandleScope handle_scope(isolate_);
117
118
4140
  int exit_code = 0;
119
7875
  std::unique_ptr<Environment> env = CreateMainEnvironment(&exit_code);
120
121
4140
  CHECK_NOT_NULL(env);
122
4140
  Context::Scope context_scope(env->context());
123
124
4140
  if (exit_code == 0) {
125
4139
    LoadEnvironment(env.get());
126
127
3875
    env->set_trace_sync_io(env->options()->trace_sync_io);
128
129
    {
130
7615
      SealHandleScope seal(isolate_);
131
      bool more;
132
3875
      env->performance_state()->Mark(
133
3875
          node::performance::NODE_PERFORMANCE_MILESTONE_LOOP_START);
134
3755
      do {
135
3890
        uv_run(env->event_loop(), UV_RUN_DEFAULT);
136
137
3757
        per_process::v8_platform.DrainVMTasks(isolate_);
138
139
3756
        more = uv_loop_alive(env->event_loop());
140

3756
        if (more && !env->is_stopping()) continue;
141
142
3755
        if (!uv_loop_alive(env->event_loop())) {
143
3755
          EmitBeforeExit(env.get());
144
        }
145
146
        // Emit `beforeExit` if the loop became alive either after emitting
147
        // event, or after running some callbacks.
148
3754
        more = uv_loop_alive(env->event_loop());
149

3755
      } while (more == true && !env->is_stopping());
150
3740
      env->performance_state()->Mark(
151
3740
          node::performance::NODE_PERFORMANCE_MILESTONE_LOOP_EXIT);
152
    }
153
154
3740
    env->set_trace_sync_io(false);
155
3740
    exit_code = EmitExit(env.get());
156
  }
157
158
3735
  env->set_can_call_into_js(false);
159
3735
  env->stop_sub_worker_contexts();
160
3735
  ResetStdio();
161
3735
  env->RunCleanup();
162
163
  // TODO(addaleax): Neither NODE_SHARED_MODE nor HAVE_INSPECTOR really
164
  // make sense here.
165
#if HAVE_INSPECTOR && defined(__POSIX__) && !defined(NODE_SHARED_MODE)
166
  struct sigaction act;
167
3735
  memset(&act, 0, sizeof(act));
168
119520
  for (unsigned nr = 1; nr < kMaxSignal; nr += 1) {
169

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