Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

Basic IPC Example

by wind (Priest)
on Jul 25, 2007 at 02:02 UTC ( [id://628603]=perlquestion: print w/replies, xml ) Need Help??

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

Greetings Monks, I'm attempting to create a simple example for testing interaction with a secondary application. I have no experience with IPC yet, but my hope is to make code that is functional on both linux and ActivePerl. Here are the basic scripts that I'm starting from.
# name: basicipc.pl # # Purpose: Receive the STDOUT from a secondary app in real time # and do some basic translation on it. End when the secondary # app ends. my $cmd = 'perl delayed.pl'; open(CMD, "$cmd |") or die "Can't open $cmd: $!"; while (<CMD>) { my ($num) = /(\d+)/; print $num % 2 ? 'odd: ' : 'even: '; print $_; } close(CMD);
# name: delayme.pl # # Purpose: Simulate an external process sending delayed # output to STDOUT for input into a script. my $MAX = 5; # In Seconds; for (1..$MAX) { sleep 1; print "Step $_ of $MAX\n"; }
Now the problem with the above code is that the open command in basicipc.pl appears to be blocking, as in it does not succeed until the delayed.pl script is finished.

Now, if I wasn't doing any translation of the output, I could simply take advantage of the advice in perlipc for Background Processes, as that method lets the secondary process share the same STDOUT and STDIN as the parent. But my goal is to start off being able to translate the output, and then move on to bi-directional interaction.

I have access to most of the major perl books. However, there appear to be so many tools that could be used for this purpose, that I'm finding it difficult on deciding where to start. Especially when trying to maintain code that would support both Linux and Windows.

Regards,
- Miller

Replies are listed 'Best First'.
Re: Basic IPC Example
by kyle (Abbot) on Jul 25, 2007 at 02:26 UTC

    In your short example, you're likely suffering from buffering. A $|++ (see perlvar) in delayme.pl should take care of it. What's happening is that the output from delayme.pl is getting buffered on the way to its parent. If you leave it as it is but make the loop longer, you'll get a bunch of lines all at once, and and then another long pause while more lines build up in the buffer.

    When it comes to bidirectional communication, you will eventually want to look into IPC::Open3 or IPC::Run for that. I've used Expect in the past too.

      You're right. Adding $OUTPUT_AUTOFLUSH to delayed.pl does make the piped open work as desired. However, using the suggestion in perlipc for Background Processes does not require any addition to delayed.pl.
      # name: basicipc.pl (non-filtering version) # # Purpose: Receive the STDOUT from a secondary app and simply # mirror it to our STDOUT. my $cmd = 'perl delayed.pl'; system("$cmd &");
      Why do these function different? I suppose it could be as simple as the fact that delayed.pl script detects where its STDOUT is being directed and chooses to buffer in the case of open with pipe. But then my question would be, is there a way for open to force delayed.pl to not buffer without having to edit delayed.pl itself? Maintaining that delayed.pl is a simulation of a real executable and not simply another perl script.

      - Miller
        Why do these function different? I suppose it could be as simple as the fact that delayed.pl script detects where its STDOUT is being directed and chooses to buffer in the case of open with pipe

        I've been trying to figure that one out for quite sometime. This is my take, (and I may be wrong). When you feed a program with piped input, the program will wait until the input pipe is closed, before proceeding. Why? How does it know when input has ended?

        When you run apps from a terminal, and feed it multiline input, you usually need to send a Control-D to signal "end of input.... now start processing it". Now the way you signal "end of input" in a pipe is to close it. See EOF character


        I'm not really a human, but I play one on earth. Cogito ergo sum a bum
Re: Basic IPC Example
by BrowserUk (Patriarch) on Jul 25, 2007 at 06:25 UTC

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://628603]
Approved by grep
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others chanting in the Monastery: (2)
As of 2024-04-26 00:57 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found