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::SealHandleScope;
24
NodeMainInstance(Isolate * isolate,uv_loop_t * event_loop,MultiIsolatePlatform * platform,const std::vector<std::string> & args,const std::vector<std::string> & exec_args)25 NodeMainInstance::NodeMainInstance(Isolate* isolate,
26 uv_loop_t* event_loop,
27 MultiIsolatePlatform* platform,
28 const std::vector<std::string>& args,
29 const std::vector<std::string>& exec_args)
30 : args_(args),
31 exec_args_(exec_args),
32 array_buffer_allocator_(nullptr),
33 isolate_(isolate),
34 platform_(platform),
35 isolate_data_(nullptr),
36 owns_isolate_(false),
37 deserialize_mode_(false) {
38 isolate_data_ =
39 std::make_unique<IsolateData>(isolate_, event_loop, platform, nullptr);
40
41 SetIsolateMiscHandlers(isolate_, {});
42 }
43
Create(Isolate * isolate,uv_loop_t * event_loop,MultiIsolatePlatform * platform,const std::vector<std::string> & args,const std::vector<std::string> & exec_args)44 std::unique_ptr<NodeMainInstance> NodeMainInstance::Create(
45 Isolate* isolate,
46 uv_loop_t* event_loop,
47 MultiIsolatePlatform* platform,
48 const std::vector<std::string>& args,
49 const std::vector<std::string>& exec_args) {
50 return std::unique_ptr<NodeMainInstance>(
51 new NodeMainInstance(isolate, event_loop, platform, args, exec_args));
52 }
53
NodeMainInstance(Isolate::CreateParams * params,uv_loop_t * event_loop,MultiIsolatePlatform * platform,const std::vector<std::string> & args,const std::vector<std::string> & exec_args,const std::vector<size_t> * per_isolate_data_indexes)54 NodeMainInstance::NodeMainInstance(
55 Isolate::CreateParams* params,
56 uv_loop_t* event_loop,
57 MultiIsolatePlatform* platform,
58 const std::vector<std::string>& args,
59 const std::vector<std::string>& exec_args,
60 const std::vector<size_t>* per_isolate_data_indexes)
61 : args_(args),
62 exec_args_(exec_args),
63 array_buffer_allocator_(ArrayBufferAllocator::Create()),
64 isolate_(nullptr),
65 platform_(platform),
66 isolate_data_(nullptr),
67 owns_isolate_(true) {
68 params->array_buffer_allocator = array_buffer_allocator_.get();
69 isolate_ = Isolate::Allocate();
70 CHECK_NOT_NULL(isolate_);
71 // Register the isolate on the platform before the isolate gets initialized,
72 // so that the isolate can access the platform during initialization.
73 platform->RegisterIsolate(isolate_, event_loop);
74 SetIsolateCreateParamsForNode(params);
75 Isolate::Initialize(isolate_, *params);
76
77 deserialize_mode_ = per_isolate_data_indexes != nullptr;
78 // If the indexes are not nullptr, we are not deserializing
79 CHECK_IMPLIES(deserialize_mode_, params->external_references != nullptr);
80 isolate_data_ = std::make_unique<IsolateData>(isolate_,
81 event_loop,
82 platform,
83 array_buffer_allocator_.get(),
84 per_isolate_data_indexes);
85 IsolateSettings s;
86 SetIsolateMiscHandlers(isolate_, s);
87 if (!deserialize_mode_) {
88 // If in deserialize mode, delay until after the deserialization is
89 // complete.
90 SetIsolateErrorHandlers(isolate_, s);
91 }
92 }
93
Dispose()94 void NodeMainInstance::Dispose() {
95 CHECK(!owns_isolate_);
96 platform_->DrainTasks(isolate_);
97 }
98
~NodeMainInstance()99 NodeMainInstance::~NodeMainInstance() {
100 if (!owns_isolate_) {
101 return;
102 }
103 platform_->UnregisterIsolate(isolate_);
104 isolate_->Dispose();
105 }
106
Run()107 int NodeMainInstance::Run() {
108 Locker locker(isolate_);
109 Isolate::Scope isolate_scope(isolate_);
110 HandleScope handle_scope(isolate_);
111
112 int exit_code = 0;
113 DeleteFnPtr<Environment, FreeEnvironment> env =
114 CreateMainEnvironment(&exit_code);
115
116 CHECK_NOT_NULL(env);
117 Context::Scope context_scope(env->context());
118
119 if (exit_code == 0) {
120 LoadEnvironment(env.get());
121
122 env->set_trace_sync_io(env->options()->trace_sync_io);
123
124 {
125 SealHandleScope seal(isolate_);
126 bool more;
127 env->performance_state()->Mark(
128 node::performance::NODE_PERFORMANCE_MILESTONE_LOOP_START);
129 do {
130 uv_run(env->event_loop(), UV_RUN_DEFAULT);
131
132 per_process::v8_platform.DrainVMTasks(isolate_);
133
134 more = uv_loop_alive(env->event_loop());
135 if (more && !env->is_stopping()) continue;
136
137 if (!uv_loop_alive(env->event_loop())) {
138 EmitBeforeExit(env.get());
139 }
140
141 // Emit `beforeExit` if the loop became alive either after emitting
142 // event, or after running some callbacks.
143 more = uv_loop_alive(env->event_loop());
144 } while (more == true && !env->is_stopping());
145 env->performance_state()->Mark(
146 node::performance::NODE_PERFORMANCE_MILESTONE_LOOP_EXIT);
147 }
148
149 env->set_trace_sync_io(false);
150 exit_code = EmitExit(env.get());
151 }
152
153 ResetStdio();
154
155 // TODO(addaleax): Neither NODE_SHARED_MODE nor HAVE_INSPECTOR really
156 // make sense here.
157 #if HAVE_INSPECTOR && defined(__POSIX__) && !defined(NODE_SHARED_MODE)
158 struct sigaction act;
159 memset(&act, 0, sizeof(act));
160 for (unsigned nr = 1; nr < kMaxSignal; nr += 1) {
161 if (nr == SIGKILL || nr == SIGSTOP || nr == SIGPROF)
162 continue;
163 act.sa_handler = (nr == SIGPIPE) ? SIG_IGN : SIG_DFL;
164 CHECK_EQ(0, sigaction(nr, &act, nullptr));
165 }
166 #endif
167
168 #if defined(LEAK_SANITIZER)
169 __lsan_do_leak_check();
170 #endif
171
172 return exit_code;
173 }
174
175 DeleteFnPtr<Environment, FreeEnvironment>
CreateMainEnvironment(int * exit_code)176 NodeMainInstance::CreateMainEnvironment(int* exit_code) {
177 *exit_code = 0; // Reset the exit code to 0
178
179 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 if (isolate_data_->options()->track_heap_objects) {
184 isolate_->GetHeapProfiler()->StartTrackingHeapObjects(true);
185 }
186
187 Local<Context> context;
188 if (deserialize_mode_) {
189 context =
190 Context::FromSnapshot(isolate_, kNodeContextIndex).ToLocalChecked();
191 InitializeContextRuntime(context);
192 SetIsolateErrorHandlers(isolate_, {});
193 } else {
194 context = NewContext(isolate_);
195 }
196
197 CHECK(!context.IsEmpty());
198 Context::Scope context_scope(context);
199
200 DeleteFnPtr<Environment, FreeEnvironment> env { CreateEnvironment(
201 isolate_data_.get(),
202 context,
203 args_,
204 exec_args_,
205 EnvironmentFlags::kDefaultFlags) };
206
207 if (*exit_code != 0) {
208 return env;
209 }
210
211 if (env == nullptr) {
212 *exit_code = 1;
213 }
214
215 return env;
216 }
217
218 } // namespace node
219