On Tue, 11 Jun 2013 01:37:52 -0400, Andrei Alexandrescu
<seewebsiteforem...@erdani.org> wrote:
On 6/11/13 12:04 AM, David Nadlinger wrote:
On Tuesday, 11 June 2013 at 04:02:59 UTC, Andrei Alexandrescu wrote:
The test program is flawed; writeln() writes to stdout, and the
redirection is to stdin.
Wouldn't stdin be fd 0?
David
Oh indeed my bad. But the test is still flawed. Consider:
import std.stdio;
int main()
{
return printf("test\n") < 0;
}
This should return 1 if printf fails. It succeeds for 1</dev/null.
This actually gave me an idea of why it doesn't fail.
This code DOES fail:
import std.stdio;
int main()
{
writeln("hello");
std.stdio.stdout.flush();
return 0;
}
Here is the (interesting) issue:
FILE *, and likewise std.stdio.File, which uses FILE * as it's
implementation, is a buffered stream.
An interesting problem to solve for buffered streams is when to flush the
buffer. The most efficient thing to do is to wait until the entire buffer
is full, then flush it (call the syscall to write the data to the
handle/descriptor). However, in an INTERACTIVE console, you want to flush
more frequently, in case the data is coming out sporadically.
HOWEVER, the C runtime first checks to see if the file descriptor is a
console. If it is, it sets the flag indicating that it should flush on
newlines, otherwise, it does not. Instead of seeing 4K (or whatever
buffer size is) of data at a time, the user sees 1 line at a time, much
more parseable by a human. This is why cat'ing a file to another file is
much more efficient than cat'ing it to the console.
Important to note is that /dev/null is NOT a console :)
So what is happening is, writeln("hello") is writing "hello\n" to the FILE
*, which sits in the buffer, no flushing occurs, because /dev/null is not
a console. However, upon calling flush, it fails, because the file
descriptor is invalid.
Upon exit, std.stdio.stdout relies on core.stdc.stdio.stdout to flush the
data (in fact, I don't even think stdout's dtor is called). And C's
stdout does not throw an exception or alter the exit code. This is why
you have no visible errors.
If D did NOT rely on C's FILE *, it may have a chance to throw an
exception on program exit (but likely wouldn't because the buffer is
likely GC based and therefore can't be accessed on the dtor :)
Re: different shells behaving differently, depending on how the individual
shells are implemented can affect how this plays out.
-Steve