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

I'm running into some problems with IO::Select examining an IO::Pipe in ActivePerl 5.8.7 (stock install) on Windows XP. For some reason, even though the writing thread is indicating that it is writing to its end of the pipe, an IO::Select can_read([timeout]) call never indicates readiness. What's more, it doesn't seem to be blocking. Am I doing something wrong, or am I just running into an OS-compatibility brick wall?

The following is simple test code. It sets up a reading parent and a writing child. The child prints (syswrites, actually) "[W]" after every write. The parent should print "[r][d:HELLO!\n:d]" for every line it reads, but it prints "[x]" to indicate that it is not ready. Examining the scalar return of $ios->can_read(); shows a zero value, but the call does not block, as the documentation says it should in such a case.

That said, if someone can recommend a better method for information exchange between threads that is non-blocking (or at least can indicate blocking), and is cross-platform on stock Perl 5.8 installs, I'd be quite grateful. Pointers (um... I mean... references) to relevant docs or sites are greatly appreciated. Thanks!

use strict; use IO::Pipe; use IO::Select; my $pipe = new IO::Pipe; if ( fork() ) { print "Parent live\n"; $pipe->reader(); my $ios = IO::Select->new(); $ios->add($pipe); while (1) { print "Handles: " . scalar $ios->handles . ", " . scalar $ios->can_read(1) . " ready.\n"; if ( $ios->can_read(1) ) { while (<$pipe>) { syswrite( STDOUT, "[r]", 3 ); print "[d:$_:d]\n"; } } else { syswrite( STDOUT, "[b]", 3 ); sleep 1; } } } else { print "Child live\n"; $pipe->writer(); $pipe->autoflush(1); while (1) { $pipe->print("HELLO!\n"); syswrite( STDOUT, "[W]", 3 ); sleep 1; } }

Update: Thanks, everyone, for having a look. I'll be taking a look at local sockets... I think that'll work well.

Replies are listed 'Best First'.
Re: IO::Select on an IO::Pipe not doing anything
by Zaxo (Archbishop) on Sep 23, 2005 at 03:46 UTC

    Select has never worked on pipes in win32, as far as I know. The os simply doesn't have a way to select except with sockets.

    After Compline,
    Zaxo

      Great idea, tried the following on WinXP and it worked:

      Outputs:

      C:\Temp>perl -w deleteme.pl Created local TCP socket on port 1861 Parent live Child live Handles: 1, 1 ready [r] [d:HELLO!:d] [W] Handles: 1, undef ready [b] Handles: 1, undef ready [b] Handles: 1, undef ready [b] Handles: 1, 1 ready [r] [d:HELLO!:d] [W]
Re: IO::Select on an IO::Pipe not doing anything
by monarch (Priest) on Sep 23, 2005 at 01:47 UTC
    On linux I get:
    $ perl -w deleteme.pl Child live Parent live Handles: 1, 1 ready. [r][d:HELLO! :d] [W][W][r][d:HELLO! :d] [W][r][d:HELLO! :d] [W][r][d:HELLO! :d] [W][r][d:HELLO! :d]

    Update: a couple of questions I would have are: why are you using while (<$pipe>) instead of sysread? Essentially the read code is entering an infinite loop as it reads, blocking line by line, the output from the child. Which I'm sure is not what you intended..

    Update 2: maybe try the following:

    I suspect that if you're going to use IO::Select then the handles returned to you should be processed by sysread (and syswrite if you're checking for handles that can be written to) as these clear the select flags and process only that bit of data which is available right now. The <> syntax, on the other hand, blocks as far as I know.

    Update 3: I can't get it to go with XP either.. using Perl v5.8.7 on MSWin32-x86-multi-thread and WinXP the IO::Select::select(undef, undef, undef, 1) call doesn't wait and it doesn't detect things being written to my pipe..

    Update 4: See below for an INET socket approach..