ActiveState problem using IPC::Open3 with IO::Select

J

J. Romano

Dear Perl Community,

I am interested in using the IPC::Open2 and IPC::Open3 modules. From
reading the documentation I know that a potential problem is that a
program I am talking to may not flush its output, possibly causing a
deadlock. Therefore, I would like to check to see if input is waiting
before reading from the process, by following the advice mentioned in
IPC::Open3's perldoc:

If you try to read from the child's stdout writer and their stderr
writer, you'll have problems with blocking, which means you'll want
to
use select() or the IO::Select, which means you'd best use
sysread()
instead of readline() for normal stuff.

So I wrote a program which uses IO::Select to check for input waiting
to be read, and used sysread() to read its input, one character at a
time. Here is a short program that does just that:

#!/usr/bin/perl -w

use strict;
use IPC::Open3;
use IO::Select;
$| = 1; # autoflush STDOUT

# Declare filehandles and command to use:
my ($w, $r, $e);
my $cmd = 'perl -ne "$| = 1; print uc($_)"';

# Open the process and set the selector:
my $pid = open3($w, $r, $e, $cmd);
my $selector = IO::Select->new($r);

while (<>)
{
print $w $_; # send line to process

sleep 1; # allow some time for request to process

# print out output from process, if any exists:
while ($selector->can_read(0))
{
my $char;
sysread($r, $char, 1);
print $char;
}
}
__END__

A quick note: The program that is spawned which I communicate with is
specified near the top of the script in the line:

my $cmd = 'perl -ne "$| = 1; print uc($_)"';

This is basically a program that does nothing but print out a copy of
its input in capital letters. Also note that $| (the autoflush
variable) is set to non-zero (ensuring that the output is flushed
frequently).

Back to the problem: This short script works perfect on the two UNIX
machines I tested it on, but it doesn't work on the two versions of
ActiveState ActivePerl I tried it on. When I ran this script using
ActivePerl, it behaved as though the inner while loop did not exist.

For anyone who is interested, "perl -v" on one of the machines printed
the following information:

This is perl, v5.8.0 built for MSWin32-x86-multi-thread
(with 1 registered patch, see perl -V for more detail)
Binary build 805 provided by ActiveState Corp.
http://www.ActiveState.com
Built 18:08:02 Feb 4 2003

What's more is, when I replaced the inner while loop with the line:

print scalar <$r>;

the program worked just fine. This doesn't help, however, because I
want to be able to check to see if there is any data waiting to be
read (using IO::Select) before I try reading, otherwise I might cause
a deadlock.

I also tried the same thing with IPC::Open2, and I got the same
situation: it worked perfectly on UNIX, but not on ActivePerl.

I seached the newsgroups for any mention of this problem with
ActivePerl, but nothing turned up.

So am I doing anything wrong? Am I missing something? Do other
ActivePerl users have the same problem? And if so, is it a bug in
ActivePerl?

Thanks in advance for any responses,

Jean-Luc
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top