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!
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;
}
}