问题
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!
回答1:
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;
}
}
回答2:
I programed an FTP server and I never had to use goto. I usually constructed interruptable system-calls like this:
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 your server has caught a signal, and it is most of the time important to handle that signal.
来源:https://stackoverflow.com/questions/2958114/handling-eintr-with-goto