linuxer has asked for the wisdom of the Perl Monks concerning the following question:

Wise monks,
I seek your wisdom to enlighten me in this matter:

In short terms:
Why does the close fail, when I try to close the filehandle
before the eof is reached?

my $cmd = '/usr/bin/strings /etc/passwd'; open my $handle, "$cmd |" or die "open: $cmd: $!\n"; # read at least one line while ( <$handle> ) { last; } close $handle or die "$cmd; exit code($?): $!\n";

In longer terms, I tested several external commands and
tested each 100 times:

#!/usr/bin/perl # vi:ts=4 sw=4 et: use strict; use warnings; # these are available commands my %cmd = ( 'cat' => '/bin/cat', 'less' => '/usr/bin/less', 'more' => '/bin/more', 'strings' => '/usr/bin/strings', ); my $textfile = '/etc/passwd'; for my $k ( keys %cmd ) { my $success = 0; for ( 1 .. 100 ) { $success += open_close_pipe( $cmd{$k} ); } print "$cmd{$k}: $success/100 successful!", $/; } sub open_close_pipe { my $ext_cmd = shift; my $cmd = "$ext_cmd $textfile"; open my $handle, "$cmd |" or die "open: $cmd: $!\n"; # read at least one line while ( <$handle> ) { last; } close $handle or do { #warn "exitcode($?): $cmd: $!\n"; # to see exit code ... return 0; }; return 1; } __END__

This was my result:

$ perl read2.pl /bin/cat: 100/100 successful! /usr/bin/less: 38/100 successful! /bin/more: 31/100 successful! /usr/bin/strings: 40/100 successful!

And the results vary (with the same code):

$ perl read2.pl /bin/cat: 100/100 successful! /usr/bin/less: 16/100 successful! /bin/more: 26/100 successful! /usr/bin/strings: 32/100 successful!

When I close the handle directly after opening (comment out the while-loop), the result is like this:

$ perl read2.pl /bin/cat: 35/100 successful! /usr/bin/less: 0/100 successful! /bin/more: 41/100 successful! /usr/bin/strings: 37/100 successful!

When I read from the handle till nothing's left (comment out the last inside the while-loop), it looks fine:

$ perl read2.pl /bin/cat: 100/100 successful! /usr/bin/less: 100/100 successful! /bin/more: 100/100 successful! /usr/bin/strings: 100/100 successful!

Can you please enlighten me and tell me, why the close fails in most cases, when the handle hasn't reached eof?

I tested upon a Linux box with Perl v5.8.8 and Perl v.5.10.0.

edit: "longer terms" included into readmore

Replies are listed 'Best First'.
Re: close fails(?) occasionally when closing handle of a reading pipe?
by waba (Monk) on May 13, 2008 at 20:56 UTC

    From close,

    If the file handle came from a piped open, "close" will additionally return false if one of the other system calls involved fails, or if the program exits with non-zero status. (If the only problem was that the program exited non-zero, $! will be set to 0.) Closing a pipe also waits for the process executing on the pipe to complete, in case you want to look at the output of the pipe afterwards, and implicitly puts the exit status value of that command into $?.

    In this case, I'd say that closing prematurely the filehandle raises a SIGPIPE in the subprocess (as explained in the documentation). If this causes a non-zero status, you get a close error although no system call failed.

      I thank you for your reply.
      I don't know why I didn't have a look at perldoc -f close though I checked several perldocs for hints; but to check close's perldoc didn't come to my mind...

Re: close fails(?) occasionally when closing handle of a reading pipe?
by dave_the_m (Monsignor) on May 13, 2008 at 20:56 UTC
    If you close the reading end of a pipe before the process writing to it has finished, then the writing process will receive a SIGPIPE, and unless it catches this signal, it will die. This dying causes close() on the reader to return false, with $? set to the signal number.

    Note that pipes usually have a 4K buffer, so its possible for the writer to have finished writing and exited cleanly before the reader closes the pipe, even if all the data hasn't been read.

    Dave.

      Also thank you for your reply.