Nonblocking Pipe Open

Discussion in 'Perl Misc' started by Gregory Toomey, Jun 29, 2004.

  1. 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
     
    Gregory Toomey, Jun 29, 2004
    #1
    1. Advertising

  2. Gregory Toomey

    J. Romano Guest

    Gregory Toomey <> 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
     
    J. Romano, Jun 29, 2004
    #2
    1. Advertising

  3. J. Romano wrote:

    > Gregory Toomey <> 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
     
    Gregory Toomey, Jun 30, 2004
    #3
  4. Gregory Toomey

    Rocco Caputo Guest

    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/
     
    Rocco Caputo, Jun 30, 2004
    #4
  5. Gregory Toomey

    J. Romano Guest

    > 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
     
    J. Romano, Jun 30, 2004
    #5
  6. Gregory Toomey

    Joe Smith Guest

    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
     
    Joe Smith, Jul 6, 2004
    #6
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. KimTaehwan

    setSoTimeout in nonblocking mode?

    KimTaehwan, Nov 16, 2003, in forum: Java
    Replies:
    0
    Views:
    1,153
    KimTaehwan
    Nov 16, 2003
  2. nonblocking sockets

    , Apr 7, 2006, in forum: Java
    Replies:
    2
    Views:
    1,117
    Gordon Beaton
    Apr 8, 2006
  3. lee, wonsun
    Replies:
    1
    Views:
    505
    Jack Klein
    Nov 2, 2004
  4. Replies:
    1
    Views:
    248
    Ben Morrow
    Jun 2, 2004
  5. PerlFAQ Server
    Replies:
    0
    Views:
    342
    PerlFAQ Server
    Apr 28, 2011
Loading...

Share This Page