http://qs1969.pair.com?node_id=22114

Cybercosis has asked for the wisdom of the Perl Monks concerning the following question:

Alrighty, I posted a question before on a similar topic (unidirectional IPC in Win32). Can anybody help me with bidirectional IPC? I've tried open2() and open3(), but neither have worked.
~Cybercosis

Replies are listed 'Best First'.
(jcwren) RE: Win32 Bidirectional IPC
by jcwren (Prior) on Jul 12, 2000 at 02:06 UTC
    Your basic problem is that your not using a file handle or a typeglob for the open2() parameters. See below:

    Stealing once again from Programming Perl, Chapter 7

    7.2.39 IPC::Open2 - Open a Process for Both Reading and Writing
    use IPC::Open2; # with named filehandles $pid = open2(\*RDR, \*WTR, $cmd_with_args); $pid = open2(\*RDR, \*WTR, $cmd, "arg1", "arg2", ...); # with object-oriented handles use FileHandle; my($rdr, $wtr) = (FileHandle->new, FileHandle->new); $pid = open2($rdr, $wtr, $cmd_with_args);
    The open2() function forks a child process to execute the specified command. The first two arguments represent filehandles, one way or another. They can be FileHandle objects, or they can be references to typeglobs, which can either be explicitly named as above, or generated by the Symbol package, as in the example below. Whichever you choose, they represent handles through which your program can read from the command's standard output and write to the command's standard input, respectively. open2() differs from Perl's built-in open function in that it allows your program to communicate in both directions with the child process.

    open2() returns the process ID of the child process. On failure it reports a fatal error.

    Here's a simple use of open2() by which you can give the program user interactive access to the bc(1) command. (bc is an arbitrary-precision arithmetic package.) In this case we use the Symbol module to produce "anonymous" symbols:
    use IPC::Open2; use Symbol; $WTR = gensym(); # get a reference to a typeglob $RDR = gensym(); # and another one $pid = open2($RDR, $WTR, 'bc'); while (<STDIN>) { # read commands from user print $WTR $_; # write a command to bc(1) $line = <$RDR>; # read the output of bc(1) print STDOUT "$line"; # send the output to the user }
    open2() establishes unbuffered output for $WTR. However, it cannot control buffering of output from the designated command. Therefore, be sure to heed the following warning. WARNING: It is extremely easy for your program to hang while waiting to read the next line of output from the command. In the example just shown, bc is known to read and write one line at a time, so it is safe. But utilities like sort(1) that read their entire input stream before offering any output will cause a deadlock when used in the manner we have illustrated. You might do something like this instead:
    $pid = open2($RDR, $WTR, 'sort'); while (<STDIN>) { print $WTR $_; } close($WTR); # finish sending all output to sort(1) while (<$RDR>) { # now read the output of sort(1) print STDOUT "$_"; }
    More generally, you may have to use select to determine which file descriptors are ready to read, and then sysread for the actual reading. 7.2.39.1 See also The IPC::open3 module shows an alternative that handles STDERR as well.

    --Chris

    e-mail jcwren
(jcwren) Re: Win32 Bidirectional IPC
by jcwren (Prior) on Jul 12, 2000 at 01:37 UTC
    Could you be a little more specific? Do you need sample code? Do you have code that doesn't work? Do you have code that sometimes works, but you don't understand why?

    I hate to harp on this, but you've got to provide details for people to help you (I'm not singling you out here, this has come up several times). Unless questions are asked in a clear, and somewhat concise manner, no one is going to be able to divine your needs. I mean, there are some good people here, but not that good.

    I really enjoy trying to help people with problems that are in my skill range. Really, I do. But without good input, I can't go off and play, to try to make it work. Which is distressing, because sometimes it means I have to do real work, instead of pursuing what might be an otherwise interesting Perl problem.

    --Chris

    e-mail jcwren
      here's the basics:
      my($read, $write, $pid); $pid = open2($read, $write, 'pipetest'); die "Pipe open failed: $!\n" if ($pid =~ /^open2/); print $write length($j_random_string); print $write $j_random_string; read $read $foo, length($j_random_string); print $foo, "\n";
      The code executes, but nothing happens. The pipetest executable executes, but doesn't recieve any data, nor does it print any. Any ideas?