Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number
 
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 (Monsignor) 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 avoiding work at the Monastery: (9)
As of 2014-09-30 11:28 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    How do you remember the number of days in each month?











    Results (364 votes), past polls