On Wed, May 01, 2013 at 04:22:42PM +0200, Manfred Lotz wrote:
> Hi there,

Hello,

> I have a script where I log stuff to a file and the same time displays
> it to stdout using Log4perl.
> 
> Here is a minimal example where I log a command which fails.
> 
> <--------------------snip------------------------->
> #! /usr/bin/perl
> 
> use strict;
> use warnings;
> 
> #use autodie;
> use Log::Log4perl qw(:easy);
> 
> Log::Log4perl->easy_init(
>       { level => $DEBUG, file => "> test.log", },
>       { level => $DEBUG, file => 'STDOUT', }
> );
> 
> my $cmd = 'uname';
> my $parms = '-f'; # invalid parm
> 
> INFO( "Issuing [$cmd $parms]" );
> open my $fh, '-|', "$cmd $parms 2>&1" or die "open: $!";
> INFO( "$_" ) while <$fh>;
> close $fh;
> 
> <--------------------snap------------------------->
> 
> This works great. Output is like this:
> 2013/05/01 16:16:40 Issuing [uname -f]
> 2013/05/01 16:16:40 uname: invalid option -- 'f'
> 2013/05/01 16:16:40 Try 'uname --help' for more information.
> 
> 
> However, if I add autodie then I get:
> 
> 2013/05/01 16:16:33 Issuing [uname -f]
> 2013/05/01 16:16:33 uname: invalid option -- 'f'
> 2013/05/01 16:16:33 Try 'uname --help' for more information.
> Can't close(GLOB(0x2554c80)) filehandle: '' at ./test02.pl line 20
> 
> 
> close does not fail if the command is ok, e.g. 'uname -a'. Can anybody
> explain to me why close fails in the example above?

One thing that I know bit me with the 'or die' pattern is that
with a pipe if the child process exits with an non-zero exit
status then close returns undef, even though there is really no
problem "closing the pipe". I had to read the perldoc closely to
notice this. So with the 'or die' pattern I had to change it
around a little bit, from:

  close $fh or die "close: $!";

...to...

  close $fh or $? != 0 or die "close: $!";

I'm *guessing* that the same thing is biting you, in that when
the piped process signals failure the close also signals failure,
even though there was no actual error with close, and autodie
just follows suit and dies. There's no meaningful errno because
no error actually occurred within your process.

My conclusion appears to be confirmed with the following
one-liners:

# This works fine.
perl -Mautodie -E 'open my $fh, "-|", "/bin/true"; close $fh;'

# This fails with the same error you get.
perl -Mautodie -E 'open my $fh, "-|", "/bin/false"; close $fh;'

So perhaps this is a bug in autodie, or perhaps you should just
not use autodie with close and a pipe... I guess a work around
should be to disable it for the close:

use autodie;

open my $fh, "-|", "/bin/false";

{
    no autodie qw/close/;

    close $fh or $? != 0 or die "close: $!";
}

Regards,


-- 
Brandon McCaig <bamcc...@gmail.com> <bamcc...@castopulence.org>
Castopulence Software <https://www.castopulence.org/>
Blog <http://www.bamccaig.com/>
perl -E '$_=q{V zrna gur orfg jvgu jung V fnl. }.
q{Vg qbrfa'\''g nyjnlf fbhaq gung jnl.};
tr/A-Ma-mN-Zn-z/N-Zn-zA-Ma-m/;say'

Attachment: signature.asc
Description: Digital signature

Reply via email to