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

I was trying to read the STDIN without stop the script in this point. To do that I have 2 options, use IO::Select or alarm(). But this doesn't work for Win32!!! I'm using Perl 5.8.0 (alarm() is only enabled on it for Win32) on Win2K.

Here are the tests:

Test IO::Select:

use IO::Select ; my $timeout = 5 ; my $stdin = \*STDIN ; my $ios = IO::Select->new( $stdin ) ; for(;;) { my $sel = $ios->can_read($timeout) ; my $buffer ; print "Reading ($timeout\s)...\n" ; 1 while( read( \*STDIN , $buffer, 1 , length($buffer) ) ) ; print "Read:<$buffer>" ; }
Test Alarm:
my $timeout = 5 ; for(;;) { eval { local $SIG{ALRM} = sub { die "DIE_ALARM\n" } ; alarm $timeout ; my $buffer; print "Reading ($timeout\s)...\n" ; 1 while( read( \*STDIN , $buffer, 1 , length($buffer) ) ) ; print "Read:<$buffer>" ; alarm 0 ; }; if ($@ !~ /DIE_ALARM/s) { die $@ } }
Someone has the solution for that?! Since this options are not working!!!

Graciliano M. P.
"The creativity is the expression of the liberty".

Replies are listed 'Best First'.
Re: Select on STDIN or ALARM?! For Win32 doesn't work!
by Ionizor (Pilgrim) on Dec 27, 2002 at 18:54 UTC

    IO::Select will not work for non-socket filehandles under Win32; that includes STD(IN|OUT).

    A relevant quote from "Network Programming with Perl", by Lincoln D. Stein:

    Win32 Issues

    Another problem arises when using multiplexed applications on Microsoft Windows platforms. When I originally developed the scripts in these chapters, I tested them on Windows98 using ActiveState Perl, and everything seemed to work fine. Later, however, I discovered that the gab5.pl script (Figure 12.1) was consuming a large amount of CPU time, even when it was apparently doing nothing but waiting for keyboard input.

    When I tracked down this problem, I learned that the Win32 port of Perl does not support select() on non-socket filehandles, including STDIN and STDOUT. So client-side scripts that multiplex across STDIN do not wait for the filehandle to be ready, but just loop.

•Re: Select on STDIN or ALARM?! For Win32 doesn't work!
by merlyn (Sage) on Dec 27, 2002 at 17:48 UTC
Re: Select on STDIN or ALARM?! For Win32 doesn't work!
by pg (Canon) on Dec 27, 2002 at 19:10 UTC
    One solution is to make your script multi-threaded, and use shared variables. I created this example for you, but you have to spend time to make this fit into your application, and my example is only a demo of the idea. Multi-thread is definitely no free lunch, and it requires time and experience.

    (As you may realize that there is chance for my demo code to lose some input, as you might get another input, before the parent process finish with the prev one. In my code, I just throw the prev one away. You may want to use a buffer, and only throw input away when the buffer is full.)
    use threads; use threads::shared; $| ++; my $line = ""; share($line); sub read_stdin { while (<STDIN>) { lock($line); $line = $_; print "child read in: $_\n"; } } threads->create(\&read_stdin); while (1) { if ($line ne "") { lock($line); print "parent process $line\n"; $line = ""; } else { print "do something else\n"; sleep(1);#this nothing but to slow down the prints } }
      Dis you test your code?! I made some tests for Thread too, but all the process stop when reading STDIN!!! :-/

      Test Thread:

      use threads; use threads::shared; my ($BUFFER) : shared ; $thra = threads->new(\&read_stdin); $thrb = threads->new(\&send_sock); print "By!\n" ; ############## # READ_STDIN # ############## sub read_stdin { 1 while( read( \*STDIN , $BUFFER, 1 , length($BUFFER) ) ) ; } ############# # SEND_SOCK # ############# sub send_sock { my ($buf_lng) ; for(;;) { if ( length($BUFFER) > $buf_lng ) { my $buf = substr($BUFFER , $buf_lng-1 ) ; print "<$buf>\n" ; } $buf_lng = length($BUFFER) ; print ".\n" ; sleep(1) ; } }
      But thanks for the reply!

      Graciliano M. P.
      "The creativity is the expression of the liberty".

        Of course, I tested my code before I post it. Before you question whether I tested my code, you better try my code out first. Everyone should only speak base on facts, not guesses.

        Your threaded code does not work, does not imply all threaded code do not work.

        But I will be happy to look into your code, and see why it is stuck. I will do this now.

        Still looking at your code... First your code exited right after I started it. Reason? simple, because after it created two child threads, your main thread just print "bye" and exit. How did you test your code? I will add joins before bye.

        ...

        Okay, tested your code. It died on you? Sorry it worked for me, after added:
        threads::join($thra); threads::join($thrb);
        Couple of things about your code:
        1. You use $BUFFER without check whether it is undef, that causes lots of warning, when you do length($BUFFER) etc.
        2. You better lock your shared variables before update them, although in your context, this not that serious a problem
Re: Select on STDIN or ALARM?! For Win32 doesn't work!
by BrowserUk (Patriarch) on Dec 27, 2002 at 18:34 UTC

    Term::ReadKey allows a non-blocking read from the terminal, though not STDIN if it's re-directed.


    Examine what is said, not who speaks.

why don't you use fork ?
by toss (Novice) on Dec 28, 2002 at 08:23 UTC
    you can create a child process to read what you want, like :
    $SIG{'CHLD'}='IGNORE'; $pid=fork; if(!$pid´){ (read stuff); } (stdin stuff);
      sorry for that '´' in my reply