in reply to Nested line buffered output

The code you posted lacks any mention of $|=1

You need to use strict and use warnings.

You also really need to check to see whether the open succeeded or not and print the reason when it fails.

Replies are listed 'Best First'.
Re^2: Nested line buffered output
by Anonymous Monk on Jun 01, 2010 at 18:04 UTC
    Okay, I can write two sample programs to illustrate my question.

    p1.pl
    #!/usr/bin/perl use strict; use warnings; $|=1; my $p2 = "/tmp/p2.pl"; open(P2,"$p2 |") || die "P2: $p2 - $!\n"; while(<P2>) { print; }
    p2.pl
    #!/usr/bin/perl use strict; use warnings; $|=1; my $i; for $i (1..10) { print "."; sleep 1; } print "\n";
    The output of p2.pl is 1 dot every second for 10 seconds but the output of p1.p1 is 10 dots after 10 seconds. Thanks.
      The problem is in the title: "line buffered". You're reading P2 line-by-line, but printing only one line total in p2.pl in the first place. Try this in p1.pl:
      #!/usr/bin/perl use strict; use warnings; $|=1; my $p2 = "./p2.pl"; open(P2,"$p2 |") || die "P2: $p2 - $!\n"; while( read( P2, $_, 1 ) ) { # fixed as per [ikegami]'s post below print; }

      BTW, you should probably be using a lexical filehandle, but given the short example I won't complain too loudly. ;-)

      Update: fixed bug in read as pointed out by ikegami in Re^4: Nested line buffered output.

        The fourth arg of read is wrong. It should be 0 or simply omitted.

        If you're going to read one character at a time, getc would be clearer. But I recommend reading all available data instead of one character at a time. You can do that using sysread since it returns all available data (up to the specified limit) as soon as any data is available.