ObjectWrap destructors run after CleanupHookΒ #45088
Copy link
Copy link
Closed
Labels
node-apiIssues and PRs related to Node-API.Issues and PRs related to Node-API.
Description
Version
16.17.0
Platform
Ubuntu 20.04
Subsystem
napi
What steps will reproduce the bug?
Having ObjectWrap objects when destroying the environment. May be related to having stale Persistent objects.
How often does it reproduce? Is there a required condition?
Always
What is the expected behavior?
All C++ objects are destroyed before the CleanupHook
What do you see instead?
This is the stack trace
pymport-native.node!Napi::ObjectWrap<pymport::PyObj>::FinalizeCallback(napi_env env, void * data) (/home/mmom/src/pymport/node_modules/node-addon-api/napi-inl.h:4597)
v8impl::RefBase::Finalize(bool) (Unknown Source:0)
node_napi_env__::~node_napi_env__() (Unknown Source:0)
node::Environment::RunCleanup() (Unknown Source:0)
node::FreeEnvironment(node::Environment*) (Unknown Source:0)
node::NodeMainInstance::Run() (Unknown Source:0)
node::Start(int, char**) (Unknown Source:0)
libc.so.6!__libc_start_main(int (*)(int, char **, char **) main, int argc, char ** argv, int (*)(int, char **, char **) init, void (*)(void) fini, void (*)(void) rtld_fini, void * stack_end) (/build/glibc-SzIz7B/glibc-2.31/csu/libc-start.c:308)
_start (Unknown Source:0)
Additional information
No response
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
node-apiIssues and PRs related to Node-API.Issues and PRs related to Node-API.
Activity
[-]GC runs after `CleanupHook`[/-][+]`ObjectWrap` destructors run after `CleanupHook`[/+]juanarbol commentedon Oct 24, 2022
cc @nodejs/node-api
legendecas commentedon Oct 24, 2022
Currently, the document only defines that cleanup hooks are run in a reversed order, but no words on if the cleanup hooks are run before any other finalizers. As the status quo, all cleanup hooks are run before the finalizers, regardless of their registration order, as the napi_env's own cleanup is registered before the registration of any addon's cleanup hooks.
I believe it would be more reasonable to run cleanup hooks after pending finalizers are drained. After the cleanup hooks are invoked, there should be no callbacks can calling into the addon again.
KevinEady commentedon Oct 24, 2022
Hi @legendecas , could this issue also be related to TSFN "release in ObjectWrap destructor" crash stacktraces we are seeing in nodejs/node-addon-api#1109?
legendecas commentedon Oct 26, 2022
@KevinEady thanks for the link. At first sight, it seems like a finalization order problem too. I'll take a look at both issues.
node-api: document node-api shutdown finalization
node-api: document node-api shutdown finalization
node-api: document node-api shutdown finalization
node-api: document node-api shutdown finalization
mmomtchev commentedon Dec 18, 2025
This is still the case in the latest Node 25, git checkout.
I see that the cleanup hooks are now explicitly sorted and run in reverse order.
However the problem is that my own module cleanup hook is registered after the cleanup hook of Node API itself - and this is the hook that runs the remaining destructors.
Look at the attached traces (git checkout from today).
I am working with a library that requires creating a context - which I do when the module is initialised - and destroying it on shutdown - which I do in a cleanup hook. Obviously, I am not supposed to continue destroying objects after I have destroyed the context.
I have instrumented the adding and calling of cleanup hooks in Node itself as well as the creation/destruction of the context and the individual object destructors.
We need some official way to solve this problem. This will certainly be a very common issue.
mmomtchev commentedon Dec 18, 2025
Maybe the destructors should be run in a separate cleanup hook to be registered after the module has finished its initialisation.
mmomtchev commentedon Dec 18, 2025
Using basic finalisers does not seem to change anything - those objects that are left over at the environment cleanup are still destroyed last.