mirror of
https://github.com/nodejs/node.git
synced 2026-11-09 15:11:11 -05:00
`Realm::RunCleanup()` finalizes the cppgc-managed wrappers it tracks so that none of them touches the Realm once it is gone, but it reaches them through weak persistents, and the GC clears those as soon as it finds a wrapper dead. With lazy and concurrent sweeping the destructor can run much later, so a wrapper collected shortly before `FreeEnvironment()` and swept after it was skipped by the cleanup and kept its `realm_`: `~CppgcMixin()` then wrote `should_purge_empty_cppgc_wrappers_` into the freed Realm, and a subclass destructor calling `Finalize()` as documented would have called `Clean()` with a dangling Realm. A Worker that compiles a few `vm.Script`s, gets a full GC from external memory pressure and calls `process.exit()` is enough to hit the first case. Move the Realm pointer into the list node, which the wrapper now owns and deletes in its destructor. `CppgcWrapperList::Cleanup()` unlinks every node, finalizing the wrappers that are still alive and clearing the Realm pointer for the collected ones, which only their own destructor may still touch. `Realm::PendingCleanup()` accounts for the list so it is always drained. The purge flag, its GC epilogue callback and `PurgeEmpty()` are no longer needed, and removing them also stops the list nodes of wrappers that are alive at `FreeEnvironment()` from leaking. Refs: https://github.com/nodejs/node/pull/56534 Signed-off-by: Shelley Vohr <shelley.vohr@gmail.com> PR-URL: https://github.com/nodejs/node/pull/65778 Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
27 lines
774 B
C++
27 lines
774 B
C++
#include "cppgc_helpers.h" // NOLINT(build/include_inline)
|
|
#include "cppgc_helpers-inl.h"
|
|
|
|
namespace node {
|
|
|
|
void CppgcWrapperList::Cleanup() {
|
|
while (!IsEmpty()) {
|
|
CppgcWrapperListNode* node = PopFront();
|
|
CppgcMixin* wrapper = node->persistent.Get();
|
|
if (wrapper != nullptr) wrapper->Finalize();
|
|
node->realm = nullptr;
|
|
}
|
|
}
|
|
|
|
void CppgcWrapperList::MemoryInfo(MemoryTracker* tracker) const {
|
|
for (auto node : *this) {
|
|
CppgcMixin* ptr = node->persistent.Get();
|
|
if (ptr != nullptr) {
|
|
// TODO(addaleax): Add weak edges instead of no edges once
|
|
// https://github.com/v8/v8/commit/e37cadf1143a8c5bbe44c0408186b5a26cc23863
|
|
// is available for us
|
|
tracker->Track(ptr, MemoryTracker::kWeakEdge);
|
|
}
|
|
}
|
|
}
|
|
} // namespace node
|