Closed
Labels
ffiIssues and PRs related to experimental Foreign Function Interface support.Issues and PRs related to experimental Foreign Function Interface support.
Description
Version
main
Platform
macOS
Subsystem
ffi
What steps will reproduce the bug?
import { DynamicLibrary } from 'node:ffi';
import { setImmediate as tick } from 'node:timers/promises';
const cases = {
'Fast API, [f64, f64] (no JS wrapper)':
['copysign', { arguments: ['f64', 'f64'], return: 'f64' }],
'Fast API, [i32, i32] (JS wrapper)':
['kill', { arguments: ['i32', 'i32'], return: 'i32' }],
'Fast API, zero args':
['getpid', { arguments: [], return: 'i32' }],
'Shared buffer ([function, pointer])':
['atexit', { arguments: ['function', 'pointer'], return: 'i32' }],
};
for (const [label, [symbol, signature]] of Object.entries(cases)) {
let lib = new DynamicLibrary('/usr/lib/libSystem.B.dylib');
let fn = lib.getFunction(symbol, signature);
const fnRef = new WeakRef(fn);
const libRef = new WeakRef(lib);
fn = null;
lib = null;
for (let i = 0; i < 20; i++) {
await tick();
globalThis.gc();
}
console.log(label);
console.log(' function collected:', fnRef.deref() === undefined);
console.log(' library collected: ', libRef.deref() === undefined);
}Run with
node --no-warnings --expose-gc repro.mjs
How often does it reproduce? Is there a required condition?
Always
What is the expected behavior? Why is that the expected behavior?
Fast API, [f64, f64] (no JS wrapper)
function collected: true
library collected: true
Fast API, [i32, i32] (JS wrapper)
function collected: true
library collected: true
Fast API, zero args
function collected: true
library collected: true
Shared buffer ([function, pointer])
function collected: true
library collected: trueAfter all user references are dropped, the function and its DynamicLibrary should both be collectable. Collection should then dlclose the library and unmap the per-function executable trampoline page.
What do you see instead?
Fast API, [f64, f64] (no JS wrapper)
function collected: false
library collected: false
Fast API, [i32, i32] (JS wrapper)
function collected: true
library collected: false
Fast API, zero args
function collected: false
library collected: false
Shared buffer ([function, pointer])
function collected: true
library collected: trueIn the [i32, i32] case, only the JS wrapper is collected; the raw function stays alive.
Additional information
No response
Metadata
Metadata
Assignees
Labels
ffiIssues and PRs related to experimental Foreign Function Interface support.Issues and PRs related to experimental Foreign Function Interface support.
Activity
ffi: make Fast API functions collectable