[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index][Thread Index][Top&Search][Original]
Re: $^S and eval
>I have a long-standing problem in detecting when code is being eval'ed and
>when not.
>
>In gimp-perl, I try to catch die's to be able to display them in a message
>box, not on standard error. To do this, I add a __DIE__-Handler:
>
> $SIG{__DIE__} = sub {
> unless ($^S || !defined $^S || $in_quit) {
> die_msg $_[0];
> initialized() ? &quiet_die : exit quiet_main();
> } else {
> die $_[0];
> }
> };
>
>The logic is: if "!$^S && defined $^S", then we are in an eval, and just
>re-throw the error, otherwise display it.
It appears that, since you really are trying to catch program exits,
that you should in theory be using an END{} handler instead of
copying with the congenitally botched old $^S/__DIE__ implementation
bug. But that doesn't mean it's not time to fix the latter.
In perlvar.pod, I for some time now have had the following text
included:
Due to an implementation glitch, the C<$SIG{__DIE__}> hook is called
even inside an eval(). Do not use this to rewrite a pending exception
in C<$@>, or as a bizarre substitute for overriding CORE::GLOBAL::die().
This strange action at a distance may be fixed in a future release
so that C<$SIG{__DIE__}> is only called if your program is about
to exit, as was the original intent. Any other use is deprecated.
In perlfunc.pod, I for some time now have had the following
text included:
Due to the current arguably broken state of C<__DIE__> hooks,
when using the C<eval{}> form as an exception trap in libraries,
you may wish not to trigger any C<__DIE__> hooks that user code
may have installed. You can use the C<local $SIG{__DIE__}>
construct for this purpose, as shown in this example:
# a very private exception trap for divide-by-zero
eval { local $SIG{'__DIE__'}; $answer = $a / $b; };
warn $@ if $@;
This is especially significant, given that C<__DIE__> hooks can
call C<die> again, which has the effect of changing their error
messages:
# __DIE__ hooks may modify error messages
{
local $SIG{'__DIE__'} =
sub { (my $x = $_[0]) =~ s/foo/bar/g; die $x };
eval { die "foo lives here" };
print $@ if $@; # prints "bar lives here"
}
The last word from Larry on this gross infelicity was:
The original intent of __DIE__ was only to allow you to substitute
one kind of death for another on an application-wide basis
without respect to whether you were in an eval or not. As a
global backstop, it should not be used any more lightly (or any
more heavily :-) than class UNIVERSAL. Any attempt to build a
general exception model on it should be politely squashed. Any
bug that causes every eval {} to have to be modified should be
not so politely squashed.
It's long past time impolitely squash the implementation bug that
causes every eval {} to have to be modified.
--tom
- Follow-Ups from:
-
Ilya Zakharevich <ilya@math.ohio-state.edu>
Marc Lehmann <marc@gimp.org>
Marc Lehmann <marc@gimp.org>
Pete Jordan <pjordan1@email.mot.com>
[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index][Thread Index][Top&Search][Original]