Feeds:
Posts
Comments

Posts Tagged ‘sysread’

or How do you make perl read input that is unbuffered?

Take a look at this. I’m simulating a process streams unbuffered output output irregularly. First it sends "hello ", then waits 5 seconds and sends "world".

I run the producer on its own, just in case it is buffering the output despite the fact I told it not to by setting $|. Nope, it isn’t. On the command line, I can see the hello output and then a few seconds later the world.

The consumer outputs whatever it receives. I get ctime() from Time::localtime for brevity.

$ date ; perl -e '$|=1; for (1..2) { print "hello "; sleep 5; print
"world\n" }' | perl -MTime::localtime -ne 'print ctime(), " : [$_]\n"'
Thu May 13 22:21:23 GMTDT 2010
Thu May 13 22:21:27 2010 : [hello world
]
Thu May 13 22:21:32 2010 : [hello world
]

No dice. The input is buffered so the consumer waits until it has received a whole line before it processes it.

Now, setting $| only affects the output, it doesn’t unbuffer the input. How about fiddling with $/ – the record separator?

$ date ; perl -e '$|=1; for (1..2) { print "hello "; sleep 5; print
"world\n" }' | perl -MTime::localtime -e '$/ = " "; while (<>) { print ctime(), " : [$_]\n" }'
Thu May 13 22:35:04 GMTDT 2010
Thu May 13 22:35:04 2010 : [hello ]
Thu May 13 22:35:09 2010 : [world
hello ]
Thu May 13 22:35:14 2010 : [world
]

Okay, quite cool, but there is a better solution. sysread is unbuffered. You will probably have to buffer the input yourself to ensure you have enough to process, but at least you get it as soon as it arrives. (Mental note: I should check if AnyEvent has something cool for this for anything more than a quick one-off script).

use Time::localtime;

use strict;
use warnings;

my ($input, $buffer);

while (sysread(STDIN, $input, 1024) > 0) {
    print ctime(), " : Read [$input]\n";
    $buffer .= $input;
    # Process $buffer here ...
}

And the test:

$ date ; perl -e '$|=1; for (1..2) { print "hello "; sleep 5; print
"world\n" }' | perl unbuffered.pl
Thu May 13 22:46:37 GMTDT 2010
Thu May 13 22:46:36 2010 : Read [hello ]
Thu May 13 22:46:41 2010 : Read [world
]
Thu May 13 22:46:41 2010 : Read [hello ]
Thu May 13 22:46:46 2010 : Read [world
]

Read Full Post »

Follow

Get every new post delivered to your Inbox.