Closed pipcet closed 9 years ago
Sorry, this is an issue in FFI::Platypus, not FFI::Platypus::Lang::CPP.
This is not a use case that I considered.
In the very least it deserves a CAVEAT
. One fix might be to cache the closure data based on the signature. Another that works Right Now to to cast the closure to an opaque like this:
use FFI::Platypus;
use FFI::TinyCC;
sub c {
}
my $tcc = FFI::TinyCC->new;
$tcc->compile_string(<<'EOF');
void c_with_arg(void (*f)(void))
{
f();
}
EOF
my $ffi = FFI::Platypus->new;
$ffi->type('()->void', 'FType');
my $c = $ffi->closure(\&c);
my $c_ptr = $ffi->cast('()->void' => 'opaque', $c);
my $a = $tcc->get_symbol('c_with_arg');
while(1) {
$ffi->function($a => ['opaque'] => 'int')->call($c_ptr);
}
That unfortunately pushes extra work on the developer to juggle both the clousre object and the closure pointer and closures are already hard enough to get right with FFI.
closing here, feel free to continue here:
Test case:
When run, memory usage keeps increasing until the process is killed when the ulimit is hit. The expected result is that memory usage does not increase indefinitely.
It's not quite a memory leak, since we can reclaim memory by destroying the closure.
It's easy enough to see what causes this: the %cbdata hash in ::Closure keeps growing, since we call add_data for each invocation but never remove payload data.
However, there's no obvious (to me) fix. We could presumably get away with reusing the same ::ClosureData between invocations, but that would break the (pathological?) case in which the same ::Closure is used for different types of function pointer. A more complete fix would attach types to ::Closures.