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
streamis a null pointer, thenfflushcauses 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?
You have already quoted the relevant POSIX provisions.
So, with respect to your example,
stdina stream open for reading? Yes.fflushing it.More generally, then, there are conditions under which POSIX does not mandate that
fflush(NULL)should flushstdin:if it does not have an underlying open file description (though I'm unsure under what circumstances that would happen)
if the underlying file is incapable of seeking -- this is typically the case when
stdinis connected to a terminal, for exampleif the underlying file has already reached EOF
On the other hand, if Glibc's
fflush(NULL)fails to flushstdinwhen all of the POSIX criteria are satisfied, then yes, that is posixly incorrect.