Skip to content
Closed
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
node-api: fix crash in finalization
Refs: nodejs/node-addon-api#906
Refs: #37616

Fix crash introduced by #37616

Signed-off-by: Michael Dawson <mdawson@devrus.com>

PR-URL: #37876
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
  • Loading branch information
mhdawson authored and targos committed Apr 24, 2021
commit 180c33dbd446dfe251ea475f72b927a0f6802641
7 changes: 5 additions & 2 deletions src/js_native_api_v8.cc
Original file line number Diff line number Diff line change
Expand Up @@ -374,8 +374,11 @@ class Reference : public RefBase {
inline void Finalize(bool is_env_teardown = false) override {
// During env teardown, `~napi_env()` alone is responsible for finalizing.
// Thus, we don't want any stray gc passes to trigger a second call to
// `Finalize()`, so let's reset the persistent here.
if (is_env_teardown) _persistent.ClearWeak();
// `Finalize()`, so let's reset the persistent here if nothing is
// keeping it alive.
if (is_env_teardown && _persistent.IsWeak()) {
Copy link
Member

@legendecas legendecas Mar 31, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After digging into v8::PersistentBase and the second pass callbacks of GlobalHandles, I find out that _persistent.IsWeak() is always false after the first pass weak callback (in which we reset the persistent).

So this fix ultimately doesn't seem to be applied to the issue at all 😵 , so sorry for not picking this up earlier.

Anyway, the Persistent handle has to be reset on the first pass weak callback, thus the persistent no longer holds an address value of the global handle -- and unable to cancel the second pass callback by any means after the first pass callback. So here we have to ensure that the parameters of the weak info of second pass callbacks been kept alive until the second pass callbacks have been invoked.

I've submitted an issue to https://bugs.chromium.org/p/v8/issues/detail?id=11608. However, while I'm thinking that in the nature of the Persistent, it is possible that we can split the weak parameter lifetime from the v8impl::Reference. Trying to sum up a fix so that we can determine if the approach is acceptable.

_persistent.ClearWeak();
}

// Chain up to perform the rest of the finalization.
RefBase::Finalize(is_env_teardown);
Expand Down