How can one see all warnings under mod_perl - perl

How can I make sure that I see all of Perl's warning and error messages when running a script under mod_perl? (Apache/2.2.16 (Debian) [...] mod_perl/2.0.4 Perl/v5.10.1)
I feel like I have done everything correctly: I have "PerlWarn On" in httpd.conf, I have
use strict;
use warnings FATAL => 'all';
in all my Perl files, and when I myself use warn(), I see the result in /var/log/apache2/error.log.
But many messages still don't get to me. For instance, "Can't locate object method" never appears in the log. The script simply dies and I have to figure out for myself where and why.
Anything I may have overlooked?

The statement
use warnings FATAL => 'all';
is a lexical warnings pragma. It only applies to the current block (in this case your script), and not modules or other files that your script calls.
Look into Carp::Always to get this kind of behavior across all of your code for debugging purposes.

Related

Can I `use strict` to observe runtime error? [duplicate]

When using use strict perl will generate a runtime error on unsafe constructs. Now I am wondering if it is possible to have it only print a warning instead of causing a runtime error ? Or is use warnings (or -w) warning about the same issues ?
No, use strict can't be made to issue warnings rather than die. All it does is set a few bits in the magic $^H variable, which triggers various things in the guts of the Perl interpreter.
No, use warnings isn't warning about the same things as use strict kills you for. For instance, use warnings will warn you about variables used only once (which might be the result of typos).
I'm gonna take a stab at guessing the real motivation here. Feel free to tell me if I guessed wrong.
I suspect your trying to tackle a large, older code base and would like to enable strictures but you were hoping first to get a sense of where the errors will be (and how many there are) without breaking functionality. Unfortunately, since use strict functions by modifying the internal behavior of the perl parser and interpreter, there isn't a 'loose strict' or, by analogy to html, any kind of 'transitional' mode.
However, you can tease apart the functionality of use strict to start moving in the right direction. First, note that there are actually three separate parts:
use strict 'refs'; # no symbolic references
use strict 'vars'; # must declare variables
use strict 'subs'; # no barewords
and of those only 'refs' generates runtime errors. So you could easily add use strict qw(vars subs) to each of your files (scripts and modules) and test them with perl -c. If you encounter any error messages, then comment out the use strict, or at least whichever of the two checks failed, and add a comment as to the nature of the failure and move on. This way you can quickly (depending on the number of files) determine which files have compile-time errors and come back to address them later. (If you were more motivated than me at the moment, you could even automate this process). Unless you have code that does scary things inside of BEGIN blocks, this should be pretty safe to do.
The trickier part is checking for the runtime errors generated by use strict 'refs' and unfortunately, there really isn't an easy way to do this because the errors are triggered by symbolic references which can't be determined by any kind of static analysis so -c and/or Perl::Critic are both useless.
Hopefully that gets closer to addressing your real problem.
The warnings and strict pragmas are complementary, not overlapping. The strict pragma has both compile-time and run-time effects. You can't reduce the severity of strictures from errors to warnings, but you can disable them entirely. For example, if you're writing your own export routine you'll need to enable symbolic references in order to manipulate the symbol table.
{
no strict 'refs';
# symrefs okay within this block
}
Warnings can also be disabled lexically (assuming you did use warnings instead of the largely obsolete -w flag).
Strictures and warnings provide a safety net. That's why they're recommended to be used by default. If you disable them you should disable only what's necessary and limit the change to the smallest possible scope.
The preferred method:
use Carp;
sub foo {
croak "no args" unless #_;
}
eval foo();
if( $# ){
print "caught die: $#";
}
If you can't change your die's to croak's:
sub foo {
die "no args" unless #_;
}
{
my $prev_die = $SIG{__DIE__};
$SIG{__DIE__} = sub { print "caught die: $_[0]"; };
eval foo();
$SIG{__DIE__} = $prev_die;
}
The second method will print out the errors on STDERR.
See:
perldoc -f eval
perldoc perlvar and search for /\$\#/ and /__DIE__/
perldoc Carp
Warnings can be made fatal — see perllexwarn — but strict errors can't be made non-fatal.
Why do you want to do that? I suspect an XY problem.

Debugging perl script

I don't know perl, but I need to debug a perl script which is needed by an application I am using, this is the error I get:
Unable to recognise encoding of this document at /usr/lib/perl5/vendor_perl/5.8.8/XML/SAX/PurePerl/EncodingDetect.pm line 9
The thing is, this script cannot figure out what is the encoding of a file. What I am trying to find out is, which file is that. I couldn't be able to find a way to stack trace. Here is the script trimmed a little:
package XML::SAX::PurePerl; # NB, not ::EncodingDetect!
use strict;
sub encoding_detect {
my ($parser, $reader) = #_;
my $error = "Invalid byte sequence at start of file";
my $data = $reader->data;
if ($data =~ /^\x00\x00\xFE\xFF/) {
# BO-UCS4-be
$reader->move_along(4);
$reader->set_encoding('UCS-4BE');
return;
} .. tons of if else statements
warn("Unable to recognise encoding of this document");
return;
I checked, but this reader object doesn't have a name, or path attribute. I have a control over this script, so I may modify it if necessary. Any help is appreciated.
Edit: I have tracked down the problem until this line in the application I'm trying to use:
my #array = SystemImager::HostRange::expand_groups($clients);
If you use the Carp module and the confess method, you get a stack backtrace:
use Carp;
confess "Something went horribly wrong" if ($something == $wrong);
This is of most use inside a function (in a module), but it helps. However, it sounds as if the error is being reported by code you're using, so you may not be able to get it to croak for you, but you should read the manual for Carp, which says in part:
Forcing a Stack Trace
As a debugging aid, you can force Carp to treat a croak as a confess and a carp as a cluck across all modules. In other words, force a detailed stack trace to be given. This can be very helpful when trying to understand why, or from where, a warning or error is being generated.
This feature is enabled by 'importing' the non-existent symbol 'verbose'. You would typically enable it by saying
perl -MCarp=verbose script.pl
or by including the string -MCarp=verbose in the PERL5OPT environment variable.
Alternat[iv]ely, you can set the global variable $Carp::Verbose to true.
As suggested by daxim in a comment, also consider Carp::Always:
use Carp::Always;
makes every warn() and die() complain loudly in the calling package and elsewhere. More often used on the command line:
perl -MCarp::Always script.pl
The pure Perl implementation of XML::SAX::PurePerl is marked as 'slow' by its maintainer. You should perhaps look at using one of the many other XS-based SAX modules, especially one that provides automatic encoding detection.
To debug perl script you may use:
perl -d:DebugHooks::Terminal script.pl
Look at this

Circumstances under which die() does not exit a Perl script?

I'm debugging a really weird problem with a long-running Perl script.
The problem is that the script does not exit on die() as expected. Instead the script just hangs without returning.
I've not defined any error handlers myself so I would assume that die() would lead to an immediate termination of the script.
This is the basic structure of the script and the modules used:
#!/usr/bin/perl
use strict;
use utf8;
use warnings;
use DBI; # with MySQL driver ("dbi:mysql:database=...")
use Geo::IP;
use POSIX;
use URI::Escape;
open(COMMAND, 'command_line |');
while (<COMMAND>) {
#
# .. stuff that can go wrong ..
#
die("I'm expecting the script to terminate here. It doesn't.") if ($gone_wrong);
}
close(COMMAND);
What could be the explanation to this behaviour? Is any of the modules used known to set up error handlers that could explain the script hanging on die()?
Well, END blocks and object destructors are still called after a die. If one of those hangs (or does something that takes a long time), the script won't exit immediately. But that should happen after printing the message from die (unless STDERR is buffered so you don't see the message immediately).
You mention DBI, so you probably have a database handle whose destructor is being called. (I'm not sure that's the problem, though.)

Can 'use strict' warn instead of error

When using use strict perl will generate a runtime error on unsafe constructs. Now I am wondering if it is possible to have it only print a warning instead of causing a runtime error ? Or is use warnings (or -w) warning about the same issues ?
No, use strict can't be made to issue warnings rather than die. All it does is set a few bits in the magic $^H variable, which triggers various things in the guts of the Perl interpreter.
No, use warnings isn't warning about the same things as use strict kills you for. For instance, use warnings will warn you about variables used only once (which might be the result of typos).
I'm gonna take a stab at guessing the real motivation here. Feel free to tell me if I guessed wrong.
I suspect your trying to tackle a large, older code base and would like to enable strictures but you were hoping first to get a sense of where the errors will be (and how many there are) without breaking functionality. Unfortunately, since use strict functions by modifying the internal behavior of the perl parser and interpreter, there isn't a 'loose strict' or, by analogy to html, any kind of 'transitional' mode.
However, you can tease apart the functionality of use strict to start moving in the right direction. First, note that there are actually three separate parts:
use strict 'refs'; # no symbolic references
use strict 'vars'; # must declare variables
use strict 'subs'; # no barewords
and of those only 'refs' generates runtime errors. So you could easily add use strict qw(vars subs) to each of your files (scripts and modules) and test them with perl -c. If you encounter any error messages, then comment out the use strict, or at least whichever of the two checks failed, and add a comment as to the nature of the failure and move on. This way you can quickly (depending on the number of files) determine which files have compile-time errors and come back to address them later. (If you were more motivated than me at the moment, you could even automate this process). Unless you have code that does scary things inside of BEGIN blocks, this should be pretty safe to do.
The trickier part is checking for the runtime errors generated by use strict 'refs' and unfortunately, there really isn't an easy way to do this because the errors are triggered by symbolic references which can't be determined by any kind of static analysis so -c and/or Perl::Critic are both useless.
Hopefully that gets closer to addressing your real problem.
The warnings and strict pragmas are complementary, not overlapping. The strict pragma has both compile-time and run-time effects. You can't reduce the severity of strictures from errors to warnings, but you can disable them entirely. For example, if you're writing your own export routine you'll need to enable symbolic references in order to manipulate the symbol table.
{
no strict 'refs';
# symrefs okay within this block
}
Warnings can also be disabled lexically (assuming you did use warnings instead of the largely obsolete -w flag).
Strictures and warnings provide a safety net. That's why they're recommended to be used by default. If you disable them you should disable only what's necessary and limit the change to the smallest possible scope.
The preferred method:
use Carp;
sub foo {
croak "no args" unless #_;
}
eval foo();
if( $# ){
print "caught die: $#";
}
If you can't change your die's to croak's:
sub foo {
die "no args" unless #_;
}
{
my $prev_die = $SIG{__DIE__};
$SIG{__DIE__} = sub { print "caught die: $_[0]"; };
eval foo();
$SIG{__DIE__} = $prev_die;
}
The second method will print out the errors on STDERR.
See:
perldoc -f eval
perldoc perlvar and search for /\$\#/ and /__DIE__/
perldoc Carp
Warnings can be made fatal — see perllexwarn — but strict errors can't be made non-fatal.
Why do you want to do that? I suspect an XY problem.

warnings::warn and FATAL categories in Perl

I must be understanding the warnings documentation wrong. The way I read it, this code:
use warnings;
use warnings FATAL => 'all';
warnings::warn('numeric', 'blarg');
print "finished\n";
Should print the 'blarg' warning and die since I've asked for all warnings to be fatal. However, when I run the code I get:
$> /opt/local/bin/perl x.pl
blarg at x.pl line 3
finished
Can somone help me understand why I can't get warn to die?
Okay. This is ugly. I had a post half-prepared explaining this as a bug in warnings, and then I realized it's not, it's just a really evil subtlety in the way warnings works.
Warnings starts looking for a relevant stack frame to get the warning bits from in warnings::warn's caller's caller. The idea is that you're writing some module and you use warnings::warn or warnings::warnif in your functions, and whether or not the warning is printed (or fatal) depends on the use warnings setting in scope in the code that uses your module. There's no option provided to have it start at caller(1) instead of caller(2), so the effect you want isn't possible.
An example of code that does work (and demonstrates how this interface was expected to be used by whoever wrote it):
package Foo;
require warnings;
sub bail {
warnings::warnif('numeric', "You fool! You divided by zero!");
}
package main;
use warnings FATAL => all;
Foo::bail();
print "Will never be reached\n";
And you can't defeat the way it works by just adding another level of subroutines, because it takes the flags from the first caller that's in a different package from the caller of warn/warnif/enable/etc.