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

Simple problem. I have 2 perl programs, one feeding the other with an infinite loop of "\n" terminated data lines. I'm running perl v5.10.0 built for i486-linux-gnu-thread-multi. I get no output on the following:
% ./buff1.pl | ./buff2.pl (out of memory)
-----buff1.pl-----
#!/usr/bin/perl use strict; use FileHandle; my $tslast = ""; while( 1 == 1 ) { my $timestamp = time(); if( $timestamp ne $tslast ) { my $ofh = select STDOUT; $| = 1; select $ofh; $ofh->autoflush(1); print STDOUT $timestamp . "\n"; $tslast = $timestamp; } }
------ end buff1.pl ------------------------ ------- buff2.pl ------------------------
#!/usr/bin/perl use FileHandle; foreach my $line ( <STDIN> ) { my $ofh = select STDOUT; $| = 1; select $ofh; $ofh->autoflush(1); print STDOUT $line; }
------ end buff2.pl ---------------

How can I remove buffering so that buff2.pl spits out my timestamps?

Replies are listed 'Best First'.
Re: Stop buffering on STDOUT
by jwkrahn (Abbot) on Nov 01, 2009 at 17:12 UTC
    foreach my $line ( <STDIN> )

    foreach reads from a list and then iterates over that list but you are reading from an infinite loop so you never get to the end of the list and it can't start iterating.    Change that to a while loop which reads one line at a time:

    while ( my $line = <STDIN> )
      Wow -- you are good! Problem solved in 3 seconds! Thanks don't seem like enough...
Re: Stop buffering on STDOUT
by b0at (Novice) on Nov 01, 2009 at 17:17 UTC

    Use while (my $line=<STDIN>) here, not for(each). while() takes its condition one scalar at a time, while foreach() tries to accumulate the entire list in memory at once, which is where you're getting your memory error.

    Also, setting the autoflush you only have to do once, not each time around the loop, unless it's getting unset somewhere else in the same program; and $| = 1; would work fine in this case without the rest of the file handle manipulation (though that may of course be more useful in a specialized case).

Re: Stop buffering on STDOUT
by biohisham (Priest) on Nov 01, 2009 at 17:29 UTC
    Actually output of STDOUT when directed to the terminal would be line buffered, buffer flushing is useful when your output is directed to a pipe as is the case with the buff1.pl program where the autoflush and the $| variable were set to non-zero values. Check Perl Documentation for $|..

    In buff2.pl however, since the output is directed to STDOUT right away then probably flushing is not warranted...


    Excellence is an Endeavor of Persistence. Chance Favors a Prepared Mind.