Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > Nonblocking Pipe Open

Reply
Thread Tools

Nonblocking Pipe Open

 
 
Gregory Toomey
Guest
Posts: n/a
 
      06-29-2004
I need to combine pipe open + make it non-blocking. The semantics I want
are:

# based on perlopentut
open(NET, "ping 11.22.33.44 |", O_NONBLOCK ) || die "can't fork ping";
while (<NET>) { print }
close(NET)

which of course gets a syntax error.
Any idea how to achieve this?

gtoomey
 
Reply With Quote
 
 
 
 
J. Romano
Guest
Posts: n/a
 
      06-29-2004
Gregory Toomey <(E-Mail Removed)> wrote in message news:<1107135.EWZglpOOTA@GMT-hosting-and-pickle-farming>...
> I need to combine pipe open + make it non-blocking. The semantics I want
> are:
>
> # based on perlopentut
> open(NET, "ping 11.22.33.44 |", O_NONBLOCK ) || die "can't fork ping";
> while (<NET>) { print }
> close(NET)
>
> which of course gets a syntax error.
> Any idea how to achieve this?



Dear Greg,

To be able to read a command's output in a non-blocking manner, you
can use the IPC::Open2 module together with IO::Select. Here is a
sample program that pings 127.0.0.1:


#!/usr/bin/perl -w

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

# Declare filehandles and command to use:
my ($r, $w);
my $cmd = 'ping 127.0.0.1';

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

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;

unless ($selector->can_read(0))
{
sleep 1; # allow some time for request to process
# or else while loop will finish if there
# there is a pause in the program
}
}

__END__


I basically use IO::Select with the can_read() method to tell when
output is waiting for me to read. Note that I periodically sleep for
some time in order to give the process enough time to output some
text. Without the sleep command, the while loop would exit as soon as
ping produces a pause (because technically there is nothing waiting to
be read during a pause).

This script should work on Unix, but I'm almost entirely sure it
won't work on Win32 platforms.

Hope this helps,

-- Jean-Luc
 
Reply With Quote
 
 
 
 
Gregory Toomey
Guest
Posts: n/a
 
      06-30-2004
J. Romano wrote:

> Gregory Toomey <(E-Mail Removed)> wrote in message
> news:<1107135.EWZglpOOTA@GMT-hosting-and-pickle-farming>...
>> I need to combine pipe open + make it non-blocking. The semantics I want
>> are:
>>
>> # based on perlopentut
>> open(NET, "ping 11.22.33.44 |", O_NONBLOCK ) || die "can't fork
>> ping";
>> while (<NET>) { print }
>> close(NET)
>>
>> which of course gets a syntax error.
>> Any idea how to achieve this?

>
>
> Dear Greg,
>
> To be able to read a command's output in a non-blocking manner, you
> can use the IPC::Open2 module together with IO::Select. Here is a
> sample program that pings 127.0.0.1:
>
>
> #!/usr/bin/perl -w
>
> use strict;
> use IPC::Open2;
> use IO::Select;
> $| = 1; # autoflush STDOUT
>
> # Declare filehandles and command to use:
> my ($r, $w);
> my $cmd = 'ping 127.0.0.1';
>
> # Open the process and set the selector:
> my $pid = open2($r, $w, $cmd);
> my $selector = IO::Select->new($r);
>
> 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;
>
> unless ($selector->can_read(0))
> {
> sleep 1; # allow some time for request to process
> # or else while loop will finish if there
> # there is a pause in the program
> }
> }
>
> __END__
>
>
> I basically use IO::Select with the can_read() method to tell when
> output is waiting for me to read. Note that I periodically sleep for
> some time in order to give the process enough time to output some
> text. Without the sleep command, the while loop would exit as soon as
> ping produces a pause (because technically there is nothing waiting to
> be read during a pause).
>
> This script should work on Unix, but I'm almost entirely sure it
> won't work on Win32 platforms.
>
> Hope this helps,
>
> -- Jean-Luc



I'll give it a try.

I'm looking at writing a "domain diagnoser" that
- does whois, dig & ping concurrently for a domain (& subdomains)
- interprets data from the subprocesses & and displays results in real time
- possibly uses an expert system to diagnose problems

gtoomey
 
Reply With Quote
 
Rocco Caputo
Guest
Posts: n/a
 
      06-30-2004
On Wed, 30 Jun 2004 10:36:14 +1000, Gregory Toomey wrote:
>
> I'm looking at writing a "domain diagnoser" that
> - does whois, dig & ping concurrently for a domain (& subdomains)
> - interprets data from the subprocesses & and displays results in real time
> - possibly uses an expert system to diagnose problems


You may want to consider using POE instead of IO::Select if you plan to
do more complex things. For example, it can help you avoid rewriting
an IO::Select loop if you choose to add a graphical interface later.

http://poe.perl.org/?POE_Cookbook has several examples, including
pinging multiple hosts, working with graphical interfaces, and managing
child processes.

http://poe.perl.org/?Poing has a program I wrote several years ago.
It's a multi-host ICMP pinger with response history. I run it around
the clock to keep tabs on my internet provider. You should see some of
the old screen shots.

By the way, I'm POE's principal author.
Here's your obligatory grain of salt.

--
Rocco Caputo - http://poe.perl.org/
 
Reply With Quote
 
J. Romano
Guest
Posts: n/a
 
      06-30-2004
> J. Romano wrote:
>
> > # print out output from process, if any exists:
> > while ($selector->can_read(0))
> > {
> > my $char;
> > sysread($r, $char, 1);
> > print $char;
> >
> > unless ($selector->can_read(0))
> > {
> > sleep 1; # allow some time for request to process
> > # or else while loop will finish if there
> > # there is a pause in the program
> > }
> > }



Dear Gregory,

Just after I posted my sample Perl script, I realized that I could
write the same loop without sleep calls if I just use an inifnite loop
to continually check to see if there is output waiting to be read. In
other words, here's a script that does the same thing as the one I
gave you yesterday, but without sleeping:


#!/usr/bin/perl -w

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

# Declare filehandles and command to use:
my ($r, $w);
my $cmd = 'ping 127.0.0.1';

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

while (1) # infinite loop (use "last" to break out)
{
if ($selector->can_read(0))
{
my $char;
sysread($r, $char, 1);
print $char;
}

# Do anything you want in between reads here...
}

__END__


The advantage to this script is that, if your commands (like
"whois", "dig", and "ping") happen to pause, the loop won't
automatically break out. The disadvantage to this script is that it
might be difficult figuring out when a command has finished, or just
has delayed output (in which case you might have to put in a few
sleep() calls). Either way, I think that this script here does a
better job of helping you visualize what is going on -- you just need
to be mindful of the fact that some programs don't flush their output
right away, and that it's not a simple matter to tell if the program
has stopped running altogether.

So you might want to give the above script a try, if my first was
too confusing. But if both are too overwhelming for you, you might
want to check out Rocco Caputo's solution.

Hopefully one of our solutions will help.

-- Jean-Luc
 
Reply With Quote
 
Joe Smith
Guest
Posts: n/a
 
      07-06-2004
Gregory Toomey wrote:

> # based on perlopentut
> open(NET, "ping 11.22.33.44 |", O_NONBLOCK ) || die "can't fork ping";


You need to read perlopentut again. It clearly shows that O_NONBLOCK is
to be used with sysopen(), not with open().
-Joe
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
FAQ 8.26 Why doesn't open() return an error when a pipe open fails? PerlFAQ Server Perl Misc 0 04-28-2011 10:00 AM
nonblocking sockets nooneinparticular314159@yahoo.com Java 2 04-08-2006 09:41 AM
[named pipe] i wanna know about validate of pipe handle of client lee, wonsun C++ 1 11-02-2004 04:29 AM
Why does IO::Pipe::END generate an EXCEPT pipe message? lvirden@gmail.com Perl Misc 1 06-02-2004 02:17 PM
setSoTimeout in nonblocking mode? KimTaehwan Java 0 11-16-2003 01:51 AM



Advertisments