EINTR Handling (with goto?)

Background: This is the next question in this thread about handling EINTR for system calls in C ++ (Linux / GCC). Regardless of whether I intend to profile my application, it seems that I should handle system calls with installation errnoon EINTRas a special case. There are many , many , many opinions on use goto.

My question is: is this a system call errnoto the EINTRcase when gotoit is considered nominal? If not, how would you suggest converting the following code for processing 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 ended up writing the following macro:

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

What is used to convert my source fragment to this example:

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

Hope this helps someone else!

+3
source share
2 answers

As far as I know, a socket system call cannot return with errno set to EINTR. In 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;
    }
}
+4
source

I programmed an FTP server and I never had to use goto. I usually made intermittent system calls like:

    while( (ret = 
        splice_stream( data, NULL, file, &block_offset, 
            XFER_BLOCK_SIZE )) == -1 )
    {
        switch( errno )
        {
        case EINTR:
            if( server_handle_signal() )
                return FTP_QUIT;
            else
                continue;
            break;
        case EPIPE:
        case ECONNRESET:
            return FTP_ABOR;
        default:
            log_fatal("Splice error: %m\n");
            return FTP_ERROR;
        }
    }

EINTR means that your server has caught a signal, and in most cases it is important to process this signal.

+2
source

All Articles