Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

What magic is this?

by Jonathan (Curate)
on Oct 26, 2006 at 12:04 UTC ( #580738=perlquestion: print w/ replies, xml ) Need Help??
Jonathan has asked for the wisdom of the Perl Monks concerning the following question:

I have two scripts that use XML::Simple to parse a small file. The XML::Simple code is identical for both, ie
# Create XML reader object my $xs = new XML::Simple(); # Parse XML string my $ref = $xs->XMLin($file_str);
With an identical XML string the first script runs without complaint. The second also runs but I have a message in my log file
Thu Oct 26 12:47:37 2006 [PID 23309] [critical] Can't use string ("<sa +:model xmlns:sa="urn:basel-rb") as a symbol ref while "strict refs" i +n use at /usr/local/lib/perl5/site_perl/5.6.0/sun4-solaris/XML/Parser +/Expat.pm line 451.
The only difference between the two routines is that in the one that reports the problem I've added my own error reporting overrides
$SIG{__WARN__} = \&log_warn; $SIG{__DIE__} = \&log_die;
Can anyone offer me some enlightenment on whats going on?

Comment on What magic is this?
Select or Download Code
Re: What magic is this?
by RMGir (Prior) on Oct 26, 2006 at 12:09 UTC
    No. But it's very interesting!

    What happens if you put

    use Carp; # or Coy, if you want humour
    in your first script (the one without the $SIG{__WARN__} and $SIG{__DIE__} settings)?

    I'm curious to see if those modules (which must set those signals themselves) also trigger the misbehaviour.

    Also, if you look at line 451 of Expat.pm, does it really try to use a symbolic ref?


    Mike
      You have an interesting take on the word 'interesting' :-)

      Expat.pm has use Carp in it, when I added it to my first script it made no difference. It still ran without complaining.

      Line 451...

      if (defined $arg) { if (ref($arg) and UNIVERSAL::isa($arg, 'IO::Handler')) { $ioref = $arg; } else { eval { --> $ioref = *{$arg}{IO}; }; undef $@; } }
      I've tried eval'ing the call in my code but the error message still gets through. As its stands I'm going to have to amend my log_die sub-routine to ignore messages with Expat in them (which is horrible).
        That code block in my Expat.pm (version 2.34) looks like
        if (defined $arg) { if (ref($arg) and UNIVERSAL::isa($arg, 'IO::Handle')) { $ioref = $arg; } elsif (tied($arg)) { my $class = ref($arg); no strict 'refs'; $ioref = $arg if defined &{"${class}::TIEHANDLE"}; } else { require IO::Handle; eval { no strict 'refs'; $ioref = *{$arg}{IO} if defined *{$arg}; }; undef $@; } }

        but to me it looks equally scary. undef $@ after eval? wtf?

        At least, there's no strict 'refs'; inside the eval (but isn't it another wtf?)

        --shmem

        _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                      /\_¯/(q    /
        ----------------------------  \__(m.====·.(_("always off the crowd"))."·
        ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
Re: What magic is this?
by ForgotPasswordAgain (Deacon) on Oct 26, 2006 at 12:37 UTC
    Did you try putting the error handlers in the other script to see if it does the same thing? (BTW, I'm assuming both scripts are running on the same server using the same Perl.)
      I know its my error handling code and when I add a cut down version it is enough to generate the same error;
      $SIG{__DIE__} = \&log_die; sub log_die { print @_; }
      This is the full version, strange it has a die in it but the process doesn't!
      sub log_die { return unless CRITICAL >= $PRIORITY; _log(_msg('critical',@_)); die @_; }
Re: What magic is this?
by gellyfish (Monsignor) on Oct 26, 2006 at 12:56 UTC

    Yes, when you use $SIG{__DIE__} it will get called if the program would die irrespective of whether there is an eval { } around the point that is dying, as you can see from:

    $SIG{__DIE__} = sub { print "die handler: " , @_ }; + eval { die "DIE NOW"; }; + print "Still alive";
    The program doesn't "die" but the "__DIE__" handler gets called nonetheless. This is the documented behaviour. You'll need to rethink the way you are handling errors.

    /J\

      It isn't perfect, but that is what $^S is for. __DIE__ handlers usually should do nothing if $^S is true.

      - tye        

Re: What magic is this?
by Jonathan (Curate) on Oct 26, 2006 at 14:11 UTC
    gellyfish I don't think the problem is my error handler (which merely logs problems for background processes). All its doing is uncovering a error message that is usually hidden away

    tye I thought $^S was readonly? Anyway, if I could set it I don't think it would have any effect on my Expat.pm

      Yes, it is usually caught by the eval { } block which the author of XML::Parser deliberately put there, because the error was expected under certain circumstances and should be ignored. It is part of the design of the module.

      You don't need to set the $^S you just want to check whether it is set in your die handler:

      $SIG{__DIE__} = sub { if (! $^S ) { # Report the error } else { # Ignore the error as it came # came from inside an eval } };

      /J\

        Ahh yes of course, that's it.

        Thanks a lot for your help

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://580738]
Approved by Corion
Front-paged by grinder
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others exploiting the Monastery: (13)
As of 2014-10-31 20:13 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    For retirement, I am banking on:










    Results (223 votes), past polls