Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Crash on node api add-on finalization #37236

Closed
legendecas opened this issue Feb 5, 2021 · 20 comments
Closed

Crash on node api add-on finalization #37236

legendecas opened this issue Feb 5, 2021 · 20 comments
Assignees
Labels
confirmed-bug Issues with confirmed bugs. node-api Issues and PRs related to the Node-API.

Comments

@legendecas
Copy link
Member

legendecas commented Feb 5, 2021

  • Version: v10.23.2, v12.20.1, v14.15.4, v15.8.0 (all latest lts and current version)
  • Platform: all
  • Subsystem: node-api

What steps will reproduce the bug?

Repo to re-produce: https://github.com/legendecas/repro-napi-v8impl-refbase-double-free

$ make
v14.15.4
force gc
fish: 'node --expose_gc index.js' terminated by signal SIGSEGV (Address boundary error)

How often does it reproduce? Is there a required condition?

Always.

What is the expected behavior?

No segment faults.

What do you see instead?

Segment faults on double free of v8impl::<anonymous>::RefBase. The RefBases were deleted once one module's napi_env was going to destroy, and the installed weak v8impl::Persistents of v8impl::<anonymous>Reference was not destroyed and these RefBase will be deleted again on finalization callbacks.

@legendecas legendecas added node-api Issues and PRs related to the Node-API. confirmed-bug Issues with confirmed bugs. labels Feb 5, 2021
@legendecas legendecas self-assigned this Feb 6, 2021
@gabrielschulhof
Copy link
Contributor

@legendecas the assumption is that once the environment begins the process of being torn down, no more gc runs will happen. This test AFAICT forces gc runs after napi_env teardown, so it is entirely possible that finalizers will be called after napi_env's FinalizeAll. TBH the scenario created in the test seems unlikely to happen under normal circumstances. OTOH, it would of course be ideal to handle even unusual circumstances. Nevertheless, please be careful to not re-introduce the problem fixed in c822ba7!

@RaisinTen
Copy link
Contributor

Is this related: #36868?

@legendecas
Copy link
Member Author

@gabrielschulhof we just identified the problem in random CI failures on our system. The force GC in the repro is to ensure the reproduce is reliable to show how the problem happens in the case. The crashes do happens in a low rate, but I have to say it's not unlikely to happen: in our internal tests the ratio is roughly 1/6 to crash on exit.

@legendecas
Copy link
Member Author

Is this related: #36868?

Yes, the crash call stacks seem very similar to the case. I strongly believe it's the same problem.

@gabrielschulhof
Copy link
Contributor

@legendecas I ran the repro and it dies reliably even without --expose-gc.

@gabrielschulhof
Copy link
Contributor

@legendecas

diff --git a/src/js_native_api_v8.cc b/src/js_native_api_v8.cc
index e037c4297d..22932dc6b9 100644
--- a/src/js_native_api_v8.cc
+++ b/src/js_native_api_v8.cc
@@ -199,7 +199,8 @@ class RefBase : protected Finalizer, RefTracker {
           void* finalize_hint)
        : Finalizer(env, finalize_callback, finalize_data, finalize_hint),
         _refcount(initial_refcount),
-        _delete_self(delete_self) {
+        _delete_self(delete_self),
+        _is_gone(nullptr) {
     Link(finalize_callback == nullptr
         ? &env->reflist
         : &env->finalizing_reflist);
@@ -220,7 +221,10 @@ class RefBase : protected Finalizer, RefTracker {
                        finalize_hint);
   }
 
-  virtual ~RefBase() { Unlink(); }
+  virtual ~RefBase() {
+    if (_is_gone != nullptr) *_is_gone = true;
+    Unlink();
+  }
 
   inline void* Data() {
     return _finalize_data;
@@ -270,10 +274,14 @@ class RefBase : protected Finalizer, RefTracker {
 
  protected:
   inline void Finalize(bool is_env_teardown = false) override {
+    bool reference_is_gone = false;
+    _is_gone = &reference_is_gone;
     if (_finalize_callback != nullptr) {
       _env->CallFinalizer(_finalize_callback, _finalize_data, _finalize_hint);
     }
 
+    if (reference_is_gone) return;
+
     // this is safe because if a request to delete the reference
     // is made in the finalize_callback it will defer deletion
     // to this block and set _delete_self to true
@@ -287,6 +295,7 @@ class RefBase : protected Finalizer, RefTracker {
  private:
   uint32_t _refcount;
   bool _delete_self;
+  bool* _is_gone;
 };
 
 class Reference : public RefBase {

seems to avert the problem without breaking the tests.

@gabrielschulhof
Copy link
Contributor

@legendecas in your repro you delete wrapper_ in two places:

  1. In the instance data finalizer:
    https://github.com/legendecas/repro-napi-v8impl-refbase-double-free/blob/5b0ae1874b9b26fb0fe453565484a004801c70e4/test.cc#L56
  2. In the napi_wrap finalizer (which calls ~MyObject)
    https://github.com/legendecas/repro-napi-v8impl-refbase-double-free/blob/5b0ae1874b9b26fb0fe453565484a004801c70e4/test.cc#L27

So, it looks like the double free is not really caused by anything Node-API does wrong.

@gabrielschulhof
Copy link
Contributor

NM. Looks like it crashes even if I remove the napi_delete_reference from the instance finalizer.

@gabrielschulhof
Copy link
Contributor

@legendecas I have been able to reduce the test case to legendecas/repro-napi-v8impl-refbase-double-free#1 while still retaining the crash.

@gabrielschulhof
Copy link
Contributor

I think the key is the napi_reference_ref it performs on the reference returned from napi_wrap.

gabrielschulhof pushed a commit to gabrielschulhof/node that referenced this issue Feb 10, 2021
The finalizer normally never gets called while a reference is strong.
However, during environment shutdown all finalizers must get called. In
order to unify the deferring behavior with that of a regular
finalization, we must force the reference to be weak when we call its
finalizer during environment shutdown.

Fixes: nodejs#37236
Co-authored-by: Chengzhong Wu <[email protected]>
@legendecas
Copy link
Member Author

legendecas commented Feb 18, 2021

@gabrielschulhof Yeah, you're right. I found I've been mistaken on the repro. In the reproduction, there are strong references to the object, this is not the case I was intended to show in the first place. After reading #37303 and tried the PR on my internal case and it does crash regardlessly, I discovered that my original crash on double free of v8impl::reference is not caused by strong references but weak references. These references were set weak before the process going to exit - there is a uv ref on the corresponding handle so only after the set weak the process is going to exit. I'll double-check the re-production to make a reliable reproduction on weak references.

@legendecas
Copy link
Member Author

legendecas commented Feb 18, 2021

The original code causing the crash is built on top of node-addon-api, and there is no napi_delete_reference (or napi_remove_wrap used directly except from Napi::~Reference, which Napi::ObjectWrap relies on to remove the wrap (not strictly remove the "wrap", but the reference object) on successful construction. So I may take node-addon-api into count for another reliable repro.

gabrielschulhof pushed a commit to gabrielschulhof/node that referenced this issue Feb 18, 2021
The finalizer normally never gets called while a reference is strong.
However, during environment shutdown all finalizers must get called. In
order to unify the deferring behavior with that of a regular
finalization, we must force the reference to be weak when we call its
finalizer during environment shutdown.

Fixes: nodejs#37236
Co-authored-by: Chengzhong Wu <[email protected]>
@legendecas
Copy link
Member Author

legendecas commented Feb 19, 2021

https://github.com/legendecas/repro-napi-v8impl-refbase-double-free/blob/master/node_addon_api.cc I crafted a mimic of GC on weak references after addon env teardown. The original environment is running in nyc augmented, there are lots of test cases in the case. So I'm assuming there is a chance that gc may be triggered at the time of clean-up (dumping coverage data to disk). Anyway, the crafted reproduction is a quite valid case of node-addon-api/node-api, I suppose the problem is still valid in the case.

(SideNote: the new case has been ran with the latest main branch with the fix of #37303, it does crash)

@gabrielschulhof

@legendecas legendecas reopened this Feb 19, 2021
@gabrielschulhof
Copy link
Contributor

@legendecas this is the crash I was able to reproduce:

#0  0x00007ffff7a8de35 in raise () from /lib64/libc.so.6
#1  0x00007ffff7a78895 in abort () from /lib64/libc.so.6
#2  0x00000000010af676 in node::Abort () at ../src/node_errors.cc:254
#3  0x00000000010b04b3 in node::OnFatalError (location=0x7fffffffd150 "Error::Error", message=0x5e6a620 "napi_create_reference") at ../src/node_errors.cc:441
#4  0x00000000010b035e in node::FatalError (location=0x7fffffffd150 "Error::Error", message=0x5e6a620 "napi_create_reference") at ../src/node_errors.cc:415
#5  0x000000000105bda1 in napi_fatal_error (location=0x7ffff7fc00cb "Error::Error", location_len=18446744073709551615, message=0x7ffff7fc00b5 "napi_create_reference", 
    message_len=18446744073709551615) at ../src/node_api.cc:749
#6  0x00007ffff7fbda44 in Napi::Error::Fatal (location=0x7ffff7fc00cb "Error::Error", message=0x7ffff7fc00b5 "napi_create_reference")
    at /home/nix/repro-napi-v8impl-refbase-double-free/node_modules/node-addon-api/napi-inl.h:2305
#7  0x00007ffff7fbdaf0 in Napi::Error::Error (this=0x7fffffffd270, env=0x5ed4ef0, value=0x5e5b0d8)
    at /home/nix/repro-napi-v8impl-refbase-double-free/node_modules/node-addon-api/napi-inl.h:2317
#8  0x00007ffff7fbd9b4 in Napi::Error::New (env=0x5ed4ef0) at /home/nix/repro-napi-v8impl-refbase-double-free/node_modules/node-addon-api/napi-inl.h:2293
#9  0x00007ffff7fbd79b in Napi::Function::Call (this=0x7fffffffd390, recv=0x5deaf28, argc=0, args=0x0)
    at /home/nix/repro-napi-v8impl-refbase-double-free/node_modules/node-addon-api/napi-inl.h:2045
#10 0x00007ffff7fbd6bc in Napi::Function::Call (this=0x7fffffffd390, recv=0x5deaf28, args=...) at /home/nix/repro-napi-v8impl-refbase-double-free/node_modules/node-addon-api/napi-inl.h:2034
#11 0x00007ffff7fbd674 in Napi::Function::Call (this=0x7fffffffd390, args=...) at /home/nix/repro-napi-v8impl-refbase-double-free/node_modules/node-addon-api/napi-inl.h:2022
#12 0x00007ffff7fbae44 in (anonymous namespace)::MyObject::Finalize (this=0x5ed5630, env=...) at ../node_addon_api.cc:42
#13 0x00007ffff7fbb882 in Napi::ObjectWrap<(anonymous namespace)::MyObject>::FinalizeCallback (env=0x5ed4ef0, data=0x5ed5630)
    at /home/nix/repro-napi-v8impl-refbase-double-free/node_modules/node-addon-api/napi-inl.h:4021
#14 0x000000000105feeb in napi_env__::CallFinalizer(void (*)(napi_env__*, void*, void*), void*, void*)::{lambda(napi_env__*)#1}::operator()(napi_env__*) const (__closure=0x7fffffffd4f0, 
    env=0x5ed4ef0) at ../src/js_native_api_v8.h:107
#15 0x000000000106082d in napi_env__::CallIntoModule<napi_env__::CallFinalizer(void (*)(napi_env__*, void*, void*), void*, void*)::{lambda(napi_env__*)#1}, void (napi_env__*, v8::Local<napi_env__::CallFinalizer(void (*)(napi_env__*, void*, void*), void*, void*)::{lambda(napi_env__*)#1}::Value>)>(napi_env__::CallFinalizer(void (*)(napi_env__*, void*, void*), void*, void*)::{lambda(napi_env__*)#1}&&, void (&&)(napi_env__*, v8::Local<napi_env__::CallFinalizer(void (*)(napi_env__*, void*, void*), void*, void*)::{lambda(napi_env__*)#1}::Value>)) (this=0x5ed4ef0, 
    call=..., handle_exception=@0x10412d6: {void (napi_env__ *, v8::Local<v8::Value>)} 0x10412d6 <napi_env__::HandleThrow(napi_env__*, v8::Local<v8::Value>)>)
    at ../src/js_native_api_v8.h:95
#16 0x000000000105ff4d in napi_env__::CallFinalizer (this=0x5ed4ef0, cb=0x7ffff7fbb80e <Napi::ObjectWrap<(anonymous namespace)::MyObject>::FinalizeCallback(napi_env, void*, void*)>, 
    data=0x5ed5630, hint=0x0) at ../src/js_native_api_v8.h:106
#17 0x0000000001033641 in v8impl::(anonymous namespace)::RefBase::Finalize (this=0x5e7d0d0, is_env_teardown=true) at ../src/js_native_api_v8.cc:281
#18 0x000000000105fcd8 in v8impl::RefTracker::FinalizeAll (list=0x5ed4f28) at ../src/js_native_api_v8.h:43
#19 0x000000000105fdfc in napi_env__::~napi_env__ (this=0x5ed4ef0, __in_chrg=<optimized out>) at ../src/js_native_api_v8.h:66
#20 0x00000000010637ca in node_napi_env__::~node_napi_env__ (this=0x5ed4ef0, __in_chrg=<optimized out>) at ../src/node_api.cc:17
#21 0x00000000010637e6 in node_napi_env__::~node_napi_env__ (this=0x5ed4ef0, __in_chrg=<optimized out>) at ../src/node_api.cc:17
#22 0x00000000010412d3 in napi_env__::Unref (this=0x5ed4ef0) at ../src/js_native_api_v8.h:77
#23 0x0000000001059f94 in v8impl::(anonymous namespace)::<lambda(void*)>::operator()(void *) const (__closure=0x0, arg=0x5ed4ef0) at ../src/node_api.cc:109
#24 0x0000000001059fb4 in v8impl::(anonymous namespace)::<lambda(void*)>::_FUN(void *) () at ../src/node_api.cc:110
#25 0x0000000000ff5309 in node::Environment::RunCleanup (this=0x5ec07d0) at ../src/env.cc:677
#26 0x0000000000f80471 in node::FreeEnvironment (env=0x5ec07d0) at ../src/api/environment.cc:371
#27 0x0000000000f7c626 in node::FunctionDeleter<node::Environment, &node::FreeEnvironment>::operator() (this=0x7fffffffda30, pointer=0x5ec07d0) at ../src/util.h:636
#28 0x0000000000f7bff8 in std::unique_ptr<node::Environment, node::FunctionDeleter<node::Environment, &node::FreeEnvironment> >::~unique_ptr (this=0x7fffffffda30, __in_chrg=<optimized out>)
    at /usr/include/c++/9/bits/unique_ptr.h:292
#29 0x000000000111c2db in node::NodeMainInstance::Run (this=0x7fffffffdad0, env_info=0x5d6f740 <node::env_info>) at ../src/node_main_instance.cc:135
#30 0x000000000105450e in node::Start (argc=3, argv=0x7fffffffdd38) at ../src/node.cc:1079
#31 0x0000000002930b72 in main (argc=3, argv=0x7fffffffdd38) at ../src/node_main.cc:127

This crashes at https://github.com/legendecas/repro-napi-v8impl-refbase-double-free/blob/master/node_addon_api.cc#L42 because one cannot call a JS function during environment teardown. It ultimately results in a fatal error, because one cannot throw exceptions in environment teardown either. We really need to distinguish between napi_pending_exception and napi_cannot_call_into_js, but we've deemed that to be semver-major.

@mhdawson we may want to reconsider the semverity of napi_cannot_call_into_js because we're seeing more and more cases where things are resulting in a fatal error because of attempts to call into JS during teardown.

@gabrielschulhof
Copy link
Contributor

@mhdawson in support of that, if we were to all of a sudden return napi_cannot_call_into_js instead of napi_pending_exception yes, we may break some folks who handle the case of napi_pending_exception, but I suspect most folks will just crash with the above stack because they do not handle any off-nominal case.

@gabrielschulhof
Copy link
Contributor

@legendecas I forgot to mention that I got the above stack with 03806a0 (IOW with #37303 already landed).

@legendecas
Copy link
Member Author

@gabrielschulhof I tried on a fresh build of main branch, it looks like there is a significant difference between v14.x with 03806a0 cherry-picked and the main branch results.

On v14.x with 03806a0 cherry-picked, the test case does crash on v8impl::RefBase. However, I believe the initial thought is that there are chances that GC may run on the env teardown (not sure on main branch since it disallow javascript execution on env teardown) and get into race conditions as https://github.com/nodejs/node/blob/master/src/js_native_api_v8.cc#L232 suggests.

@gabrielschulhof
Copy link
Contributor

@legendecas it sounds like the problem is fixed on the main branch but not on v14.x, right? I will try to repro with v14.x + 03806a0 when I get a chance. It sounds like the backport will be non-trivial.

@legendecas
Copy link
Member Author

legendecas commented Feb 22, 2021

@gabrielschulhof on main branch calling into js on tear down will get an exception from v8 that we can not call into js at that time. So this reproduction does not work out - which relies on trigger GC by calling global.gc in js. And the exception thrown by v8 is a string, that will crash node-addon-api for nodejs/node-addon-api#912 (the crash above #37236 (comment))

So I tried to backport 03806a0 on v14.x locally and it did crash on v8impl::reference as expected.

targos pushed a commit that referenced this issue Feb 28, 2021
The finalizer normally never gets called while a reference is strong.
However, during environment shutdown all finalizers must get called. In
order to unify the deferring behavior with that of a regular
finalization, we must force the reference to be weak when we call its
finalizer during environment shutdown.

Fixes: #37236
Co-authored-by: Chengzhong Wu <[email protected]>
PR-URL: #37303
Reviewed-By: Chengzhong Wu <[email protected]>
Reviewed-By: Michael Dawson <[email protected]>
gabrielschulhof pushed a commit to gabrielschulhof/node that referenced this issue Mar 6, 2021
The finalizer normally never gets called while a reference is strong.
However, during environment shutdown all finalizers must get called. In
order to unify the deferring behavior with that of a regular
finalization, we must force the reference to be weak when we call its
finalizer during environment shutdown.

Fixes: nodejs#37236
Co-authored-by: Chengzhong Wu <[email protected]>
PR-URL: nodejs#37303
Reviewed-By: Chengzhong Wu <[email protected]>
Reviewed-By: Michael Dawson <[email protected]>
gabrielschulhof added a commit to gabrielschulhof/node that referenced this issue Mar 6, 2021
A gc may happen during environment teardown. Thus, during finalization
initiated by environment teardown we must remove the V8 finalizer
before calling the Node-API finalizer.

Fixes: nodejs#37236
PR-URL: nodejs#37616
@legendecas legendecas linked a pull request Mar 15, 2021 that will close this issue
gabrielschulhof pushed a commit to gabrielschulhof/node that referenced this issue Mar 19, 2021
The finalizer normally never gets called while a reference is strong.
However, during environment shutdown all finalizers must get called. In
order to unify the deferring behavior with that of a regular
finalization, we must force the reference to be weak when we call its
finalizer during environment shutdown.

Fixes: nodejs#37236
Co-authored-by: Chengzhong Wu <[email protected]>
PR-URL: nodejs#37303
Reviewed-By: Chengzhong Wu <[email protected]>
Reviewed-By: Michael Dawson <[email protected]>
gabrielschulhof added a commit to gabrielschulhof/node that referenced this issue Mar 19, 2021
A gc may happen during environment teardown. Thus, during finalization
initiated by environment teardown we must remove the V8 finalizer
before calling the Node-API finalizer.

Fixes: nodejs#37236
PR-URL: nodejs#37616
Reviewed-By: Chengzhong Wu <[email protected]>
Reviewed-By: Michael Dawson <[email protected]>
gabrielschulhof pushed a commit to gabrielschulhof/node that referenced this issue Mar 19, 2021
The finalizer normally never gets called while a reference is strong.
However, during environment shutdown all finalizers must get called. In
order to unify the deferring behavior with that of a regular
finalization, we must force the reference to be weak when we call its
finalizer during environment shutdown.

Fixes: nodejs#37236
Co-authored-by: Chengzhong Wu <[email protected]>
PR-URL: nodejs#37303
Reviewed-By: Chengzhong Wu <[email protected]>
Reviewed-By: Michael Dawson <[email protected]>
gabrielschulhof added a commit to gabrielschulhof/node that referenced this issue Mar 19, 2021
A gc may happen during environment teardown. Thus, during finalization
initiated by environment teardown we must remove the V8 finalizer
before calling the Node-API finalizer.

Fixes: nodejs#37236
PR-URL: nodejs#37616
Reviewed-By: Chengzhong Wu <[email protected]>
Reviewed-By: Michael Dawson <[email protected]>
ruyadorno pushed a commit that referenced this issue Mar 24, 2021
A gc may happen during environment teardown. Thus, during finalization
initiated by environment teardown we must remove the V8 finalizer
before calling the Node-API finalizer.

Fixes: #37236
PR-URL: #37616
Reviewed-By: Chengzhong Wu <[email protected]>
Reviewed-By: Michael Dawson <[email protected]>
gabrielschulhof pushed a commit to gabrielschulhof/node that referenced this issue Mar 26, 2021
The finalizer normally never gets called while a reference is strong.
However, during environment shutdown all finalizers must get called. In
order to unify the deferring behavior with that of a regular
finalization, we must force the reference to be weak when we call its
finalizer during environment shutdown.

Fixes: nodejs#37236
Co-authored-by: Chengzhong Wu <[email protected]>
PR-URL: nodejs#37303
Reviewed-By: Chengzhong Wu <[email protected]>
Reviewed-By: Michael Dawson <[email protected]>
gabrielschulhof added a commit to gabrielschulhof/node that referenced this issue Mar 26, 2021
A gc may happen during environment teardown. Thus, during finalization
initiated by environment teardown we must remove the V8 finalizer
before calling the Node-API finalizer.

Fixes: nodejs#37236
PR-URL: nodejs#37616
Reviewed-By: Chengzhong Wu <[email protected]>
Reviewed-By: Michael Dawson <[email protected]>
targos pushed a commit to gabrielschulhof/node that referenced this issue Apr 24, 2021
The finalizer normally never gets called while a reference is strong.
However, during environment shutdown all finalizers must get called. In
order to unify the deferring behavior with that of a regular
finalization, we must force the reference to be weak when we call its
finalizer during environment shutdown.

Fixes: nodejs#37236
Co-authored-by: Chengzhong Wu <[email protected]>
PR-URL: nodejs#37303
Reviewed-By: Chengzhong Wu <[email protected]>
Reviewed-By: Michael Dawson <[email protected]>
targos pushed a commit to gabrielschulhof/node that referenced this issue Apr 24, 2021
A gc may happen during environment teardown. Thus, during finalization
initiated by environment teardown we must remove the V8 finalizer
before calling the Node-API finalizer.

Fixes: nodejs#37236
PR-URL: nodejs#37616
Reviewed-By: Chengzhong Wu <[email protected]>
Reviewed-By: Michael Dawson <[email protected]>
targos pushed a commit that referenced this issue Apr 26, 2021
The finalizer normally never gets called while a reference is strong.
However, during environment shutdown all finalizers must get called. In
order to unify the deferring behavior with that of a regular
finalization, we must force the reference to be weak when we call its
finalizer during environment shutdown.

Fixes: #37236
Co-authored-by: Chengzhong Wu <[email protected]>
PR-URL: #37303
Backport-PR-URL: #37802
Reviewed-By: Chengzhong Wu <[email protected]>
Reviewed-By: Michael Dawson <[email protected]>
targos pushed a commit that referenced this issue Apr 26, 2021
A gc may happen during environment teardown. Thus, during finalization
initiated by environment teardown we must remove the V8 finalizer
before calling the Node-API finalizer.

Fixes: #37236
PR-URL: #37616
Backport-PR-URL: #37802
Reviewed-By: Chengzhong Wu <[email protected]>
Reviewed-By: Michael Dawson <[email protected]>
@yisibl
Copy link

yisibl commented Mar 17, 2022

Has the patch for this issue been merged into Node.js 12.x?

I'm getting a segmentation fault error in Node.js 12, is it related to this issue? See yisibl/svg-sprite#3

legendecas added a commit to legendecas/node that referenced this issue Mar 29, 2022
The finalizer normally never gets called while a reference is strong.
However, during environment shutdown all finalizers must get called. In
order to unify the deferring behavior with that of a regular
finalization, we must force the reference to be weak when we call its
finalizer during environment shutdown.

Fixes: nodejs#37236
Co-authored-by: Chengzhong Wu <[email protected]>
PR-URL: nodejs#37303
Reviewed-By: Chengzhong Wu <[email protected]>
Reviewed-By: Michael Dawson <[email protected]>
legendecas pushed a commit to legendecas/node that referenced this issue Mar 29, 2022
A gc may happen during environment teardown. Thus, during finalization
initiated by environment teardown we must remove the V8 finalizer
before calling the Node-API finalizer.

Fixes: nodejs#37236
PR-URL: nodejs#37616
Reviewed-By: Chengzhong Wu <[email protected]>
Reviewed-By: Michael Dawson <[email protected]>
richardlau pushed a commit that referenced this issue Mar 30, 2022
The finalizer normally never gets called while a reference is strong.
However, during environment shutdown all finalizers must get called. In
order to unify the deferring behavior with that of a regular
finalization, we must force the reference to be weak when we call its
finalizer during environment shutdown.

Fixes: #37236
Co-authored-by: Chengzhong Wu <[email protected]>
PR-URL: #37303
Backport-PR-URL: #42512
Reviewed-By: Chengzhong Wu <[email protected]>
Reviewed-By: Michael Dawson <[email protected]>
richardlau pushed a commit that referenced this issue Mar 30, 2022
A gc may happen during environment teardown. Thus, during finalization
initiated by environment teardown we must remove the V8 finalizer
before calling the Node-API finalizer.

Fixes: #37236
PR-URL: #37616
Backport-PR-URL: #42512
Reviewed-By: Chengzhong Wu <[email protected]>
Reviewed-By: Michael Dawson <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
confirmed-bug Issues with confirmed bugs. node-api Issues and PRs related to the Node-API.
Projects
None yet
4 participants