David M. Karr
David M. Karr

Reputation: 15225

Write text to pipe and read result never completes

I've written a Perl program that opens a pipe to xargs so that it will read from the input and run a command with each row of input.

I need to read the output from that pipe.

I use open3 and then write the input to the input file handle. Then a loop reads from the output filehandle.

But when it prints the last line that I expect to see, it just hangs and doesn't complete the process.

Here's an excerpt from the script

my $classNamesOutput = `classNamesInArchive $opt_archive`;

my $pid = open3( \*CHILD_IN, \*CHILD_OUT, false, "xargs -n1 listJavaClassRefs -p $opt_archive -c" );
print "pid[" . $pid . "]\n";

print CHILD_IN $classNamesOutput;

my $output = '';
my $matchingArchiveNames = '';

while ( my $row = <CHILD_OUT> ) {
    chomp $row;
    print "row[" . $row . "]\n";

    if ( $onlyListingMatches == 1 && $row eq $opt_className ) {
        print $opt_archive;
        last;
    }

    if ( $onlyListingMatches == 0 ) {
        $output .= $row . "\n";
    }
}

print "Past loop.\n";

It never prints Past loop: it just hangs on the last line of output that I think the called script would have produced.

Upvotes: 0

Views: 167

Answers (1)

user3243135
user3243135

Reputation: 820

You need to close the writer before the while loop:

close CHILD_IN;

Edit: The reason you need to close the pipe for xargs (but not in general) is that xargs apparently does not launch any processes until the input in finished. This can be seen by running cat | xargs echo:

cat | xargs echo
asdf
asd
faw
seas
eryawr
yawr
ya
ryhs
rhy
erh
< I press Ctrl-d here to terminate pipe >
asdf asd faw seas eryawr yawr ya ryhs rhy erh

For non-xargs programs it might still be a good idea anyways to close the pipe, or at least flush it, since there might be bytes stuck in a buffer at some level.

Upvotes: 4

Related Questions