[PATCH] Increase the amount of data tested in stdio-common/tst-fwrite-bz29459.c

Adhemerval Zanella Netto adhemerval.zanella@linaro.org
Fri Feb 14 13:25:00 GMT 2025



On 14/02/25 09:43, Tulio Magno Quites Machado Filho wrote:
> Florian Weimer <fweimer@redhat.com> writes:
> 
>> Have you applied the patch?  We saw this as well.  But with the patch, 6
>> million bytes are written, which I believe exceeds even the most
>> generous kernel pipe buffer.
> 
> I decided to test this myself.
> The test does fail very frequently when the system is under high load.
> I was able to reproduce the issue in less than 10s when executing this
> test in a loop.
> 
> After applying this patch, I left the test running in a loop on high
> load. It's been running for 14h+ without any failures.
> I believe this is indeed an effective fix.
> 
> Adhemerval, would you object to applying this patch as-is?
> 

The main problem with this test is pipe buffer configurable but the caller
(in this case the shell), and on Linux the default size depends on the page
size.

If the idea is to force a pipe write error, I think using a buffer larger
than the default pipe buffer would be better. Something like:

int
main (void)
{
  /* Ensure that fwrite buffers the output before writing to stdout.  */
  setlinebuf (stdout);
  /* Ignore SIGPIPE in order to catch the EPIPE returned by the
     underlying call to write().  */
  xsignal (SIGPIPE, SIG_IGN);

  {
    const char *s = "hello\n";
    const size_t len = strlen(s);
    size_t rc = fwrite (s, 1, len, stdout);
    TEST_COMPARE (rc, len);
    TEST_COMPARE (ferror (stdout), 0);
    TEST_COMPARE (errno, 0);
  }

  {
    long pagesz = sysconf (_SC_PAGESIZE);
    /* Linux defaults the buffer size to 16 pages, but it can set up to
       /proc/sys/fs/pipe-max-size with F_SETPIPE_SZ.  Another option would
      to allocate a buffer larger than pipe-max-size.  */
    size_t bigsz = 17 * pagesz;
    char big[bigsz];
    memset (big, 'a', bigsz - 1);
    big[bigsz - 1] = '\0';

    size_t rc = fwrite (big, 1, bigsz, stdout);
    TEST_COMPARE (ferror (stdout), 1);
    TEST_COMPARE (errno, EPIPE);
    if (rc < bigsz)
      {
        fprintf (stderr, "Success: fwrite returned %zu < %zu and errno=EPIPE\n",
                 rc, bigsz);
        exit (0);
      }
  }

  fprintf (stderr, "Error: fwrite did not return an error\n");
  return 1;
}


More information about the Libc-alpha mailing list