How to pipe two CORE::system commands in a cross-platform way

Posted by Pedro Silva on Stack Overflow See other posts from Stack Overflow or by Pedro Silva
Published on 2010-05-27T21:57:34Z Indexed on 2010/05/27 22:11 UTC
Read the original article Hit count: 161

Filed under:
|
|

I'm writing a System::Wrapper module to abstract away from CORE::system and the qx operator. I have a serial method that attempts to connect command1's output to command2's input. I've made some progress using named pipes, but POSIX::mkfifo is not cross-platform.

Here's part of what I have so far (the run method at the bottom basically calls system):

package main;

my $obj1 = System::Wrapper->new(
    interpreter => 'perl',
    arguments   => [-pe => q{''}],
    input       => ['input.txt'],
    description => 'Concatenate input.txt to STDOUT',
);

my $obj2 = System::Wrapper->new(
    interpreter => 'perl',
    arguments   => [-pe => q{'$_ = reverse $_}'}],
    description => 'Reverse lines of input input',
    output      => { '>' => 'output' },
);

$obj1->serial( $obj2 );


package System::Wrapper;

#...

sub serial {
    my ($self, @commands) = @_;

    eval {
        require POSIX; POSIX->import();
        require threads;
    };

    my $tmp_dir = File::Spec->tmpdir();

    my $last = $self;

    my @threads;

    push @commands, $self;

    for my $command (@commands) {

        croak sprintf
        "%s::serial: type of args to serial must be '%s', not '%s'",
        ref $self, ref $self, ref $command || $command
        unless ref $command eq ref $self;

        my $named_pipe = File::Spec->catfile( $tmp_dir, int \$command );

        POSIX::mkfifo( $named_pipe, 0777 )
          or croak sprintf
          "%s::serial: couldn't create named pipe %s: %s",
          ref $self, $named_pipe, $!;

        $last->output( { '>' => $named_pipe } );
        $command->input( $named_pipe );

        push @threads, threads->new( sub{ $last->run } );
        $last = $command;
    }

    $_->join for @threads;
}

#...

My specific questions:

  1. Is there an alternative to POSIX::mkfifo that is cross-platform? Win32 named pipes don't work, as you can't open those as regular files, neither do sockets, for the same reasons.

  2. The above doesn't quite work; the two threads get spawned correctly, but nothing flows across the pipe. I suppose that might have something to do with pipe deadlocking or output buffering. What throws me off is that when I run those two commands in the actual shell, everything works as expected.

© Stack Overflow or respective owner

Related posts about perl

Related posts about threads