• 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   isolate_data_->max_young_gen_size =
93       params->constraints.max_young_generation_size_in_bytes();
94 }
95 
Dispose()96 void NodeMainInstance::Dispose() {
97   CHECK(!owns_isolate_);
98   platform_->DrainTasks(isolate_);
99 }
100 
~NodeMainInstance()101 NodeMainInstance::~NodeMainInstance() {
102   if (!owns_isolate_) {
103     return;
104   }
105   platform_->UnregisterIsolate(isolate_);
106   isolate_->Dispose();
107 }
108 
Run()109 int NodeMainInstance::Run() {
110   Locker locker(isolate_);
111   Isolate::Scope isolate_scope(isolate_);
112   HandleScope handle_scope(isolate_);
113 
114   int exit_code = 0;
115   DeleteFnPtr<Environment, FreeEnvironment> env =
116       CreateMainEnvironment(&exit_code);
117 
118   CHECK_NOT_NULL(env);
119   Context::Scope context_scope(env->context());
120 
121   if (exit_code == 0) {
122     LoadEnvironment(env.get());
123 
124     env->set_trace_sync_io(env->options()->trace_sync_io);
125 
126     {
127       SealHandleScope seal(isolate_);
128       bool more;
129       env->performance_state()->Mark(
130           node::performance::NODE_PERFORMANCE_MILESTONE_LOOP_START);
131       do {
132         uv_run(env->event_loop(), UV_RUN_DEFAULT);
133 
134         per_process::v8_platform.DrainVMTasks(isolate_);
135 
136         more = uv_loop_alive(env->event_loop());
137         if (more && !env->is_stopping()) continue;
138 
139         if (!uv_loop_alive(env->event_loop())) {
140           if (EmitProcessBeforeExit(env.get()).IsNothing())
141             break;
142         }
143 
144         // Emit `beforeExit` if the loop became alive either after emitting
145         // event, or after running some callbacks.
146         more = uv_loop_alive(env->event_loop());
147       } while (more == true && !env->is_stopping());
148       env->performance_state()->Mark(
149           node::performance::NODE_PERFORMANCE_MILESTONE_LOOP_EXIT);
150     }
151 
152     env->set_trace_sync_io(false);
153     if (!env->is_stopping()) env->VerifyNoStrongBaseObjects();
154     exit_code = EmitProcessExit(env.get()).FromMaybe(1);
155   }
156 
157   ResetStdio();
158 
159   // TODO(addaleax): Neither NODE_SHARED_MODE nor HAVE_INSPECTOR really
160   // make sense here.
161 #if HAVE_INSPECTOR && defined(__POSIX__) && !defined(NODE_SHARED_MODE)
162   struct sigaction act;
163   memset(&act, 0, sizeof(act));
164   for (unsigned nr = 1; nr < kMaxSignal; nr += 1) {
165     if (nr == SIGKILL || nr == SIGSTOP || nr == SIGPROF)
166       continue;
167     act.sa_handler = (nr == SIGPIPE) ? SIG_IGN : SIG_DFL;
168     CHECK_EQ(0, sigaction(nr, &act, nullptr));
169   }
170 #endif
171 
172 #if defined(LEAK_SANITIZER)
173   __lsan_do_leak_check();
174 #endif
175 
176   return exit_code;
177 }
178 
179 DeleteFnPtr<Environment, FreeEnvironment>
CreateMainEnvironment(int * exit_code)180 NodeMainInstance::CreateMainEnvironment(int* exit_code) {
181   *exit_code = 0;  // Reset the exit code to 0
182 
183   HandleScope handle_scope(isolate_);
184 
185   // TODO(addaleax): This should load a real per-Isolate option, currently
186   // this is still effectively per-process.
187   if (isolate_data_->options()->track_heap_objects) {
188     isolate_->GetHeapProfiler()->StartTrackingHeapObjects(true);
189   }
190 
191   Local<Context> context;
192   if (deserialize_mode_) {
193     context =
194         Context::FromSnapshot(isolate_, kNodeContextIndex).ToLocalChecked();
195     InitializeContextRuntime(context);
196     SetIsolateErrorHandlers(isolate_, {});
197   } else {
198     context = NewContext(isolate_);
199   }
200 
201   CHECK(!context.IsEmpty());
202   Context::Scope context_scope(context);
203 
204   DeleteFnPtr<Environment, FreeEnvironment> env { CreateEnvironment(
205       isolate_data_.get(),
206       context,
207       args_,
208       exec_args_,
209       EnvironmentFlags::kDefaultFlags) };
210 
211   if (*exit_code != 0) {
212     return env;
213   }
214 
215   if (env == nullptr) {
216     *exit_code = 1;
217   }
218 
219   return env;
220 }
221 
222 }  // namespace node
223