Subject: Re: bug#77800: grep-3.12: write-error-msg test failure on fedora rawhide (f43)

From: Jim Meyering <[email-masked]>
Date: Tue, 15 Apr 2025 18:54:23 -0700

On Tue, Apr 15, 2025 at 4:12 PM Grisha Levit <[email-masked]> wrote:
>
> On Tue, Apr 15, 2025 at 6:38 PM <[email-masked]> wrote:
> >
> > >> This seems to be fixed if the patch here [1] is _not_ applied when
> > >> building the RPM
> >
> > Can you check, perhaps using strace, whether that problematic patch pushes
> > the total amount of bytes written to stdout by grep, writing to /dev/full as you
> > invoke it, goes from a little below 4096 bytes, in a single write(2) system call,
> > to trying to write more than 4096 bytes, which likely forces two write calls,
> > the first 4096 bytes, then the remainder.
> >
>
> Indeed, the `--help' output is 4096 bytes normally and longer after the patch:
>
> $ ./src/grep --help | wc -c
> 4096
> $ patch ... && make -C src grep
> $ ./src/grep --help | wc -c
> 4122
>
> ltrace shows:
>
> printf("General help using GNU software:"...,
> "https://www.gnu.org/gethelp/") = 64
> exit(0 <unfinished ...>
> __fpending(0xffff9afe1510, 0, 0xffff9afe2280, 1) = 4096
> fclose(0xffff9afe1510)                           = -1
> dcgettext(0x41d480, 0x41c418, 5, 0x450000)       = 0x41c418
> __errno_location()                               = 0xffff9b0da760
> error(0, 28, 0x41c318, 0x41c418)                 = 0xffff9b0ebc90
>
> vs
>
> printf("General help using GNU software:"...,
> "https://www.gnu.org/gethelp/") = -1
> exit(0 <unfinished ...>
> __fpending(0xffff813f1510, 0, 0xffff813f2280, 1) = 0
> fclose(0xffff813f1510)                           = 0
> __errno_location()                               = 0xffff814e9760
> dcgettext(0x41d4a0, 0x41c418, 5, 0x450000)       = 0x41c418
> __errno_location()                               = 0xffff814e9760
> error(0, 0, 0x41c318, 0x41c418)                  = 0xffff814fac90
>
> and gdb (with the patch applied):
>
> (gdb) n
> 58   const bool prev_fail = (ferror (stream) != 0);
> (gdb) n
> close_stream (stream=0xfffff7ef1510 <_IO_2_1_stdout_>) at
> /usr/include/bits/stdio.h:137
> 137   return __ferror_unlocked_body (__stream);
> (gdb) n
> close_stream (stream=0xfffff7ef1510 <_IO_2_1_stdout_>) at close-stream.c:59
> 59   const bool fclose_fail = (fclose (stream) != 0);
> (gdb) n
> 69   if (prev_fail || (fclose_fail && (some_pending || errno != EBADF)))
> (gdb) p prev_fail
> $2 = true
> (gdb) p fclose_fail
> $3 = false
> (gdb) p some_pending
> $4 = false
> (gdb) p errno
> $5 = 28
> (gdb) n
> 71       if (! fclose_fail)
> (gdb) n
> 72         errno = 0;

Whoa. Thanks. It looks like this is a >19-year-old bug in stream-close.c
Here's a tentative fix -- the ChangeLog entry still lacks details of
when it was introduced: