in reply to 5.10 shows uninitialized $@ warning

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; ... };

Replies are listed 'Best First'.
Re^2: 5.10 shows uninitialized $@ warning
by pmSwim (Acolyte) on May 16, 2008 at 16:00 UTC
    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}
        Thanks starbolin, to fix the cause of the problem is for me the the best solution. Your doubts are right. Between my "global" sig `die` handler and the one shown was a place where I make
        local $SIG{'__DIE__'};
        As I removed this, the real error message occurs from "global" handler and was fixed easily.

      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.