in reply to Re: How to detect a die() without catching it?
in thread How to detect a die() without catching it?

I do? You mean I should use $SIG{__DIE__} right? Won't that cause problems with evals in the code being called? And how does it avoid the need to re-die() to continue the error?

UPDATE: More to the point, these profiler subs will be called recursively. There will be a stack of profiler subs equivalent to the normal Perl call stack. How can I use $SIG{__DIE__} in a case where multiple subs need to be ready to catch die()s?

Of course, I may just be clinging irrationally to the idea that this is a hard problem just to save myself from realizing I'm a manual-ignoring moron...

-sam

  • Comment on Re: Re: How to detect a die() without catching it?

Replies are listed 'Best First'.
Re3: How to detect a die() without catching it?
by belg4mit (Prior) on May 17, 2002 at 23:03 UTC
    A little experimentation and reading will get you a long ways. You don't die in a DIE handler, recursion is bad. You exit, or you don't, it's your call. But those are your two options, eval or $SIG{DIE}.

    >Won't that cause problems with evals in the code being called?
    Could you rephrase the question? It's not exactly clear what you mean there.

    --
    perl -pew "s/\b;([mnst])/'$1/g"

      Mid-air collision of update and reply! Eee gads. Ok, I see what you mean about not needing to die() from &$SIG{__DIE__}. (Although, BTW, this recursion isn't "bad" - it's actually recommended in the die() docs as the way to change the error message!)

      But I think my concern about the call stack still stands. How can a single global handler be enough?

      UPDATE: To clarify, here's an example of how $SIG{__DIE__} doesn't behave the way I think I would need it to:

      sub catcher { local $SIG{__DIE__} = sub { print "Caught 1!\n"; }; catcher2(); } sub catcher2 { local $SIG{__DIE__} = sub { print "Caught 2!\n"; }; sub_that_dies(); } sub sub_that_dies { die "Foo"; } catcher();

      Now, I'd like that code to print both "Caught 1!" and "Caught 2!". But what it actually does is less useful:

      $ perl bomb.pl Caught 2! Foo at bomb.pl line 30.

      Does that make it clear what I mean?

      -sam

        Well I was a bit hasty in calling it recursion, as it isn't really.

        So actually you want the opposite (in a manner of speaking) of what you said, you wish to artificially enforce inheritance of die as *exceptions*. The code you give does exactly what it is supposed to, there is no die called within catcher, and $SIG{__DIE__} is re-localed to the catcher2 scope.

        I think Exception::Class is what you want for that. Alternatively, here's some ugly code

        local @stack; $SIG{__DIE__} = sub { die(@stack, @_); }; catcher(); sub catcher { local @stack = (@stack, "Caught 1!\n"); catcher2(); } sub catcher2 { local @stack = (@stack, "Caught 2!\n"); sub_that_dies(); } sub sub_that_dies { die "Foo"; }

        If, on the other hand, you actually want what's in yor original code, which is just to do something before (outter) dieing then I stand by the original suggestions, and also add END to the list; END output comes last though.

        #=begin a require 'b'; print "Hello World\n"; #This die can also be replaced with print && exit $SIG{__DIE__} = sub { print "BOB!\n"; die(@_); }; a::a(); END{ print "Waka waka\n"; #=end a #=begin b package a; sub a{ die("A!"); } 1; #=end b __END__ Hello World BOB! A! at /tmp/b line 3. Waka waka

        --
        perl -pew "s/\b;([mnst])/'$1/g"