On Tue, Mar 01, 2016 at 12:23:52AM -0600, Ryan Wilson wrote: > So I was studying sbase and found a bug in cat. POSIX says that cat -u should > "Write bytes from the input file to the standard output without delay as each > is read." But if you try feeding cat input slowly you can see this is not the > case: > > # Feed one byte per second to cat: > $ yes | pv -q -L1 | ./cat -u > <no output> > > It should print one byte per second, but instead it hangs. Running it under > ltrace -S reveals the problem: > > __libc_start_main(0x804877a, 2, 0xbff42644, 0x8048c10 <unfinished ...> > setbuf(0xb7728d40, 0) = > <void> > fread(0xbff4054c, 1, 8192, 0xb7728580 <unfinished ...> > SYS_read(8192, "y", 3076835683) = 1 > SYS_read(4096, "\n", 3076835683) = 1 > SYS_read(4096, "y", 3076835683) = 1 > SYS_read(4096, "\n", 3076835683) = 1 > SYS_read(4096, "y", 3076835683) = 1 > SYS_read(4096, "\n", 3076835683) = 1 > > cat disabled stdio buffering for stdout, but that is not sufficient. Input is > still buffered because fread blocks until it can fill the entire 8192 byte > buffer. Note that setbuf(stdin, NULL) is no fix either, because fread still > wants to fill the entire buffer you give it. > > The fix is to either: > > * Do a getchar/putchar loop and copy one byte at a time. Sucks, but that's > the only way to not block on reads with stdio. That's how cat originally did > it in Unix v7, and that's how the BSDs still do it for certain options. > * Do a read(2)/write(2) loop. That's what concat() did until commit c0d36e00, > but the problem is other things use concat() and its not safe for them to mix > raw IO with stdio IO. > > Thoughts?
Thanks for the report, this has been fixed on HEAD.