in reply to Closures, object destruction and memory leaks

I would test this on your client's version of Perl.

What you describe should work, but I know that there was a bug in some versions of Perl (sorry, I couldn't seem to track it down, nor do I have them to test, but I am pretty sure that Perl 5.005_03 was one of them) where closures like that would never get garbage collected because of a Perl bug.

I would suggest trying the above with a $req with a DESTROY method that tells you when it goes away. See if it is a problem. If it is, then there isn't much you can do about it other than clean up $req yourself and hope that the memory leak doesn't grow too fast.

  • Comment on Re: Closures, object destruction and memory leaks

Replies are listed 'Best First'.
Re: Re: Closures, object destruction and memory leaks
by mpeppler (Vicar) on Nov 11, 2003 at 01:19 UTC
    Thanks all - the target platform is perl 5.6+, so I guess the bug tilly mentioned won't be an issue. I've got this working the way I want now (well - the way I want for an alpha relase :-)) and I've decided on the following:
    sub execute { my $self = shift; my $req = BigHairyDatabaseInteraction->new(...); { local $SIG{INT} = sub {$req->{_signal} = 2; $req->handleInterrupt; }; local $SIG{TERM} = sub {$req->{_signal} = 15; $req->handleInterrupt; }; $req->executeRequest(); } # If a TERM/INT signal has been delivered during the request # then pass it on to the program itself: if($req->{_signal}) { kill $req->{_signal}, $$; } ... rest of $sth->execute()
    The idea is that I want to override any signal handlers that the calling program may have installed so that I can interrupt the processing on the server as needed, but I also want to make sure that the caller does eventually receive the signal.

    So far this appears to work really well...

    Michael

      One tip that may make sense.

      Before you do the local, capture the existing handlers in lexical variables and pass them in to $req's handleInterrupt method.

      That way if a particular request type wants to, it can rethrow an exception properly up the chain, rather than just ignoring the poor programmer who is trying to put a signal handler around your code because they really don't want to exit on that signal.

      Doing this makes the signal handler system act a little bit more like a proper exception handling system. Not that much more like, mind you, but somewhat more like it.

        Hmm - that was why I have the
        if($req->{_signal}) { kill $req->{_signal}, $$; }
        bit. That re-delivers the signal to the program, rather than chaining the handlers, but won't that achieve the same end-result?

        In any case the $req->handleInterrupt() call really only sets a flag in the $req object, so chaining the signal handlers here would potentially prevent the request from being properly cancelled on the server, which I think could be a problem.

        Michael

Re: Re: Closures, object destruction and memory leaks
by demerphq (Chancellor) on Nov 10, 2003 at 16:15 UTC

    I _think_ the memory leak you mean only comes up with recursive closures:

    my $foo; $foo=sub { $foo->(@_[1..$#_]) if @_ }; $foo->();

    But like you I dont remember the details...


    ---
    demerphq

      First they ignore you, then they laugh at you, then they fight you, then you win.
      -- Gandhi


      Recursive closures leak memory. That is documented and the fix is to use WeakRef.

      What I am talking about is an actual bug, and I darned well know that it was there in 5.005_03 because I encountered it and had to fix a bunch of code that was leaking memory too fast.