Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

Tying events to perl warnings and errors

by jcwren (Prior)
on Sep 13, 2000 at 22:53 UTC ( [id://32319]=perlquestion: print w/replies, xml ) Need Help??

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

Is there any way to trigger a piece of code on a warning generated by -w?

I have a piece of code that gets run intermittently, and every so often, it gets a warning about an uninitialized variable. Now, I could put some code that tests the variable that I *suspect* is bad before usage (this is a multiple hash dereference), but I don't know that I'd catch it, and I'd have to wait for the program to run again.

What I'd rather do is setup a code trap that would record the states of those variable in the subroutine, and a few others, using Data::Dumper or somesuch, to a file.

Consider the following fragment of code. We know that 3 parameters are being passed, since the @_ == 3 test passes, but without wrapping a test around each parameter, the perl diagnostics don't tell us *which* variable is the cause for the error messages.
#!/usr/local/bin/perl -w use strict; { test ('arf', undef, 'dog'); } sub test { @_ == 3 or die "Incorrect number of arguments"; my ($a, $b, $c) = @_; my %hash = ('arf' => {'spot' => {'dog' => 3}}); print $hash {$a}->{$b}->{$c}; }
Anyone got any good ideas on this? Besides using tie() to every variable I might possibly reference... And why the perl interpeter couldn't print *what* variable is uninitialized?

--Chris

e-mail jcwren

Replies are listed 'Best First'.
Re: Tying events to perl warnings and errors
by Shendal (Hermit) on Sep 13, 2000 at 23:00 UTC
    You can trap any warn (or die) yourself like this:

    use strict; $SIG{__WARN__} = \&mywarn; sub mywarn { print "here!\n @_\n"; } { test ('arf', undef, 'dog'); } sub test { @_ == 3 or die "Incorrect number of arguments"; my ($a, $b, $c) = @_; my %hash = ('arf' => {'spot' => {'dog' => 3}}); print $hash {$a}->{$b}->{$c}; }
    ...which prints this output:
    here! Use of uninitialized value in hash element at test.txt line 23. here! Use of uninitialized value in hash element at test.txt line 23. here! Use of uninitialized value in print at test.txt line 23.

    Hope that helps,
    Shendal
      Playing with $SIG{__WARN__} and $SIG{__DIE__} is fun, but remember that you can't out-wit death. If die gets called, the script will end, but first it will evaluate/run the expression/subroutine that is $SIG{__DIE__}. It will pass die's arguments in as @_ and will disable the signal (avoiding recursive calls to $SIG{__DIE__}). Good stuff really. Great if you want to say... print a time stamp whenever your script dies... or log warnings to an extra log file. (you trigger __WARN__ when you call warn too.)
      The only problem with the $SIG{__WARN__} method is that I don't get the data I want. I'm not a perlguts guy, so maybe someone can point the way for what I mentioned I wanted in the article, which is access to the variable list for the subroutine.

      What I want to do is upon receipt of the error, dump the variable state for the subroutine out to disk. Timestamping is all well and fine, but it doesn't get me the information that I'm really needing. Any ideas?

      --Chris

      e-mail jcwren

        Localize the handler with a closure, like this:

        sub foo { my ($a, $b, $c) = @_; my %hash = (a => {b => {c => 0}}); # whatever other variables you want to initialize local $SIG{__WARN__} = sub { # dump those variables here }; print $hash{$a}->{$b}->{$c}; # ... }

        The variables you want to dump will be in scope of the __WARN__ handler and you can do whatever you like with them.

        local $_ = "0A72656B636148206C72655020726568746F6E41207473754A"; while(s/..$//) { print chr(hex($&)) }

      this method should work out.

      i'd also suggest logging to syslog with Sys::Syslog rather than writing out logfiles. that way, any permissions issues are avoided, and no one can remove/replace the log files.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://32319]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others meditating upon the Monastery: (4)
As of 2024-04-25 05:43 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found