-
Notifications
You must be signed in to change notification settings - Fork 29.6k
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: implement v8 host weakref hooks #29874
Conversation
d6df190
to
f4e1d29
Compare
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
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 with some questions/suggestions.
PR-URL: nodejs#29874 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
@devsnek This PR changed a bit since I reviewed … shouldn’t |
@addaleax all the behaviour is at least within the specification. we can definitely tune it more as people start using weakrefs. |
@devsnek Yeah, but then again so is not running the finalization calllbacks at all, as I understand it 🙃 I’m happy to provide a PR myself, but that this doesn’t run callbacks scheduled from a regular GC (i.e. not |
@addaleax I'm not sure what change you're looking for exactly |
@devsnek As I’ve said, |
@addaleax these should run at the end of the microtask (and technically nextTick) queue, as they currently do. |
@devsnek @addaleax, the behavior seems to be spec compliant and within the spirit of it. From what I understand from the PR, if a cleanup callback throws, the rest of groups with pending finalization callbacks will simply be executed next tick. While that could cause delays, it's spec compliant and guarantees all callbacks are ultimately invoked. I guess the only thing is the environment should avoid shutting down until all pending callbacks have been executed, if possible. I don't think anything prevents that right now. Edit: I'll try to run my shim's test on the latest nightly. |
I got a crash running my shim's test in the latest nightly:
https://github.com/mhofman/tc39-weakrefs-shim/tree/node12-experimental-weakrefs I managed to extract a reproduction. It's not simple and I'm not sure if a smaller repro is possible (I tried): "use strict";
// Flags: --expose-gc --harmony-weak-refs
const common = require("../common");
const assert = require("assert");
const TRIGGER_CRASH = true;
function makeAsyncGc(gc, FinalizationGroup) {
const finalizationGroup = new FinalizationGroup(holdings => {
for (const holding of holdings) {
holding.collected = true;
}
});
return function asyncGc(target, trigger) {
let checker = {};
const checkerHolding = {
collected: false,
};
const holding = target != null ? { collected: false } : checkerHolding;
finalizationGroup.register(target || checker, holding, holding);
finalizationGroup.register(checker, checkerHolding, checkerHolding);
target = checker = undefined;
return Promise.resolve(trigger)
.then(() => {
return gc();
})
.then(() => {
try {
finalizationGroup.cleanupSome();
finalizationGroup.unregister(checkerHolding);
finalizationGroup.unregister(holding);
} catch (err) {}
if (!checkerHolding.collected) {
return Promise.reject(
new Error("Couldn't collect checker")
);
}
return holding.collected;
});
};
}
const asyncGc = makeAsyncGc(globalThis.gc, globalThis.FinalizationGroup);
let resolve;
const called = new Promise(r => {
resolve = r;
});
let marker = {};
const fg = new globalThis.FinalizationGroup(
common.mustCallAtLeast(i => {
resolve();
}, 1)
);
const collected = (function() {
let obj = {};
fg.register(obj, 42);
const collected = asyncGc(obj);
obj = undefined;
return collected;
})();
collected
.then(() => {
globalThis.gc();
})
.then(() => called)
.then(() => {
if (!TRIGGER_CRASH) return;
const collected = asyncGc(marker);
marker = undefined;
return collected;
})
.then(common.mustCall()); The crash seem to be a combination of resolving a promise in the callback and triggering a new gc() in the resolution chain of that promise. |
@mhofman would you mind running lldb and seeing where the backtrace is from? |
I don't have much of a native dev environment setup. I basically got the nightly running by building a the alpine-node docker image pulling in the nightly source instead of dist. Looks like lldb isn't available on alpine 3.9. I'll see what I can do, but it might be faster to run the test I provided. I made sure it could run as part of node's test suite. |
@devsnek, here is what I got running the test file above on the latest node 13.0.1:
Anything else I can provide ? |
no that is enough, it seems that Environment::RunWeakRefCleanup is missing a HandleScope. I was considering rewriting this based on some feedback from anna anyway, so maybe it won't be a problem. |
If v8 7.8 does ends up backported to 12 LTS (#30109), it'd be great if this PR and fix could also be included. |
FYI, the pending integration changes for the chromium side can be found here: https://chromium-review.googlesource.com/c/chromium/src/+/1873754 |
Also is there any chance #30130 might fix this issue too? |
no that's unrelated |
Should only land on v12.x if #30109 does. |
PR-URL: #29874 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
PR-URL: #29874 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
* chore: bump node in DEPS to v12.16.0 * Fixup asar support setup patch nodejs/node#30862 * Fixup InternalCallbackScope patch nodejs/node#30236 * Fixup GN buildfiles patch nodejs/node#30755 * Fixup low-level hooks patch nodejs/node#30466 * Fixup globals require patch nodejs/node#31643 * Fixup process stream patch nodejs/node#30862 * Fixup js2c modification patch nodejs/node#30755 * Fixup internal fs override patch nodejs/node#30610 * Fixup context-aware warn patch nodejs/node#30336 * Fixup Node.js with ltcg config nodejs/node#29388 * Fixup oaepLabel patch nodejs/node#30917 * Remove redundant ESM test patch nodejs/node#30997 * Remove redundant cli flag patch nodejs/node#30466 * Update filenames.json * Remove macro generation in GN build files nodejs/node#30755 * Fix some compilation errors upstream * Add uvwasi to deps nodejs/node#30258 * Fix BoringSSL incompatibilities * Fixup linked module patch nodejs/node#30274 * Add missing sources to GN uv build libuv/libuv#2347 * Patch some uvwasi incompatibilities * chore: bump Node.js to v12.6.1 * Remove mark_arraybuffer_as_untransferable.patch nodejs/node#30549 * Fix uvwasi build failure on win * Fixup --perf-prof cli option error * Fixup early cjs module loading * fix: initialize diagnostics properly nodejs/node#30025 * Disable new esm syntax specs nodejs/node#30219 * Fixup v8 weakref hook spec nodejs/node#29874 * Fix async context timer issue * Disable monkey-patch-main spec It relies on nodejs/node#29777, and we don't override prepareStackTrace. * Disable new tls specs nodejs/node#23188 We don't support much of TLS owing to schisms between BoringSSL and OpenSSL. Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
Checklist
make -j4 test
(UNIX), orvcbuild test
(Windows) passes