Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Concurrent Input and Output in Perl

Tags:

c

pipe

perl

Recently I've taken up learning pipes for fun. I've gotten stuck on a few parts but I have it mostly figured out I think, however I cannot figure out how to get input to forward to a program and output from that program at the same time.

Currently I have this Perl script that handles the piping:

#!/usr/bin/perl
use strict;
use warnings;
use threads;
use FileHandle;
use IPC::Open2;

my $cv_program = "./test"; #test is the compiled C program below
my $cv_message = "";
my $cv_currentkey = "";
my $pid = open2(*PIN, *POUT, $cv_program);
my $thread_pipeout = threads->create('PIPEOUT', \&PIN);

$thread_pipeout->detach();

while($cv_currentkey ne "\n")
{
    $cv_currentkey = getc(STDIN);
    $cv_message .= $cv_currentkey;
}
print POUT $cv_message;

sub PIPEOUT
{
    my $PIN = shift;
    while(<PIN>)
    {
        print $_;
    }
}

And then I have this C program which just outputs something, asks for a string, then prints that string:

#include <stdio.h>

int main(int argc, char const *argv[])
{
    char input[100] = {0};

    printf("This is a test.\n");
    fgets(input, 100, stdin);
    printf("You entered %s\n", input);
    return 0;
}

The output from running the Perl script is:

~/Programming/Perl Pipes$ ./pipe.pl
Hello
This is a test.
You entered Hello

Notice it blocks while taking input and then prints everything in a block after. I need it to print This is a test, then wait for input like the actual program would.

Also I'll note is the reason I use getc instead of STDIN in the Perl script is because I couldn't find a way to get STDIN to not block the output from test.c, however getc isn't working too well at the moment either.

like image 359
ozdrgnaDiies Avatar asked Nov 06 '12 20:11

ozdrgnaDiies


Video Answer


1 Answers

I think the problem is mostly on the C end rather than the Perl end. C sees that its standard-output is going to a pipe, so it isn't very punctilious about making sure it flushes its standard-output buffer before querying standard-input.

To fix this, you should be able to just add this line:

fflush(stdout);

after the first printf and before the fgets.

(Disclaimer: Not tested.)

like image 138
ruakh Avatar answered Sep 30 '22 09:09

ruakh