Beefy Boxes and Bandwidth Generously Provided by pair Networks Ovid
Your skill will accomplish
what the force of many cannot
 
PerlMonks  

close and autodie on pipes

by apomatix (Novice)
on Jun 29, 2012 at 18:06 UTC ( #979163=perlquestion: print w/ replies, xml ) Need Help??
apomatix has asked for the wisdom of the Perl Monks concerning the following question:

I want to get both the output and status of a pipe. Here is a working example:

#!/usr/bin/perl use strict; open my $fh, '-|', 'bash -c "echo Hello; exit 1"'; print <$fh>; close $fh; my $status = $? >> 8; print "$status\n";

Fine. It outputs

Hello 1

Now let's try to use autodie:

#!/usr/bin/perl use strict; use autodie; open my $fh, '-|', 'bash -c "echo Hello; exit 1"'; print <$fh>; close $fh; my $status = $? >> 8; print "$status\n";

No good, that breaks it:

Hello Can't close(GLOB(0x10082a098)) filehandle: '' at test.pl line 7

It is the "close" statement. So we can take that out.

use strict; use autodie; open my $fh, '-|', 'bash -c "echo Hello; exit 1"'; print <$fh>; #close $fh; my $status = $? >> 8; print "$status\n";

Now it is broken differently---it has lost the exit status:

Hello 0

I need to call close in order to get the exit status of a pipe.

So now I have settled on this ugly thing:

use strict; use autodie; open my $fh, '-|', 'bash -c "echo Hello; exit 1"'; print <$fh>; {no autodie; close $fh;} my $status = $? >> 8; print "$status\n";

That seems to work, but I'm not doing any error checking on the close statement:

Hello 1
Can I use close with autodie when my pipe fails? If not, how should I check for errors?

Comment on close and autodie on pipes
Select or Download Code
Re: close and autodie on pipes
by runrig (Abbot) on Jun 29, 2012 at 19:55 UTC
    If you want to catch exceptions, use eval:
    my $result = eval { close $fh }; unless ($result) { print "Got an error: $@\n"; }
    Or even:
    my $result = eval { open my $fh, '-|', 'bash -c "echo Hello; exit 1"'; print for <$fh>; close $fh; }; ...
Re: close and autodie on pipes
by Athanasius (Prior) on Jun 30, 2012 at 03:12 UTC

    From close in perldoc (emphasis added):

    If the filehandle came from a piped open, close returns false if one of the other syscalls involved fails or if its program exits with non-zero status. If the only problem was that the program exited non-zero, $! will be set to 0.

    So, by setting your pipe program to exit 1 you are ensuring that close() fails (i.e., returns false). autodie is working correctly here.

    how should I check for errors?
    #! perl use strict; use warnings; use autodie; open(my $fh, '-|', 'bash -c "echo Hello; exit 1"'); print <$fh>; { no autodie; unless (close($fh)) { die "Real pipe error: $!" if $!; } } print "status: ", ($? >> 8), "\n";

    HTH,

    Athanasius <°(((><contra mundum

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://979163]
Approved by toolic
Front-paged by MidLifeXis
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others exploiting the Monastery: (6)
As of 2014-04-18 01:02 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    April first is:







    Results (460 votes), past polls