Subject: Re: bug#50129: closed (Re: bug#50129: -f - option doesn't respond to single EOF from TTY.)

From: Kaz Kylheku <[email-masked]>
Date: Fri, 20 Aug 2021 10:25:10 -0700

Nope! It looks like a behavior of fread.

We have to reverse the middle two arguments of fread,
so that it's reading an n-sized array of 1-byte objects,
rather than one object of size n.

   #include <stdio.h>

   int main(void)
   {
     char buf[8192];
     while (fread(buf, 1, sizeof buf, stdin) != 0);

     //                ^^^^^^^^^^^^^^ reversed these!
     return 0;
   }

and now, a behavior closely resembling the issue is
reproduced. You can see in the strace that two
zero-sized reads are needed to bail out:

   $ strace ./fread
    read(0, abc
    "abc\n", 8192)                  = 4
   read(0, "", 7168)                       = 0
   read(0, "", 8192)                       = 0
   exit_group(0)                           = ?
   +++ exited with 0 +++

what happens is that upon receiving the zero byte read,
fread is returning the number of bytes it has accumulated
to the application. The application calls fread again.

This is expected, because fread didn't fail.

In my original example, fread is called only once
and returns zero, because it was told to read a 128
byte object, during which it received a short read,
at which point it is game over.

Still, I don't understand.  The grep 3.1 and 3.7
code both have 1 as the second argument of fread,
and the size as the third.

This argument order is necessary, so that fread
doesn't discard partial data at EOF.

So there is something more there. I'd have to play
with the code to see how the second argument is behaving
under the buffer resize logic and whatnot.

(E.g. if it happens that the second argument is
now always 1, that would explain why the behavior is
fixed.)