• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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