Search code examples
c++gotosystem-callseintr

Handling EINTR (with goto?)


Background: This is a follow-up question to this thread about handling EINTR for system calls in C++ (Linux/GCC). Regardless of whether or not I intend to profile my application, it seems like I should be handling system calls setting errno to EINTR as a special case. There are many, many, many opinions about the use of goto.

My question: is a system call setting errno to EINTR a case where goto is considered nominal? If not, then how would you suggest converting the following code to handle EINTR?

if ( ( sock_fd = ::socket( domain, type, protocol ) ) < 0 ) {
  throw SocketException( "Socket::Socket() -> ::socket()", errno );
}

Thanks in advance!
Cheers,
-Chris

UPDATE: Based on the answers below, I wound up writing the following macro:

#define SOCK_SYSCALL_TRY(call,error)              \
  while ( (call) < 0 ) {                          \
    switch ( errno ) {                            \
      case EINTR:                                 \
        continue;                                 \
      default:                                    \
        throw SocketException( (error), errno );  \
    }                                             \
  }                                               \

Which is used to transform my original snippet to this example:

SOCK_SYSCALL_TRY( sock_fd = ::socket( domain, type, protocol ), "Socket::Socket() -> ::socket()" )

Hope this helps someone else!


Solution

  • As far as I know the socket system call can't return with errno set to EINTR. For other cases I use a loop:

    while ((::connect(sock, (struct sockaddr *)&destAddress, sizeof(struct sockaddr))) == -1) {
        if (errno == EINTR) {
            LOGERROR("connect interrupted, retry");
            continue;
        } else if (errno == EINPROGRESS) {
            break;
        } else {
            LOGERROR("connect failed, errno: " << errno);
            return -1;
        }
    }