-
Notifications
You must be signed in to change notification settings - Fork 152
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Run FinalizationRegistry callback in the job queue #500
Conversation
96f3f72
to
59d1dda
Compare
@bnoordhuis THis one should be ready now. I had to dig deep, so pl let me know what you think! |
The spec says HostMakeJobCallback has to be used on the callback: https://tc39.es/ecma262/multipage/managing-memory.html#sec-finalization-registry-cleanup-callback That makes the following (arguably contrived) example run forever until memory is exhausted. ```js let count = 0; function main() { console.log(`main! ${++count}`); const registry = new FinalizationRegistry(() => { globalThis.foo = main(); }); registry.register([]); registry.register([]); return registry; } main(); console.log(count); ``` That is unlike V8, which runs 0 times. This can be explained by the difference in GC implementations and since FinRec makes GC observable, here we are! Fixes: #432
59d1dda
to
5cb2c21
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.
👍
if (!rt->in_free && (!JS_IsObject(fre->held_val) || JS_IsLiveObject(rt, fre->held_val))) { | ||
JSValue args[2]; | ||
args[0] = frd->cb; | ||
args[1] = fre->held_val; | ||
JS_EnqueueJob(frd->ctx, js_finrec_job, 2, args); | ||
} | ||
JS_FreeValueRT(rt, fre->token); | ||
js_free_rt(rt, fre); |
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 appears to cause #648 and now that I'm looking at it more closely, I believe a spot a bug:
If the branch is not taken (i.e. no job is enqueued), shouldn't it JS_FreeValueRT(rt, fre->held_val)
? fre
is freed here.
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.
Possibly yeah. The object might not be live so I think we need to check for that.
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.
Figured it out just now: it should call JS_FreeValueRT(rt, fre->held_val)
because JS_EnqueueJob increments the ref count, and js_finrec_job should not call JS_FreeValue(ctx, argv[1])
. Pull request incoming.
The spec says HostMakeJobCallback has to be used on the callback: https://tc39.es/ecma262/multipage/managing-memory.html#sec-finalization-registry-cleanup-callback
That makes the following (arguably contrived) example run forever until memory is exhausted.
That is unlike V8, which runs 0 times. This can be explained by the difference in GC implementations and since FinRec makes GC observable, here we are!
Fixes: #432