Skip to content

Commit 10bf2eb

Browse files
joyeecheungtargos
authored andcommitted
src,test: unregister the isolate after disposal and before freeing
The order of these calls is important. When the Isolate is disposed, it may still post tasks to the platform, so it must still be registered for the task runner to be found from the map. After the isolate is torn down, we need to remove it from the map before we can free the address, so that when another Isolate::Allocate() is called, that would not be allocated to the same address and be registered on an existing map entry.
1 parent da9d784 commit 10bf2eb

12 files changed

+28
-34
lines changed

src/api/embed_helpers.cc

+1-2
Original file line numberDiff line numberDiff line change
@@ -244,8 +244,7 @@ CommonEnvironmentSetup::~CommonEnvironmentSetup() {
244244
if (impl_->snapshot_creator.has_value()) {
245245
impl_->snapshot_creator.reset();
246246
}
247-
isolate->Dispose();
248-
impl_->platform->UnregisterIsolate(isolate);
247+
impl_->platform->DisposeIsolate(isolate);
249248

250249
// Wait until the platform has cleaned up all relevant resources.
251250
while (!platform_finished)

src/node.h

+3
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,9 @@ class NODE_EXTERN MultiIsolatePlatform : public v8::Platform {
449449
// pending delayed tasks scheduled for that isolate.
450450
// This needs to be called right after calling `Isolate::Dispose()`.
451451
virtual void UnregisterIsolate(v8::Isolate* isolate) = 0;
452+
// This disposes, unregisters and frees up an isolate that's allocated using
453+
// v8::Isolate::Allocate() in the correct order to prevent race conditions.
454+
void DisposeIsolate(v8::Isolate* isolate);
452455

453456
// The platform should call the passed function once all state associated
454457
// with the given isolate has been cleaned up. This can, but does not have to,

src/node_main_instance.cc

+1-3
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,7 @@ NodeMainInstance::~NodeMainInstance() {
8282
// IsolateData must be freed before UnregisterIsolate() is called.
8383
isolate_data_.reset();
8484
}
85-
// TODO(joyeecheung): split Isolate::Free() here?
86-
isolate_->Dispose();
87-
platform_->UnregisterIsolate(isolate_);
85+
platform_->DisposeIsolate(isolate_);
8886
}
8987

9088
ExitCode NodeMainInstance::Run() {

src/node_platform.cc

+14
Original file line numberDiff line numberDiff line change
@@ -669,4 +669,18 @@ std::queue<std::unique_ptr<T>> TaskQueue<T>::Locked::PopAll() {
669669
return result;
670670
}
671671

672+
void MultiIsolatePlatform::DisposeIsolate(Isolate* isolate) {
673+
// The order of these calls is important. When the Isolate is disposed,
674+
// it may still post tasks to the platform, so it must still be registered
675+
// for the task runner to be found from the map. After the isolate is torn
676+
// down, we need to remove it from the map before we can free the address,
677+
// so that when another Isolate::Allocate() is called, that would not be
678+
// allocated to the same address and be registered on an existing map
679+
// entry.
680+
// Refs: https://github.com/nodejs/node/issues/30846
681+
isolate->Deinitialize();
682+
this->UnregisterIsolate(isolate);
683+
Isolate::Free(isolate);
684+
}
685+
672686
} // namespace node

src/node_worker.cc

+1-13
Original file line numberDiff line numberDiff line change
@@ -230,19 +230,7 @@ class WorkerThreadData {
230230
*static_cast<bool*>(data) = true;
231231
}, &platform_finished);
232232

233-
// The order of these calls is important; if the Isolate is first disposed
234-
// and then unregistered, there is a race condition window in which no
235-
// new Isolate at the same address can successfully be registered with
236-
// the platform.
237-
// (Refs: https://github.com/nodejs/node/issues/30846)
238-
// TODO(joyeecheung): we reversed the order because the task runner has
239-
// to be available to handle GC tasks posted during isolate disposal.
240-
// If this flakes comes back again, try splitting Isolate::Delete out
241-
// so that the pointer is still available as map key after disposal
242-
// and we delete it after unregistration.
243-
// Refs: https://github.com/nodejs/node/pull/53086#issuecomment-2128056793
244-
isolate->Dispose();
245-
w_->platform_->UnregisterIsolate(isolate);
233+
w_->platform_->DisposeIsolate(isolate);
246234

247235
// Wait until the platform has cleaned up all relevant resources.
248236
while (!platform_finished) {

src/util.cc

+1-2
Original file line numberDiff line numberDiff line change
@@ -729,8 +729,7 @@ RAIIIsolateWithoutEntering::RAIIIsolateWithoutEntering(const SnapshotData* data)
729729
}
730730

731731
RAIIIsolateWithoutEntering::~RAIIIsolateWithoutEntering() {
732-
isolate_->Dispose();
733-
per_process::v8_platform.Platform()->UnregisterIsolate(isolate_);
732+
per_process::v8_platform.Platform()->DisposeIsolate(isolate_);
734733
}
735734

736735
RAIIIsolate::RAIIIsolate(const SnapshotData* data)

test/cctest/node_test_fixture.h

+1-2
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,7 @@ class NodeTestFixture : public NodeZeroIsolateTestFixture {
123123
void TearDown() override {
124124
platform->DrainTasks(isolate_);
125125
isolate_->Exit();
126-
isolate_->Dispose();
127-
platform->UnregisterIsolate(isolate_);
126+
platform->DisposeIsolate(isolate_);
128127
isolate_ = nullptr;
129128
NodeZeroIsolateTestFixture::TearDown();
130129
}

test/cctest/test_cppgc.cc

+1-2
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,7 @@ TEST_F(NodeZeroIsolateTestFixture, ExistingCppHeapTest) {
9696
platform->DrainTasks(isolate);
9797
}
9898

99-
isolate->Dispose();
100-
platform->UnregisterIsolate(isolate);
99+
platform->DisposeIsolate(isolate);
101100

102101
// Check that all the objects are created and destroyed properly.
103102
EXPECT_EQ(CppGCed::kConstructCount, 100);

test/cctest/test_environment.cc

+2-4
Original file line numberDiff line numberDiff line change
@@ -544,8 +544,7 @@ TEST_F(EnvironmentTest, InspectorMultipleEmbeddedEnvironments) {
544544
node::FreeIsolateData(isolate_data);
545545
}
546546

547-
isolate->Dispose();
548-
data->platform->UnregisterIsolate(isolate);
547+
data->platform->DisposeIsolate(isolate);
549548
uv_run(&loop, UV_RUN_DEFAULT);
550549
CHECK_EQ(uv_loop_close(&loop), 0);
551550

@@ -678,8 +677,7 @@ TEST_F(NodeZeroIsolateTestFixture, CtrlCWithOnlySafeTerminationTest) {
678677
}
679678

680679
// Cleanup.
681-
isolate->Dispose();
682-
platform->UnregisterIsolate(isolate);
680+
platform->DisposeIsolate(isolate);
683681
}
684682
#endif // _WIN32
685683

test/cctest/test_platform.cc

+1-2
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,7 @@ TEST_F(NodeZeroIsolateTestFixture, IsolatePlatformDelegateTest) {
107107

108108
// Graceful shutdown
109109
delegate->Shutdown();
110-
isolate->Dispose();
111-
platform->UnregisterIsolate(isolate);
110+
platform->DisposeIsolate(isolate);
112111
}
113112

114113
TEST_F(PlatformTest, TracingControllerNullptr) {

test/fuzzers/fuzz_env.cc

+1-2
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,7 @@ class FuzzerFixtureHelper {
6565
void Teardown() {
6666
platform->DrainTasks(isolate_);
6767
isolate_->Exit();
68-
isolate_->Dispose();
69-
platform->UnregisterIsolate(isolate_);
68+
platform->DisposeIsolate(isolate_);
7069
isolate_ = nullptr;
7170
}
7271
};

test/fuzzers/fuzz_strings.cc

+1-2
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,7 @@ class FuzzerFixtureHelper {
7272
void Teardown() {
7373
platform->DrainTasks(isolate_);
7474
isolate_->Exit();
75-
isolate_->Dispose();
76-
platform->UnregisterIsolate(isolate_);
75+
platform->DisposeIsolate(isolate_);
7776
isolate_ = nullptr;
7877
}
7978
};

0 commit comments

Comments
 (0)