[Haskell-cafe] [Haskell-beginners] ghc --make Vs runhaskell

Richard A. O'Keefe ok at cs.otago.ac.nz
Thu Feb 5 03:10:50 UTC 2015

On 4/02/2015, at 4:35 pm, Brandon Allbery <allbery.b at gmail.com> wrote:

> C / C++ programs also do buffering, but there's a heinous hack which detects reads on stdin and flushes stdout beforehand. (Heinous because there is no guarantee that they are actually related --- but naïve programmers invariably do not learn about line buffering and expect all output to be unbuffered(*), and C standard library programmers eventually gave up and catered to them after years of trying to get them to pay attention. I have a nasty suspicion we're going to end up with a similar horrible hack in Haskell eventually.)

Looking in the last public draft of C99, section 7.19.3 has this:

    When a stream is line buffered, characters are intended to be transmitted to
    or from the host environment as a block when a new-line character is encountered.
>>> Furthermore, characters are intended to be transmitted as a block to the host
>>> environment when a buffer is filled, when input is requested on an unbuffered
>>> stream, or when input is requested on a line buffered stream that requires the
>>> transmission of characters from the host environment.

So the "heinous hack" is not about stdin or stdout specifically; the standard
requirement is that getting input from ANY line-buffered stream forces EVERY
line-buffered output stream to be flushed.  And it's this way precisely
*because* the C runtime doesn't know whether two such streams are "related" or
not, so it plays safe.  Given things like sockets, STREAMS, and ptys, I am not
sure that it is _possible_ for a Unix system to determine whether two streams
are or are not "related" reliably.

Solaris and OpenBSD do what the standard requires.

A local copy of the Linux manual pages says (in setbuf(3)):
    When an output stream ... is line buffered characters are saved up until
    a newline is output or input is read from any stream attached to a terminal
    device (typically stdin).
I hope that's wrong.  There's other GNU documentation that disagrees,
saying that every output stream is flushed whenever any input stream "actually
reads data from its file" and not mentioning line buffering at all.  I suspect
that Linux is doing the right thing, but digging through the glibc-2.20 sources
left me even more confused than the Linux documenters.

More information about the Haskell-Cafe mailing list