erabus has asked for the wisdom of the Perl Monks concerning the following question:

Actually, what I really want to know is why the object is being destroyed.

Within the DESTROY method I would like to differentiate between:
A reference to an object going out-of-scope and
The PERL interpreter stopping because the die function was invoked.

Thanks.
  • Comment on Is there a way to know why the DESTROY method was invoked?

Replies are listed 'Best First'.
Re: Is there a way to know why the DESTROY method was invoked?
by BrowserUk (Patriarch) on Feb 18, 2010 at 17:42 UTC

    Yes.

    #! perl -slw use strict; use Carp qw[ cluck ]; my $x = 0; $SIG{ __DIE__ } = sub{ $x = 1 }; sub DESTROY{ cluck 'DESTROY called' . ($x ? ' after die':'') } { my $r=bless[]; } my $r = bless[]; die 'dying'; __END__ c:\test>junk79 DESTROY called at C:\test\junk79.pl line 9 main::DESTROY('main=ARRAY(0xacf98)') called at C:\test\junk79. +pl line 15 eval {...} called at C:\test\junk79.pl line 15 dying at C:\test\junk79.pl line 17. DESTROY called after die at C:\test\junk79.pl line 9 main::DESTROY('main=ARRAY(0x2e67e8)') called at C:\test\junk79 +.pl line 17 eval {...} called at C:\test\junk79.pl line 17

    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      Thank you.
Re: Is there a way to know why the DESTROY method was invoked?
by kennethk (Abbot) on Feb 18, 2010 at 17:43 UTC
    When the perl interpreter stops because die was invoked, your reference goes out of scope. So no matter what, the object is being destroyed because it went out of scope - see Destructors. The question you want to ask is "How can I detect in a DESTROY method whether die was called?"

    A better question I should be asking is "Why do you need to know?" Is this just for near-term debugging purposes or do you intend to use this in production code? All of the ways I can think of implementing this involve introducing either unnecessarily complicated code or significant potential for spooky action-at-a-distance bugs. Both of these result in maintenance and code-reuse headaches.

    Caveats aside, one fairly straightforward way to do this would be to set either a module variable or global variable in a signal handler so you can test in DESTROY if die was called. See die and %SIG for information on setting $SIG{__DIE__}.

      Thank you for your reply
      Yesterday I realized that I had not called the close method for an open file. I would like to trap this situation when the file handle goes out-of-scope so that I can make sure that the close is in place.
      A side affect of implementing the DESTROY method is that the method complains when the interpreter is stopped because the die function was invoked.
      I would like to know why the reference is going out-of-scope in the DESTROY method so that I can elect to report the message or just let it go.

        close isn't complaining because an exception has been thrown. Why is close actually complaining? (i.e. What error are you getting?) That's the problem you actually need to fix.

        By the way, if you don't check if close returned an error, you don't need to call it. The file or file object will close itself if necessary.

      I'm also curious to know why. This has the smell of an XY problem.
Re: Is there a way to know why the DESTROY method was invoked?
by Anonymous Monk on Feb 18, 2010 at 17:32 UTC
    Use a signal handler