Consider this program: $ cat foo.c #include <stdio.h> #include <unistd.h> int main (int argc, char **argv) { /* Check that fflush after a non-backup ungetc() call discards the ungetc buffer. */ int c; c = fgetc (stdin); printf ("c = '%c'\n", c); c = fgetc (stdin); printf ("c = '%c'\n", c); c = ungetc (argc > 1 ? c : '@', stdin); printf ("ungetc result = '%c'\n", c); fflush (stdin); printf ("after fflush, location = %d\n", (int) lseek (fileno (stdin), 0, SEEK_CUR)); c = fgetc (stdin); printf ("c = '%c'\n", c); c = fgetc (stdin); printf ("c = '%c'\n", c); return 0; } $ ./foo < foo.c c = '#' c = 'i' ungetc result = '@' after fflush, location = 582 c = 'n' c = 'c' $ ./foo 1 < foo.c c = '#' c = 'i' ungetc result = 'i' after fflush, location = 1 c = 'i' c = 'n' I found it inconsistent that fflush on seekable input streams sets the position of the underlying file descriptor to a different location based on whether the byte that was pushed back was what was originally read. And I'm not the only one - the Austin Group admitted that Interp-002 is fishy, and that an aardvark will be needed after POSIX 200x is released to require that fflush discards all ungetc data and sets the offset of the file descriptor to the stream position (ie. like the 2nd run, when pushing back the byte that was read, and NOT like the behavior of the 1st run when pushing back random bytes). https://www.opengroup.org/sophocles/show_mail.tpl?CALLER=index.tpl&source=L&listname=austin-group-l&id=11398
I'm not even going to look at this until something at the standard level is decided.
> I'm not even going to look at this until something > at the standard level is decided. A gnulib had a patch for this from 2009. http://lists.gnu.org/archive/html/bug-gnulib/2009-01/msg00131.html Was this also send to libc?
(In reply to Ondrej Bilka from comment #2) > > I'm not even going to look at this until something > > at the standard level is decided. > > A gnulib had a patch for this from 2009. > http://lists.gnu.org/archive/html/bug-gnulib/2009-01/msg00131.html > > Was this also send to libc? Not to my knowledge; POSIX 2013 is now explicit about fflush behavior, and gnulib is still claiming that glibc fflush() is broken and needs a workaround.
*** Bug 9754 has been marked as a duplicate of this bug. ***
I'm not clear what the current glibc behavior is. Does it reflect the Austin Group decision cited in the text of glibc bug 9754 (the one marked duplicate) or is it still somewhere in between the correct (per Austin Group) behavior and the (horribly wrong) behavior the original text of the standard demanded?
(In reply to Rich Felker from comment #5) > I'm not clear what the current glibc behavior is. Does it reflect the Austin > Group decision cited in the text of glibc bug 9754 (the one marked > duplicate) or is it still somewhere in between the correct (per Austin > Group) behavior and the (horribly wrong) behavior the original text of the > standard demanded? Current glibc behavior is still broken. The test program in this report is what drove the Austin Group decision cited in glibc bug 9754. When compiled, the foo.c in this report should output: $ ./foo < foo.c c = '#' c = 'i' ungetc result = '@' after fflush, location = 1 c = 'i' c = 'n' $ ./foo 1 < foo.c c = '#' c = 'i' ungetc result = 'i' after fflush, location = 1 c = 'i' c = 'n' I tested on rawhide with glibc 2.18.90 gets it right in the second instance, but is still broken in the first: $ ./foo < foo.c c = '#' c = 'i' ungetc result = '@' after fflush, location = 581 c = 'n' c = 'c'
Thanks Eric. I tested again and got the same results. I was just uncertain, with this bug having been around so long, whether anything had changed since it was first reported. Now I guess we need someone familiar with the code to look at what's involved in fixing it.