-
Notifications
You must be signed in to change notification settings - Fork 30k
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
src: make realm binding data store weak #47688
Conversation
Review requested:
|
// This is necessary to avoid cleaning up base objects before their scheduled | ||
// weak callbacks are invoked, which can lead to accessing to v8 apis during | ||
// the first pass of the weak callback. | ||
realm->env()->SetImmediate([realm](Environment* env) { delete realm; }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just remembered that technically shadow realms can outlive the environment...(which is why I added the if (env_ != nullptr)
branch in the destructor of shadow realms, I think I ran into that before)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is going to lead to crashes if the ream has access to any libuv handles within it. The problem is that any handles could emit data and ultimately call into JS.
IMHO the mechanism needs to be more sophisticated and we should track any native resource that the realm can spawn and let the ream be collected only after they have all been disposed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the ideas. Also, I noticed that the ASan build is failing for the URL binding data. I'm going to see how to address the failure too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added a cleanup for ShadowRealms when the environment is being freed. This ensures that no shadow realms can outlive the lifetime of the environment. Similar to BaseObjects, no BaseObjects can outlive their creation realm (https://github.com/nodejs/node/blob/main/src/node_realm.cc#L27).
As for the ASan failure of the URL binding data, I've removed the aliased buffer's weak callback as the validness of the aliased buffer can be checked with the emptiness of the persistent handle.
Would you mind taking a look again? Thank you!
2f14395
to
eadbf52
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm
@joyeecheung would you mind taking a look at this again? Thank you! <3 |
@@ -915,10 +928,6 @@ Environment::~Environment() { | |||
addon.Close(); | |||
} | |||
} | |||
|
|||
for (auto realm : shadow_realms_) { | |||
realm->OnEnvironmentDestruct(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add a test that creates a bunch of shadow realms and then generates a heap snapshot? I think that's how I ran into the shadow realms outliving shadow realms issue and is why this is necessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a new test test/pummel/test-heapdump-shadow-realm.js
.
An AliasedBuffer can be nested in a BaseObject and their weak callbacks invoke order are not guaranteed. Prevent aliased buffer from being accessed in its weak callback as its validness can be checked with the emptiness of the persistent handle.
The binding data must be weak so that it won't keep the realm reachable from strong GC roots indefinitely. The wrapper object of binding data should be referenced from JavaScript, thus the binding data should be reachable throughout the lifetime of the realm.
46ce6c0
to
952cabc
Compare
Rebased on the tip of the main branch to address CI coverage reports. |
Landed in 8bc6e19...ac0853c |
An AliasedBuffer can be nested in a BaseObject and their weak callbacks invoke order are not guaranteed. Prevent aliased buffer from being accessed in its weak callback as its validness can be checked with the emptiness of the persistent handle. PR-URL: #47688 Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Joyee Cheung <[email protected]>
The binding data must be weak so that it won't keep the realm reachable from strong GC roots indefinitely. The wrapper object of binding data should be referenced from JavaScript, thus the binding data should be reachable throughout the lifetime of the realm. PR-URL: #47688 Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Joyee Cheung <[email protected]>
An AliasedBuffer can be nested in a BaseObject and their weak callbacks invoke order are not guaranteed. Prevent aliased buffer from being accessed in its weak callback as its validness can be checked with the emptiness of the persistent handle. PR-URL: #47688 Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Joyee Cheung <[email protected]>
The binding data must be weak so that it won't keep the realm reachable from strong GC roots indefinitely. The wrapper object of binding data should be referenced from JavaScript, thus the binding data should be reachable throughout the lifetime of the realm. PR-URL: #47688 Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Joyee Cheung <[email protected]>
An AliasedBuffer can be nested in a BaseObject and their weak callbacks invoke order are not guaranteed. Prevent aliased buffer from being accessed in its weak callback as its validness can be checked with the emptiness of the persistent handle. PR-URL: nodejs#47688 Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Joyee Cheung <[email protected]>
The binding data must be weak so that it won't keep the realm reachable from strong GC roots indefinitely. The wrapper object of binding data should be referenced from JavaScript, thus the binding data should be reachable throughout the lifetime of the realm. PR-URL: nodejs#47688 Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Joyee Cheung <[email protected]>
An AliasedBuffer can be nested in a BaseObject and their weak callbacks invoke order are not guaranteed. Prevent aliased buffer from being accessed in its weak callback as its validness can be checked with the emptiness of the persistent handle. PR-URL: nodejs#47688 Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Joyee Cheung <[email protected]>
The binding data must be weak so that it won't keep the realm reachable from strong GC roots indefinitely. The wrapper object of binding data should be referenced from JavaScript, thus the binding data should be reachable throughout the lifetime of the realm. PR-URL: nodejs#47688 Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Joyee Cheung <[email protected]>
These commits do not land cleanly on |
src: remove aliased buffer weak callback
An AliasedBuffer can be nested in a BaseObject and their weak callbacks
invoke order are not guaranteed. Prevent aliased buffer from being
accessed in its weak callback as its validness can be checked with the
emptiness of the persistent handle.
src: make realm binding data store weak
The binding data must be weak so that it won't keep the realm reachable
from strong GC roots indefinitely. The wrapper object of binding data
should be referenced from JavaScript, thus the binding data should be
reachable throughout the lifetime of the realm.
Fixes #47353