From: Andy K. <and...@gm...> - 2011-02-26 10:59:46
|
On 22 February 2011 17:03, Keith Marshall wrote: > On 22 February 2011 15:14, Andy Koppe wrote: >> On 22 February 2011 15:01, Keith Marshall wrote: >>> On 22 February 2011 13:54, Albrecht Schlosser wrote: >>>> Instead of using flush, it is also possible to set stdout and stderr >>>> unbuffered unconditionally at program initialization: >>>> >>>> setvbuf (stdout,NULL,_IONBF,0); >>>> setvbuf (stderr,NULL,_IONBF,0); >> >> _IOLBF ought to do the job too, except that according to MSDN "For >> some systems, this provides line buffering. However, for Win32, the >> behavior is the same as _IOFBF - Full Buffering." :( > > So, yet another example of "broken windows" behaviour. :-) > > AFAICT, the ISO C Standard insists that stderr shall *not* be fully > buffered, when opened. Ever. (That is, irrespective of whether it is > connected to a terminal or otherwise). Thus, it might be unbuffered, or > it might be line buffered, but it should never be fully buffered. Okay, > Windows apparently does not have any concept of line buffered (IOLBF) > output, so that means, for standards conformance[*] stderr should never > be anything other than unbuffered; yet it appears that it becomes fully > buffered when connected to a pipe. You're right. I wrote the little test below to check. It prints a row of asterisks for each of the six combinations of stdin/stderr streams and default/full/no buffering, with a small delay between each asterisk. The asterisks should appear one-by-one when unbuffered and all-at-once when buffered. It shows that enabling and disabling buffering with setvbuf works correctly both in the console and with a pty, i.e. a pipe. It also confirms that on a pipe, both stdout and stderr are buffered by deault. Finally, with a console, both stdout and stderr are unbuffered by default. Andy #include <stdio.h> #include <stdlib.h> void test(FILE *f, char *s) { int i; fputs(s, f); fflush(f); for (i = 0; i < 60; i++) { fputc('*', f); usleep(10000); } fputc('\n', f); fflush(f); } int main(void) { test(stdout, "stdout default: "); test(stderr, "stderr default: "); setvbuf(stdout, 0, _IONBF, BUFSIZ); test(stdout, "stdout _IONBF: "); setvbuf(stderr, 0, _IONBF, BUFSIZ); test(stderr, "stderr _IONBF: "); setvbuf(stdout, 0, _IOFBF, BUFSIZ); test(stdout, "stdout _IOFBF: "); setvbuf(stderr, 0, _IOFBF, BUFSIZ); test(stderr, "stderr _IOFBF: "); } |