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

Dear monks,
yesterday I installed the active state and the strawberry distribution of perl 5.10 on a windows XP box. In a program the SIG{__DIE__} handler is globally defined. But in some parts the normal die should be used. Thatswhy I use this construct
eval { local $SIG{'__DIE__'} = sub { die $@ }; # do something that may die };
This does the job, but now with perl 5.10 there is a warning
Use of uninitialized value $@ in ...
Please, can someone tell me the best way to avoid this. With older perl(s) I've never seen this message in this context of $@.

Replies are listed 'Best First'.
Re: 5.10 shows uninitialized $@ warning
by ikegami (Patriarch) on May 16, 2008 at 14:43 UTC

    Like Burak and like I already said, I can't replicate your behaviour.

    However, it is possible for $@ to get cleared. For example, if you have an object that gets destroyed in the eval and it uses eval in its destructor, $@ would get cleared. That's why you shouldn't rely on $@ being set to detect an exception.

    my $result; if (!eval { ... $result = ...; 1; }) { die("Unable to ...: $@\n"); }

    That said, I'd like to present a better solution to your initial problem. I propose there's a bug in your global __DIE__ handler. It should check $^S just rethrow the exception if it's true.

    local $SIG{'__DIE__'} = sub { die($@) if $^S; ... };
      Thank for your post, when I understand it correctly I would recommend the use of eval in a destructor as not so good practice. But the handler in general are not the problem. The code runs without a exception and no handler is called. What I dislike is the warning. I found a way to reproduce the warning (a local $@), but I have no idea where this happend in the program. Here is a longer code snippet which reproduces the warnings:
      use warnings;use strict; package What::Ever; $@=undef; $SIG{'__DIE__'} = sub { die "My global die: $@" } ; sub divide { local $SIG{'__DIE__'} = sub { die $@ }; eval { print STDERR 1/$_[0] , "\n"; } } ; { local $@; print STDERR "No exception:\n"; divide(1); print STDERR "Throw...\n"; divide(0); }; warn $@; # with this the warnings are shown // without none
      but this produces the warning in 5.8 too. So I do not really know what introduces the real problem.

        Except I doubt your code snippet is representative of your actual code and thus of little use in the discussion. Reading through the discussion I kept getting confused as to where the problem lay. This is why we need code that is representative of your code and which demonstrates the problem.

        First, can you verify that your current code runs without warning under 5.8 so that were sure some change didn't slip into the code? Next you're going to have to start paring things from your code until the warning goes away. I'm sorry we can't do this for you. You're going to have to be the one to do this. Once you find the offending bit of code then we can put more that one set of eyes on it and try to determine whether it is the code or whether something's not right in 5.10.

        pmSwim writes:

        "The code runs without a exception and no handler is called."
        Are you sure? The warning is a runtime message. This appears to be confirmed in your latest code snippet as you have to issue warn $@ to generate the message.

        I guess you could also sprinkle $@=''; throughout your code until the warning goes away.


        s//----->\t/;$~="JAPH";s//\r<$~~/;{s|~$~-|-~$~|||s |-$~~|$~~-|||s,<$~~,<~$~,,s,~$~>,$~~>,, $|=1,select$,,$,,$,,1e-1;print;redo}

        when I understand it correctly

        { package Foo; sub new { bless({}, $_[0]) } DESTROY { eval { die "Woof\n"; }; } } eval { my $foo = Foo->new(); die "Meow\n"; }; print($@); # Woof

        I would recommend the use of eval in a destructor as not so good practice.

        There's no alternative. The bad practice is relying on $@ telling you if an exception occurred or not.

        But the handler in general are not the problem

        If that's true, you wouldn't have to add local $SIG{'__DIE__'} = sub { die $@ }; in every eval. Seeing as you don't control all the evals in your program, a better solution to your initial problem (your handler misbehaving when you are in an eval) is to check $^S in the global handler

        but this produces the warning in 5.8 too. So I do not really know what introduces the real problem.

        As it should. The local $@; restores $@ to its previous value (undef) once the scope in which local $@; resides is exited (no matter how its exited).

        $@=undef; { local $@; ... } # $@ is undef here, no matter what "..." is.
Re: 5.10 shows uninitialized $@ warning
by Burak (Chaplain) on May 16, 2008 at 14:06 UTC
    I don't get any warnings with 5.10 on windows xp. You must give a full example that generates that warning...
Re: 5.10 shows uninitialized $@ warning
by syphilis (Archbishop) on May 16, 2008 at 13:49 UTC
    I can't reproduce the behaviour. I tried:
    use warnings; eval { local $SIG{'__DIE__'} = sub { die $@ }; print 1 / 0; };
    On 5.10 (AS and Strawberry) that script runs without output. On perl 5.8.8 it outputs Illegal division by zero at try.pl line 4. for me.

    Cheers,
    Rob
      Bad example. 1/0 produces a compile-time exception in 5.8. Once you fix that, both behave identically and contrary to the OP's results.
      use warnings; my $denum = 0; eval { local $SIG{'__DIE__'} = sub { die $@ }; print 1 / $denum; }; print "[$@]\n";
      >c:\progs\perl588\bin\perl script.pl [Died at script.pl line 4. ] >c:\progs\perl5100\bin\perl script.pl [Died at script.pl line 4. ]
      This is perl, v5.8.8 built for MSWin32-x86-multi-thread Binary build 817 [257965] provided by ActiveState http://www.ActiveSta +te.com This is perl, v5.10.0 built for MSWin32-x86-multi-thread Binary build 1001 [283495] provided by ActiveState http://www.ActiveSt +ate.com
        Bad example

        It was a perfectly fine example (in terms of the op's original conditions ;-)

        Cheers,
        Rob
      I checked your snippet with same results like you. So I'm now more unillumined as before my post. I played a little bit with your code and find that there must be a local $@ in the code hierarchy. I'm relative sure that is not explicit set inside of my code. Maybe in a module I use but I do not understand why it is localized. Can someone please give me a hint how to find the place where $@ is maybe localized. Thanks in advance.