stdin.readline no longer flushes stdout #847

Closed
pmichaud opened this Issue Sep 27, 2012 · 9 comments

Comments

Projects
None yet
4 participants
Owner

pmichaud commented Sep 27, 2012

Starting with 4.8.0, reading from standard input (via .readline in this case) no longer flushes the standard output. This is changed behavior from 4.6.0, and a potential blocker for the Rakudo Star 2012.09 release.

Consider the following example program:

pmichaud@kiwi:/zip/perl/parrot-4.6.0$ cat ../pz1.pir
.sub 'main' :main
    $P0 = getstdin
    'xyz'($P0)
.end


.sub 'xyz'
    .param pmc pio

    print "abc: "
    $S0 = pio."readline"()
    print "abc = "
    say $S0

    print "def: "
    $S0 = pio."readline"()
    print "def = "
    say $S0
.end

When run with parrot 4.6.0, the "abc: " and "def: " prompts are displayed prior to blocking for input:

pmichaud@kiwi:/zip/perl/parrot-4.6.0$ ./parrot ../pz1.pir
abc: hello
abc = hello

def: world
def = world

(Here I've entered "hello" and "world" in response to the prompts.)

In parrot 4.8.0 and current master (RELEASE_4_8_0-77-gd220be7), the prompts are not displayed until after the input is supplied:

pmichaud@kiwi:~/p6/parrot$ ./parrot /zip/perl/pz1.pir 
hello
abc: abc = hello

world
def: def = world

pmichaud@kiwi:~/p6/parrot$ 

This causes problems for programs that expect to be able to print a prompt to standard output and then read from standard input. This problem is known to exist on both Linux (Kubuntu 12.04) and Windows (XP 32-bit).

There have been other problems reported with Parrot's .readline in 4.8.0, I'm golfing those now and will file separate issue tickets as soon as I have them.

Thanks,

Pm

rurban was assigned Sep 27, 2012

Member

rurban commented Sep 27, 2012

Thanks for the testcase. This code changed, yes. I'll try to fix it ASAP. We have now an extra io_sync_buffers_for_read() function which does not handle STDIN/STDOUT in the READLINE case.

@rurban rurban pushed a commit that referenced this issue Sep 27, 2012

Reini Urban [GH #847] flush STDOUT in readline 1fe3b78
Member

rurban commented Sep 27, 2012

Fixed with 1fe3b78

Owner

pmichaud commented Sep 28, 2012

If I'm reading 1fe3b78 correctly, it appears to me that the standard output is flushed when .readline is invoked on any filehandle, not just standard input. That's not exactly correct either.

The standard behavior I've always encountered (in C and Perl 5) is that when standard output is line buffered, the buffer is flushed whenever input is requested from a line buffered device that requires characters to be obtained from the device. See the second paragraph of http://pubs.opengroup.org/onlinepubs/7908799/xsh/stdio.html , or section 7.19.3 of the C99 specification. Or just follow what a Perl 5 program does with standard input and output by default.

Pm

Owner

pmichaud commented Sep 28, 2012

The problem isn't limited to .readline -- programs using .read on the standard input also no longer have stdout flushed prior to input:

pmichaud@kiwi:/zip/perl/parrot-4.6.0$ cat ../pz4.pir
.sub 'main' :main
    $P0 = getstdin

    print "abc: "
    $S0 = $P0.'read'(1)
    say $S0
.end

pmichaud@kiwi:/zip/perl/parrot-4.6.0$ ./parrot ../pz4.pir
abc: hello
h
pmichaud@kiwi:/zip/perl/parrot-4.6.0$

pmichaud@kiwi:/zip/perl/parrot-4.8.0$ ./parrot ../pz4.pir
hello
abc: h
pmichaud@kiwi:/zip/perl/parrot-4.8.0$ 

pmichaud@kiwi:/zip/perl/parrot$ git describe --tags
RELEASE_4_8_0-78-g1fe3b78
pmichaud@kiwi:/zip/perl/parrot$ ./parrot ../pz4.pir
hello
abc: h
pmichaud@kiwi:/zip/perl/parrot$ 

Note that in Parrot 4.6.0, the prompt was displayed prior to reading input from standard input; in 4.8.0 and in RELEASE_4_8_0-78-g1fe3b78, the program waits for input before displaying the prompt.

By way of comparison, here's what Perl 5 and C do:

pmichaud@kiwi:/zip/perl$ cat pz4.p5
#!/usr/bin/perl

print 'abc: ';
read STDIN, $s, 1;
print "$s\n";

pmichaud@kiwi:/zip/perl$ perl pz4.p5
abc: hello
h

Note that Perl 5 flushes standard output prior to the read from standard input. Similarly in C:

pmichaud@kiwi:/zip/perl$ cat pz4.c
#include <stdio.h>

int main()
{
    int ch;
    printf("abc: ");
    ch = getchar();
    printf("%c\n", ch);
}

pmichaud@kiwi:/zip/perl$ make pz4
cc     pz4.c   -o pz4
pmichaud@kiwi:/zip/perl$ ./pz4
abc: hello
h

Feels like Parrot ought to be able to support the same standard default behavior as Perl 5 and C.

Pm

Owner

leto commented Sep 28, 2012

+1 to reverting back to our old behavior

Contributor

Whiteknight commented Sep 28, 2012

This is a bug, and represents a case which was clearly not covered by our test suite. I'm going to revert rurban's fix now and patch this issue.

Contributor

Whiteknight commented Sep 28, 2012

I reverted rurban's fix in 3260e22, and put in a possible fix in 2922c18.

I had mistakenly thought that the old IO system was setting up STDOUT as being linebuffered. However, on second read through it seems like stdout buffering was left up to the OS in the old system, and Parrot was not buffering it explicitly. I may be mistaken again, but I think this is what was happening.

In 2922c18 I removed buffering from stdout and run a small test program similar to the one posted by pmichaud. It appears to be working correctly. Can we confirm that this is the correct behavior at the rakudo level?

@rurban rurban pushed a commit that referenced this issue Sep 30, 2012

Reini Urban [GH #847] flush STDOUT in readline d5c2c63
Owner

leto commented Dec 11, 2012

I think this issue has been resolved. Can somebody confirm and close this issue?

Member

rurban commented Dec 11, 2012

The perl6 folks indeed confirmed that the issues were resolved with whiteknight's fixes.
We could not come up with an testcase, because it involved interactive input.

rurban closed this Dec 11, 2012

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment