Skip to content

Commit d7bc581

Browse files
committed
src: make FreeEnvironment() perform all necessary cleanup
Make the calls `stop_sub_worker_contexts()`, `RunCleanup()` part of the public API for easier embedding. (Note that calling `RunAtExit()` is idempotent because the at-exit callback queue is cleared after each call.) PR-URL: nodejs#30467 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Gireesh Punathil <gpunathi@in.ibm.com>
1 parent 78a2dc7 commit d7bc581

5 files changed

Lines changed: 39 additions & 33 deletions

File tree

src/api/environment.cc

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,23 @@ Environment* CreateEnvironment(IsolateData* isolate_data,
355355
}
356356

357357
void FreeEnvironment(Environment* env) {
358-
env->RunCleanup();
358+
{
359+
// TODO(addaleax): This should maybe rather be in a SealHandleScope.
360+
HandleScope handle_scope(env->isolate());
361+
Context::Scope context_scope(env->context());
362+
env->set_stopping(true);
363+
env->stop_sub_worker_contexts();
364+
env->RunCleanup();
365+
RunAtExit(env);
366+
}
367+
368+
// This call needs to be made while the `Environment` is still alive
369+
// because we assume that it is available for async tracking in the
370+
// NodePlatform implementation.
371+
MultiIsolatePlatform* platform = env->isolate_data()->platform();
372+
if (platform != nullptr)
373+
platform->DrainTasks(env->isolate());
374+
359375
delete env;
360376
}
361377

src/node_main_instance.cc

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,8 @@ int NodeMainInstance::Run() {
112112
HandleScope handle_scope(isolate_);
113113

114114
int exit_code = 0;
115-
std::unique_ptr<Environment> env = CreateMainEnvironment(&exit_code);
115+
DeleteFnPtr<Environment, FreeEnvironment> env =
116+
CreateMainEnvironment(&exit_code);
116117

117118
CHECK_NOT_NULL(env);
118119
Context::Scope context_scope(env->context());
@@ -151,10 +152,7 @@ int NodeMainInstance::Run() {
151152
exit_code = EmitExit(env.get());
152153
}
153154

154-
env->set_can_call_into_js(false);
155-
env->stop_sub_worker_contexts();
156155
ResetStdio();
157-
env->RunCleanup();
158156

159157
// TODO(addaleax): Neither NODE_SHARED_MODE nor HAVE_INSPECTOR really
160158
// make sense here.
@@ -169,10 +167,6 @@ int NodeMainInstance::Run() {
169167
}
170168
#endif
171169

172-
RunAtExit(env.get());
173-
174-
per_process::v8_platform.DrainVMTasks(isolate_);
175-
176170
#if defined(LEAK_SANITIZER)
177171
__lsan_do_leak_check();
178172
#endif
@@ -182,8 +176,8 @@ int NodeMainInstance::Run() {
182176

183177
// TODO(joyeecheung): align this with the CreateEnvironment exposed in node.h
184178
// and the environment creation routine in workers somehow.
185-
std::unique_ptr<Environment> NodeMainInstance::CreateMainEnvironment(
186-
int* exit_code) {
179+
DeleteFnPtr<Environment, FreeEnvironment>
180+
NodeMainInstance::CreateMainEnvironment(int* exit_code) {
187181
*exit_code = 0; // Reset the exit code to 0
188182

189183
HandleScope handle_scope(isolate_);
@@ -208,14 +202,14 @@ std::unique_ptr<Environment> NodeMainInstance::CreateMainEnvironment(
208202
CHECK(!context.IsEmpty());
209203
Context::Scope context_scope(context);
210204

211-
std::unique_ptr<Environment> env = std::make_unique<Environment>(
205+
DeleteFnPtr<Environment, FreeEnvironment> env { new Environment(
212206
isolate_data_.get(),
213207
context,
214208
args_,
215209
exec_args_,
216210
static_cast<Environment::Flags>(Environment::kIsMainThread |
217211
Environment::kOwnsProcessState |
218-
Environment::kOwnsInspector));
212+
Environment::kOwnsInspector)) };
219213
env->InitializeLibuv(per_process::v8_is_profiling);
220214
env->InitializeDiagnostics();
221215

src/node_main_instance.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ class NodeMainInstance {
6161

6262
// TODO(joyeecheung): align this with the CreateEnvironment exposed in node.h
6363
// and the environment creation routine in workers somehow.
64-
std::unique_ptr<Environment> CreateMainEnvironment(int* exit_code);
64+
DeleteFnPtr<Environment, FreeEnvironment> CreateMainEnvironment(
65+
int* exit_code);
6566

6667
// If nullptr is returned, the binary is not built with embedded
6768
// snapshot.

src/node_platform.cc

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,7 @@ void PerIsolatePlatformData::RunForegroundTask(uv_timer_t* handle) {
421421

422422
void NodePlatform::DrainTasks(Isolate* isolate) {
423423
std::shared_ptr<PerIsolatePlatformData> per_isolate = ForNodeIsolate(isolate);
424+
if (!per_isolate) return;
424425

425426
do {
426427
// Worker tasks aren't associated with an Isolate.
@@ -489,12 +490,14 @@ std::shared_ptr<PerIsolatePlatformData>
489490
NodePlatform::ForNodeIsolate(Isolate* isolate) {
490491
Mutex::ScopedLock lock(per_isolate_mutex_);
491492
auto data = per_isolate_[isolate];
492-
CHECK(data.second);
493+
CHECK_NOT_NULL(data.first);
493494
return data.second;
494495
}
495496

496497
bool NodePlatform::FlushForegroundTasks(Isolate* isolate) {
497-
return ForNodeIsolate(isolate)->FlushForegroundTasksInternal();
498+
std::shared_ptr<PerIsolatePlatformData> per_isolate = ForNodeIsolate(isolate);
499+
if (!per_isolate) return false;
500+
return per_isolate->FlushForegroundTasksInternal();
498501
}
499502

500503
bool NodePlatform::IdleTasksEnabled(Isolate* isolate) {

src/node_worker.cc

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -270,26 +270,18 @@ void Worker::Run() {
270270
auto cleanup_env = OnScopeLeave([&]() {
271271
if (!env_) return;
272272
env_->set_can_call_into_js(false);
273-
Isolate::DisallowJavascriptExecutionScope disallow_js(isolate_,
274-
Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE);
275273

276274
{
277-
Context::Scope context_scope(env_->context());
278-
{
279-
Mutex::ScopedLock lock(mutex_);
280-
stopped_ = true;
281-
this->env_ = nullptr;
282-
}
283-
env_->set_stopping(true);
284-
env_->stop_sub_worker_contexts();
285-
env_->RunCleanup();
286-
RunAtExit(env_.get());
287-
288-
// This call needs to be made while the `Environment` is still alive
289-
// because we assume that it is available for async tracking in the
290-
// NodePlatform implementation.
291-
platform_->DrainTasks(isolate_);
275+
Mutex::ScopedLock lock(mutex_);
276+
stopped_ = true;
277+
this->env_ = nullptr;
292278
}
279+
280+
// TODO(addaleax): Try moving DisallowJavascriptExecutionScope into
281+
// FreeEnvironment().
282+
Isolate::DisallowJavascriptExecutionScope disallow_js(isolate_,
283+
Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE);
284+
env_.reset();
293285
});
294286

295287
if (is_stopped()) return;

0 commit comments

Comments
 (0)