http://www.perlmonks.org?node_id=495424

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

If, inside a DESTORY, I *really* want to CORE::die, how can I do it?

I know DESTROY wraps in an eval; is there a way to override.

water

Replies are listed 'Best First'.
Re: die in a DESTROY
by sauoq (Abbot) on Sep 27, 2005 at 17:01 UTC

    You can always die by hand: print an error message to STDERR and exit with a non-zero status.

    -sauoq
    "My two cents aren't worth a dime.";
    
       die is the same as  print STDERR "message"; exit(1) ???

      Really?

      Never knew that! Is in docs somewhere?

      How does  print STDERR "message"; exit(1) work with eval then?

      water

        die is the same as print STDERR "message"; exit(1) ???

        Well, it's not exactly the same. Specifically, the status you exit with shouldn't necessarily be 1 if you want a perfect emulation. But, the right status to exit with is easy enough to determine. See below.

        Never knew that! Is in docs somewhere?

        The first paragraph of the perlfunc entry for die states:

        die LIST Outside an "eval", prints the value of LIST to "STDERR" and exits with the current value of $! (errno). If $! is 0, exits with the value of "($? >> 8)" (backtick `command` status). If "($? >> 8)" is 0, exits with 255.

        How does print STDERR "message"; exit(1) work with eval then?

        Exactly like you would expect. Since exit doesn't care whether you are in an eval or not, it will work fine. It's only because die has special behavior inside an eval that you are running into problems.

        -sauoq
        "My two cents aren't worth a dime.";
        
Re: die in a DESTROY
by water (Deacon) on Sep 28, 2005 at 00:24 UTC
    Ok. I don't think  exit is right for me; I am writing a module and would like the code which uses it to have the option to trap it with eval.

    The gist of the module is a series of pushes onto a stack, which then get sent to a DB upon request. The send-to-DB is an explicit call. I've got a DESTROY that checks the stack is empty (either never was pushed, or was pushed but then properly sent off to DB) when the object goes out of scope.

    I want the DESTROY do something like this

    # untested sub DESTROY { my ($self) = @_; die "destroy called with non-empty stack" if $self->stack_count; }
    Now, the caller could trap this die if they knew what they were doing, or if they didn't, they'd get a fatal die if they used the module improperly (eg not calling send-to-DB).

    So that's what I want to do:

    die from a DESTROY in such a way isn't caught by the DESTROY itself, but could be caught (eg eval) by a module user.

    Do I have any shot at getting this behavior?

    water }

      Now that you've explained what you want, it seems this is a difficult problem. I played with it a bit, trying some obvious things with caller and such to no avail. I'm guessing you'd have to resort to using B to cobble together a workaround.

      -sauoq
      "My two cents aren't worth a dime.";
      
Re: die in a DESTROY
by adrianh (Chancellor) on Sep 28, 2005 at 13:47 UTC
    If, inside a DESTORY, I *really* want to CORE::die, how can I do it?

    Short answer - you can't. Exceptions don't propagate out of DESTROY blocks.

    If you want to detect some kind of error condition that happened during DESTROY time your best bet would be to set a global error flag and then test that.

    Personally I'm would be suspicious of DESTROY blocks that would need to throw exceptions.... can you describe what you want to do in more detail? There might be a better way :-)