Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When opening n pipes to child processes executing xargs from Perl, n-1 processes receive an empty line

Tags:

pipe

perl

xargs

...on the other side if I write something to the pipes before opening the next one, this doesn't happen.

The following code should make it clearer:

sub test_concurrent_pipes
{
    my $write_at_once = $_[0];
    my $pipe_handle;
    my @pipe_handle_list;
    my $i;
    foreach $i ( 1..3 )
    {
        open ( $pipe_handle, "| xargs echo" ) or die ( "Cannot open pipe.\n" );
        if ( $write_at_once == 1 )
        {
          print $pipe_handle "Hello\n";
        }
        push( @pipe_handle_list, $pipe_handle );
    }
    foreach $pipe_handle ( @pipe_handle_list )
    {
        print $pipe_handle "world\n";
    }
    foreach $pipe_handle ( @pipe_handle_list )
    {
        close ( $pipe_handle );
    }
}

print "Test 0: open all pipes before writing\n";
test_concurrent_pipes(0);

print "Test 1: write Hello before opening next pipe\n";
test_concurrent_pipes(1);

Running the test I get

./test_pipe_2_xargs.pl 
Test 0: open all pipes before writing


world world world
Test 1: write Hello before opening next pipe
Hello
Hello
Hello world world world

As you can see in Test 0, opening the 3 pipes in a row without any output in between generates 2 empty lines. Strangely enough, if I substitute xargs echo with cat - there are not empty lines produced. The xargs behavior seems also to contradict its man page, which states Blank lines on the standard input are ignored.

How can I avoid those empty lines?

This happens with Perl 5.14.2 on cygwin/XP and with Perl 5.8.8 on HP-UX 11.00.

I write what I'm really trying to do at the end, since it's irrelevant here:

efficiently cleanup all derived objects visible from all Clearcase views through a Perl script which forks one process per view to remove the files (xargs rm) before removing them from the VOBs (rmdo).

like image 881
lafrecciablu Avatar asked Nov 10 '14 14:11

lafrecciablu


1 Answers

Making "creation loop" use local variable ( my $pipe_handle ) fixes the problem.

foreach $i ( 1..3 )
{
    open ( my $pipe_handle, "| xargs echo" ) or die ( "Cannot open pipe.\n" );
    ...
}
like image 122
AnFi Avatar answered Nov 15 '22 05:11

AnFi