in reply to Can't get it working: Bidirectional Pipe on Windows

As another data point, I did some tests with my own simple "echo" program. I was able to confirm that the first problem, "hangs with blank output" was caused by output buffering. I was unable to find any way to get an EOF recognized in "echo2.pl" for reasons that I don't understand. closing $writer didn't do it. So this still hangs, just further along in the process. I was hoping to find some way to get "echo2.pl" to exit, but that didn't happen.

The pipe will have a finite size and if you try to cram too much stuff into it via a blocking write, then it can "fillup" and you can deadlock while trying to cram even more into the pipe. But that's not the problem in this simple example.

I think BrowserUk's suggestion is a good one. Although it is not completely clear to me why this fails. And of course, it is seldom that we have control over buffering settings the other process.

use strict; use warnings; use IPC::Open2; $|=1; $SIG{PIPE} = sub { print STDERR "SIGPIPE received\n"; exit; }; my $pid = open2(my $reader, my $writer, "perl echo2.pl"); print "pid=$pid\n"; print $writer "$_\n" for (qw(first second third )); print "Data written\n"; print $writer chr 4; #try manually send EOF - didn't work! close $writer; #reader still "hangs" print "Reading from pipe:\n"; while( my $in=<$reader>) { print "Received: ".$in."\n"; } close $reader; print "No more data\n"; waitpid($pid, 0); print "Finished\n"; =echo2.pl #!/usr/bin/perl -w use strict; $|++; print "first test line\n"; while (<STDIN>){print;} =cut __END__ C:\TEMP>perl ipc_open2.pl pid=5688 first second third Data written Reading from pipe: Received: first test line Received: first Received: second Received: third ####now hung up in reader ### #### for some reason it doesn't see that input pipe #### closed
Update: Things are a lot easier if this is like a "one line in", "one line out" interface. Or if the response has a "end of transmission" flag, something like blank line means "end of transmission" so that we can quit trying to read more lines that will not be forthcoming.
use strict; use warnings; use IPC::Open2; $|=1; # this is for main program # $writer is alread unbuffered by open2 my $pid = open2(my $reader, my $writer, "perl echo2.pl"); print "pid=$pid\n"; for ( qw(first second third) ) { print $writer "$_\n"; # one line in, one line out my $result = <$reader>; print $result; } =heading #### echo2.pl ##### #!/usr/bin/perl -w use strict; $|=1; while (my $in=<STDIN>){print $in;} print STDERR "out of loop\n"; #never gets here! =cut #### echo2.pl ##### __END__ C:\TEMP>perl ipc_open2.pl pid=3244 first second third

Replies are listed 'Best First'.
Re^2: Can't get it working: Bidirectional Pipe on Windows
by rovf (Priest) on Mar 09, 2012 at 13:50 UTC
    Thanks for your comment. I also think that it has to do with buffering, and in this case I have zero knowledge about the properties of the other process, except what I already said.

    I also thought first that somehow EOF won't be recognized, so I explicitly sent a "Windows Textfile EOF" (Control-Z), but - as I already had expected - this had no effect. I think I will follow the solution suggested by BrowserUK. To be honest, I had hoped that I would find a solution which will then work on Unix too (although this is not required), but it seems that Windows and Unix are too different in this respect...

    -- 
    Ronald Fischer <ynnor@mm.st>
      I would re-consider this idea of not making a temporary file for the input. This simplifies the situation a lot. And prevents deadlocks that can occur in a single process while simultaneously feeding stuff in and reading stuff out.

      The File::Temp module is multi-platform and generates a unique file name that you can use. The best is to delete this file yourself when you are finished with it, although this file will be created in a directory that is periodically cleaned-up - don't assume that file will be there for any significant length of time! - if you are a single user on Windows, you have to run the "file cleanup" utility yourself!

      I would at least try making intermediate interface file before having to attempt complicated code to deal with this. You may be over-estimating the logistical requirements of a temporary interface file and under estimating the complexity of other solutions. The simple idea will be more easily portable.