ffi: refCallback()/unrefCallback() crash (SIGSEGV) when called on a garbage-collected callback
ffi
### Version
main
### Platform
```text
N/A
```
### Subsystem
ffi
### What steps will reproduce the bug?
`repro.c`
```c
#include <stdint.h>
int32_t noop(int32_t x) { return x; }
```
Compile it by running
```sh
$ cc -shared -o repro.so repro.c # or .dylib on macOS
```
`repro.js`
```js
import { DynamicLibrary, suffix } from 'node:ffi';
const lib = new DynamicLibrary(`./repro.${suffix}`);
let cb = (x) => x + 1;
const ptr = lib.registerCallback({ arguments: ['i32'], return: 'i32' }, cb);
// Allow GC to collect the callback backing function
lib.unrefCallback(ptr);
cb = null;
globalThis.gc();
// Second unref (or refCallback) on the now-empty weak handle → SIGSEGV
lib.unrefCallback(ptr);
lib.close();
```
Run it using
```sh
$ node --experimental-ffi --expose-gc --no-warnings repro.js
```
### How often does it reproduce? Is there a required condition?
Always
### What is the expected behavior? Why is that the expected behavior?
`unrefCallback`/`refCallback` on a collected callback should throw `ERR_INVALID_ARG_VALUE("Callback not found")`.
### What do you see instead?
```console
segmentation fault (core dumped)
```
The process crashes with `SIGSEGV` inside `v8::PersistentBase::SetWeak()` (or `ClearWeak()` for refCallback) because the weak handle slot is already cleared after GC.
### Additional information
_No response_
关闭于 19 天前 1 条评论