(stat(...) == -1 || faccessat(...) == -1) && errno == EINTR ?!??

Konstantin Kharlamov hi-angel@yandex.ru
Sun Feb 14 20:46:59 GMT 2021


On Sun, 2021-02-14 at 19:58 +0100, Tobias Bading wrote:
> Hello Konstantin,
>
> thanks for trying to reproduce the problem. Could you please try
>
> void handler (int signum)
> {
> }
>
> and
>
> timer.it_value.tv_usec = timer.it_interval.tv_usec = 1000000 / 10000;
>
> to increase the rate of SIGALRMs to 10000 (or even higher) per second?
> For me this reproduces the error also on shares that looked like they
> weren't affected when only 50 signals per second were created. There
> seems to be only a very short time window in which some piece of
> (probably CIFS-related) kernel code can be thrown of the rails by a
> signal, and the length of that time window probably depends on the
> performance of client and server, the network connection and whatnot.
> Since you're using a local share, your time window to produce the error
> is probably much smaller than mine.

Thanks, did that, I ran the testcase under `time` utility:

     λ time ./a
    ^C
    ./a  18.98s user 49.15s system 99% cpu 1:08.69 total

So, it ran for a minute before I interrupted it with ^C, no fails observed.

For the record, here's the code I used (the smb share is mounted under /tmp/mnt, and
it's a localhost share).

    #include <fcntl.h>
    #include <signal.h>
    #include <stdio.h>
    #include <string.h>
    #include <sys/stat.h>
    #include <sys/time.h>
    #include <sys/types.h>
    #include <unistd.h>

    static const char path[] = "/tmp/mnt/";

    void handler (int signum)
    {
    }

    int main ()
    {
      struct stat st;
      struct sigaction action;
      struct itimerval timer;

      memset (&action, 0, sizeof action);
      action.sa_handler = handler;
      action.sa_flags = SA_RESTART;
      if (sigaction (SIGALRM, &action, NULL))
      {
        perror ("sigaction() failed");
        return 1;
      }

      timer.it_value.tv_sec  = timer.it_interval.tv_sec  = 0;
      timer.it_value.tv_usec = timer.it_interval.tv_usec = 1000000 / 10000;
      if (setitimer (ITIMER_REAL, &timer, NULL))
      {
        perror ("setitimer() failed");
        return 1;
      }

      for (;;)
      {
        int r = stat (path, &st);
        if (r)
        {
          perror ("stat() failed");
          return 1;
        }

        r = faccessat (AT_FDCWD, path, R_OK, 0);
        if (r)
        {
          perror ("faccessat() failed");
          return 1;
        }
      }

      return 0;
    }

I built it with `gcc dont-interrupt-me.c -o a -g3 -O0`



More information about the Libc-help mailing list