[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]