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

Hey all!

I am trying to make a bidirectional communication to an external program using IPC::Open2. The problem is: I cannot "read" program's output unless I close the writer handle before attempting to read.

Such a problem is mentioned also here (I am not using Oracle but the essence of the problem is the same i guess): http://rootshell.be/~yong321/computer/OracleAndPerl.html (Pls see the first code block in Appendix section, also copied below).

use IPC::Open2; local (*Reader, *Writer); $pid = open2(\*Reader, \*Writer, "e:/oracle/ora81/bin/sqlplus -s scott +/tiger"); print Writer "set pagesize 100\n"; print Writer "select * from emp;\n"; print Writer "exit\n"; close Writer; #have to close Writer before read #have to read and print one line at a time while (<Reader>) { print "$_"; } close Reader; waitpid($pid, 0); #makes your program cleaner
It says: "the Writer has to be closed before you can read from the Reader". Why? Is there a way to overcome because I need to make read-write-read-write-read-... sequentially and I cannot open a new connection every time I want to read.

However such a code block would perfectly work (again there is a read followed by a write):

use IPC::Open2; local (*Reader, *Writer); $pid = open2(\*Reader, \*Writer, "bc -l"); $sum = 2; for (1 .. 5) { print Writer "$sum * $sum\n"; chomp($sum = <Reader>); } close Writer; close Reader; waitpid($pid, 0); print "sum is $sum\n";
I desperately need your opinion.

Replies are listed 'Best First'.
Re: can't read before closing the writer in open2
by jasonk (Parson) on Jul 10, 2007 at 14:43 UTC

    As the documentation for IPC::Open2 tells you, the big problem with trying to interface with a program in this way, is that while you can be reasonably sure that your perl program isn't buffering (IPC::Open2 will turn on autoflush on the writer handle automatically) you probably can't control whether the program you are interfacing with is going to buffer due to the fact that it is reading from a pipe. If the program you are controlling does buffer the data (like sqlplus) then you have to close the writer to get it to process it's buffer. If the program you are controlling does not buffer (like bc) then it works just like you would expect. If you need to control something that is doing buffering, you would be better off with Expect, which can allocate a pseudo-tty and trick the program into thinking it is talking to a terminal rather than a pipe.


    We're not surrounded, we're in a target-rich environment!
Re: can't read before closing the writer in open2
by zentara (Cardinal) on Jul 10, 2007 at 15:31 UTC
    There are certains types of programs that are a PITA to run through IPC, for the reason you mention. With these you need to try and get a shell in between. One way is Expect. You might try running your program through a bash shell instead of directly, or use IO::Pty. Examples below:

    I'm not really a human, but I play one on earth. Cogito ergo sum a bum
Re: can't read before closing the writer in open2
by karden (Novice) on Jul 10, 2007 at 17:05 UTC
    Thank you for your replies. Let me try Expect now.

    Another question: how would sourcing be done in the case of using Expect? Before spawning the program I am trying to run, I need to export/set/etc. some environment variables so I use a source file. How should I proceed?