perlquestion
jbert
<p>Hi.</p>
<p>I've recently had a bunch of "fun" chasing down leaks in code (mine and others) caused by accidental capture of variables in callbacks.</p>
<p>e.g. something like:</p>
<code>
sub foo {
my $self = shift;
$self->do_something(on_success => sub {
do_stuff();
$self->log("done stuff");
do_more_stuff();
$self->log("done more stuff");
});
</code>
<p>Assuming that do_something hides the callback within $self, we've just created a cycle which if it doesn't get cleared (e.g. on an error path) will cause a leak (could leak mem, could leak other resources such as network connections. badness.)</p>
<p>Note that the logging could have been added casually, and doesn't look evil on a review diff.</p>
<p>One idea being bounced around here would be a pragma which declared "I don't want any vars to be captured implicitly" and a way of marking which vars are ok to capture.</p>
<p>The thinking is that this would make it clear and explicit what vars are being captured, so it is easy to see them and reason about them. Something like:</p>
<code>
use NoClose;
sub foo {
# Still a cycle, but now a more obvious one!
$self->do_something(on_success => sub : capture('$self') {
do_stuff();
$self->log("done stuff");
do_more_stuff();
$self->log("done more stuff");
});
</code>
<p>With the idea being that any vars which a closure would capture would be compile-time errors unless they are referenced in the 'capture' attribute.</p>
<p>So...is this madness? And has it already been implemented? Or do people resolve this pain in a different way?</p>
<p>(I know about weak refs, the issue is more about making it easy to know what to weaken.)</p>
<p>[Edit, added comment to code to emphasise that this doesn't prevent cycles, just makes them more visible.</p>