src: add cleanup hooks to node::ObjectWrap#63642
Conversation
Add cleanup hooks to make sure that addons making use of this legacy API can do so safely in Worker threads or embedder-controlled Node.js instances. Refs: nodejs#63575 Fixes: nodejs#63540 Signed-off-by: Anna Henningsen <anna@addaleax.net>
This content is taken from nodejs#63575. The original commit message is preserved below: --- worker: fix premature addon unload Weak callbacks could run after addons were unloaded, leading to a crash. Signed-off-by: Mohamed Akram <mohd.akram@outlook.com>
|
Review requested:
|
| if (!isMainThread) { | ||
| const addon = require(`./build/${common.buildType}/binding`); | ||
|
|
||
| // Create some garbage |
There was a problem hiding this comment.
Is this necessary to test with the CleanupHook? I don't think it is necessary to trigger GC here, right?
There was a problem hiding this comment.
You're right, GC would prevent the test case from working, if anything – done in fcb0a4d
There was a problem hiding this comment.
@legendecas @addaleax It's not meant to trigger a GC immediately. The purpose of the loop is to make sure the WeakCallback runs, which it does after the addon is unloaded, and therefore causes a segfault absent a fix. Without that loop you won't be testing the visible effects of the clean up hook (i.e. that it removes the WeakCallback). The loop iterations were chosen such that this happens consistently.
There was a problem hiding this comment.
@mohd-akram If the weak callback runs here, won't that mean that the object is destroyed before the Environment and therefore the issue in #63540 will actually not occur? I can reproduce a fairly consistent crash with current Node.js versions (i.e. before this PR) when the loop is commented out and no consistent crash when it is active.
There was a problem hiding this comment.
If the weak callback runs here, won't that mean that the object is destroyed before the Environment and therefore the issue in #63540 will actually not occur?
On my system, it doesn't run there, it runs after.
I can reproduce a fairly consistent crash with current Node.js versions (i.e. before this PR) when the loop is commented out and no consistent crash when it is active.
Hmm, that's surprising. Definitely the opposite happening for me:
$ cat test.js
'use strict';
const common = require('../../common');
const { isMainThread, Worker } = require('worker_threads');
if (!isMainThread) {
const addon = require(`./build/${common.buildType}/binding`);
// Create some garbage
const arr = [];
for (let i = 0; i < 1e5; i++) arr.push(`${i}`.repeat(100));
new addon.MyObject(10);
// Should not segfault
throw new Error('exit');
} else {
const worker = new Worker(__filename);
worker.on('error', () => {});
}
$ node --version
v26.2.0
$ node test.js
zsh: segmentation fault node test.js
What OS are you on?
There was a problem hiding this comment.
It's arm64 macOS.
Testing out a few different combinations: Node.js 26.0.0 has this crash only without the extra array, Node.js 26.1.0 and 26.2.0 do not have it at all, and Node.js @ 40dc5a1 (base of this PR) has it only with the extra array.
I could probably dig deeper into the exact reasons, but regardless of what the outcome of that would be, I don't really see a good reason not to just include both versions as tests, so I've done that in 0cede86
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #63642 +/- ##
==========================================
+ Coverage 90.30% 90.32% +0.01%
==========================================
Files 730 732 +2
Lines 234802 236435 +1633
Branches 43957 44531 +574
==========================================
+ Hits 212041 213560 +1519
- Misses 14485 14596 +111
- Partials 8276 8279 +3 🚀 New features to boost your workflow:
|
In two commits to keep attribution to @mohd-akram's PR intact. If somebody feels strongly that they should be a single commit, I can turn them into one with a
Co-authored-bytag.src: add cleanup hooks to
node::ObjectWrapAdd cleanup hooks to make sure that addons making use
of this legacy API can do so safely in Worker threads
or embedder-controlled Node.js instances.
Refs: #63575
Fixes: #63540
test: add regression test for using
ObjectWrapin workerThis content is taken from #63575.
The original commit message is preserved below: