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.

Reply via email to