Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

Non-blocking pipe write

by Marcello (Hermit)
on Nov 04, 2004 at 16:12 UTC ( #405204=perlquestion: print w/replies, xml ) Need Help??

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

Hello,

I have a question about pipes. In the following example, the parent blocks after sending 1024 pipe messages to the child because the child is not reading the messages. Is it possible to prevent this blocking behaviour and immediately return without blocking?

use strict; use warnings; use IO::Socket; my $handle; my $pid; if (!defined($pid = open($handle, "|-"))) { die "Fork failed: ".$!; } elsif ($pid == 0) { # Child sleep(5); exit 0; } else { # Parent $handle->autoflush(1); my $i = 0; my $result; do { $result = print $handle "ABC\n"; print "PIPE write ".++$i."\n"; } while ($result); }

I'm experiencing this in a large project where sometimes a child process is busy doing something which is not interruptable and therefore not able to read the pipe messages. The parent process needs to continue and not block. FYI, it is no problem that the pipe messages are lost, because they will be resend later.

Thanks in advance!

Replies are listed 'Best First'.
Re: Non-blocking pipe write
by ikegami (Pope) on Nov 04, 2004 at 16:16 UTC

    Look into the select RBITS, WBITS, EBITS in perlfunc, and/or IO::Select. caveat: select doesn't work on pipes in Windows.

      I tried:
      #!/usr/local/bin/perl use strict; use warnings; use IO::Handle; use IO::Select; my $handle; my $pid; if (!defined($pid = open($handle, "|-"))) { die "Fork failed: ".$!; } elsif ($pid == 0) { # Child sleep(5); exit 0; } else { # Parent $handle->autoflush(1); my $selector = IO::Select->new($handle); my $i = 0; do { if ($selector->can_write(0)) { print $handle "ABC\n"; print "PIPE write ".++$i."\n"; } else { print "PIPE cannot write\n"; } } while (1); }
      but only one pipe write is successful and then the can_write check fails every time. Can you be more specific please?

      FYI, I am on Linux

      Select mostly works on pipes in win32 (theres some strange behaviour but generally it works), select doesn't work on filehandles though.
Re: Non-blocking pipe write
by borisz (Canon) on Nov 04, 2004 at 16:54 UTC
    You mean like this?
    use strict; use warnings; use IO::Socket; my $handle; my $pid; if (!defined($pid = open($handle, "|-"))) { die "Fork failed: ".$!; } elsif ($pid == 0) { # Child stdin->blocking(0); sleep(5); exit 0; } else { # Parent $handle->autoflush(1); $handle->blocking(0); my $i = 0; my $result; do { $result = print $handle "ABC\n"; print "PIPE write ".++$i."\n"; } while ($i < 10000); }
    Boris
      I tried your code but now 1025 messages are written and then the parent blocks again... Any idea why?

        Hmm, no it should not block, the print should return and $result is undefined if the print fail. thats all.
        Boris
Re: Non-blocking pipe write
by iKnowNothing (Scribe) on Nov 07, 2004 at 01:18 UTC
    I had a similiar problem using TCP/IP sockets, and a fellow monk suggested that I solve the problem by setting flags on the handle. This worked great as long as I ran on UNIX. Unfortunately this didn't work for me since my script has to work on UNIX and Windows, but it may work for you.
    use Fcntl; my $flags; fcntl(SERVER_HANDLE, F_GETFL, $flags) || die $!; # Get the current fla +gs on the filehandle $flags |= O_NONBLOCK; # Add non-blocking to the flags fcntl(SERVER_HANDLE, F_SETFL, $flags) || die $!; # Set the flags on th +e filehandle
Re: Non-blocking pipe write
by tsmoyers (Pilgrim) on Nov 05, 2004 at 20:08 UTC

    I'm not sure how it will work for what you are doing, but I've had to use

    $| = 1;

    to force the buffer to flush to a pipe after each iteration. I don't know if this will help in your specific case (I code admin scripts on HPUX, Solaris and Linux; not Win), but I thought I'd offer it.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://405204]
Approved by pelagic
Front-paged by diotalevi
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others cooling their heels in the Monastery: (5)
As of 2020-05-25 10:59 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    If programming languages were movie genres, Perl would be:















    Results (145 votes). Check out past polls.

    Notices?