Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does select() keep failing with EINTR errno?

I have a C++ application that includes this function:

int
mySelect(const int fdMaxPlus1,
         fd_set *readFDset,
         fd_set *writeFDset,
         struct timeval *timeout)
{
 retry:
  const int selectReturn
    = ::select(fdMaxPlus1, readFDset, writeFDset, NULL, timeout);

  if (selectReturn < 0 && EINTR == errno) {
    // Interrupted system call, such as for profiling signal, try again.
    goto retry;
  }

  return selectReturn;
}

Normally, this code work just fine, however, in one instance, I saw it get into an infinite loop where select() keeps failing with the EINTR errno code. In this case, the caller had set the timeout to zero seconds and zero microseconds, meaning don't wait and return the select() result immediately. I thought that EINTR only occurs when a signal handler occurred, why would I keep getting a signal handler over and over again (for over 12 hours)? This is Centos 5. Once I put this into the debugger to see what was happening, the code returned without EINTR after a couple iterations. Note that the fd being checked is a socket.

I could add a retry limit to the above code, but I'd like to understand what is going on first.

like image 840
WilliamKF Avatar asked Nov 10 '22 19:11

WilliamKF


1 Answers

On Linux, select(2) may modify the timeout argument (passed by address). So you should copy it after the call.

retry:
struct timeout timeoutcopy = timeout;
const int selectReturn
  = ::select(fdMaxPlus1, readFDset, writeFDset, NULL, &timeoutcopy);

(in your code, your timeout is probably zero or very small after a few or even the first iterations)

BTW, I suggest rather using poll(2) instead of select (since poll is is more C10K problem friendly)

BTW, EINTR happens on any signal (see signal(7)), even without a registered signal handler.

You might use strace to understand the overall behavior of your program.

like image 121
Basile Starynkevitch Avatar answered Nov 14 '22 21:11

Basile Starynkevitch