Perl: STDOUT reopened as FH only for input

2019-07-26 15:09发布

I have the following error message (with Perl 5):

Tools.pm: Filehandle STDOUT reopened as FH only for input at /usr/local/lib/perl5/site_perl/mach/5.20/Template/Provider.pm line 967.

I understand its cause: It is that STDOUT was closed and later the same FD was used for something unrelated to STDOUT.

The code does the right thing. The only problem is that this error message should not to be logged.

How to stop printing this error message into our log file?

1条回答
ら.Afraid
2楼-- · 2019-07-26 15:37

Detailed handling of errors is outlined in Template::Manual::Config::ERROR.

It can be categorized in the constructor by specifying templates for exception types

my $template = Template->new({  
     ERRORS => {
         user     => 'user/index.html',
         dbi      => 'error/database',
         default  => 'error/default',
     },
});

which can be raised using the THROW directive

[% THROW user.login 'no user id: please login' %]

or by calling throw method

$context->throw('user.passwd', 'Incorrect Password');  
$context->throw('Incorrect Password');    # type 'undef'

or by Perl code by calling die, perhaps with a Template::Exception object.

How to use this to solve the problem is a matter of details, of which none are provided.

But you really want to find (user) code that triggers this and clean it up. For one, as noted by ikegami in a comment, don't close STDOUT but reopen it to /dev/null. (I'd say, never simply close standard streams.) For instance, if you just don't want to see STDOUT any more

open STDOUT, '>', '/dev/null';

or first save it before reopening so that you can restore it later

open my $SAVEOUT, '>&', 'STDOUT';
open STDOUT, '>', '/dev/null';
...
open STDOUT, '>', $SAVEOUT;  # restore STDOUT
close $SAVEOUT;              # if unneeded

(see open), or if feasible create a local *FOO and use that to save STDOUT.

The warning comes about since the lowest unused file descriptor is always used, and here fd 1 was vacated by closing STDOUT; but it is attempted to be used for input what isn't OK. As for why it's not OK and why emit a warning, this thread and an old bug report are useful. This goes beyond Perl.


One generic way is to use the __WARN__ hook

BEGIN {
    $SIG{__WARN__} = sub {
        warn @_ 
            unless $_[0] ~= /Filehandle STDOUT reopened as FH only for input/
    }
};

where the warning is emitted unless it matches the one you want to suppress. This BEGIN block need be before the use statements for modules it is expected to affect. If you know the scope at which this is needed it is better to localize it, local $SIG{__WARN__} = sub {...};

See this post and its links, to other posts and relevant documentation, for more details.

查看更多
登录 后发表回答