TL;DR: Is it posixly incorrect for fflush(NULL)
not to flush stdin
?
Consider the following code snippet,
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void) {
char line[128] = {0};
fgets(line, sizeof(line), stdin);
puts(line);
fflush(NULL);
pid_t pid = fork();
if (pid == 0) {
fgets(line, sizeof(line), stdin);
puts(line);
exit(EXIT_SUCCESS);
} else {
waitpid(pid, NULL, 0);
fgets(line, sizeof(line), stdin);
puts(line);
}
return 0;
}
When fed a file with 3 lines using file redirection, it exhibits different behaviour on macOS and Linux,
$ cat test
line 1
line 2
line 3
macOS $ ./a.out < test
line 1
line 2
line 3
Linux $ ./a.out < test
line 1
line 2
line 2
The reason seems to be that glibc fflush(NULL)
does not flush stdin
although fflush(stdin)
is well defined. glibc manual reads,
If
stream
is a null pointer, thenfflush
causes buffered output on all open output streams to be flushed.
while POSIX states,
For a stream open for reading with an underlying file description, if the file is not already at EOF, and the file is one capable of seeking, the file offset of the underlying open file description shall be set to the file position of the stream, and any characters pushed back onto the stream by
ungetc()
orungetwc()
that have not subsequently been read from the stream shall be discarded (without further changing the file offset).If stream is a null pointer,
fflush()
shall perform this flushing action on all streams for which the behavior is defined above.
macOS libc source glibc source musl source
I am suspecting it to be a non-compliance bug in glibc/musl, but considering the enormous install base, I wonder if it is indeed against POSIX?