-->

Perl warning printed without 'use warnings'

2020-04-21 05:48发布

问题:

I have a lot of old Perl code that gets called frequently, I have been writing a new module and all of a sudden I'm getting a lot of warnings in my error_log for Apache, they are for every module currently being used. e.g,

"my" variable $variable masks earlier declaration in same statement at
    /path/to/module.pm line 40 (#1)

Useless use of hash element in void context at
    /path/to/another/module.pm line 212 (#2)

The main layout of the codebase is one giant script that includes the modules and directs the requests to them needed to create certain pages for the website and the main script then handles static elements like menus.

My current project is separated from this main script and doesn't use it however any time I call my code using ajax, there are some other ajax calls that will use the main script and the warnings only seem to appear from those request but only when I'm calling my project.

I have grepped every module and none of them have use warnings (or -w) in them, I have also tried using no warnings 'all' in the main script and my own project but it's not doing anything.

At this point I'm out of ideas on what to do next so all help is appreciated, I'd just like to suppress the warnings, the codebase is quite old and poorly written so going and correcting each issue that causes the warns in the first place isn't do-able.

The Apache server is running mod_perl as well, if that might make a difference I have a feeling it might be something to do with CGI, but I can't seem to find any evidence.

回答1:

I take it that the code gets called by running certain top-level Perl script(s).

Then use the __WARN__ hook in those script(s) to stop printing of warnings

BEGIN { $SIG{__WARN__} = sub {} };

Place this BEGIN block before the use statements so to affect modules as well.

An empty subroutine is the way to mute warnings since __WARN__ doesn't support 'IGNORE'.

See warn and %SIG in perlvar. See this post and this post for comments and some examples.


To investigate further and track the warnings you can use Carp

BEGIN {
    $SIG{__WARN__} = \&Carp::cluck;  # or Carp::confess; to also die
}

which will make it print full stack traces. This can be fine-tuned as you please since we can write our own sub to be called. Or use Carp::Always.

See this post for some more drastic measures (like overriding CORE::GLOBAL::warn)

Once you find a more precise level at which to suppress warnings then local $SIG{__WARN__} is the way to go, if possible. This is used in a post linked above, and here is another example. It is of course far better to suppress warnings only where needed instead of everywhere.

More detail

  • Getting stack traces in Perl?

  • How can I get a call stack listing in Perl?

Note that longmess is unfortunately no longer so standard and well supported.