处理EINTR(使用goto吗?) [英] Handling EINTR (with goto?)
问题描述
背景:这是对此线程的后续问题关于在C ++(Linux/GCC)中处理EINTR以进行系统调用的信息.无论我是否打算分析应用程序,在特殊情况下,我似乎都应该处理将errno
设置为EINTR
的系统调用.有很多,很多有关使用goto
的意见. /p>
我的问题:系统调用是否将errno
设置为EINTR
?如果没有,那么您如何建议将以下代码转换为处理EINTR
?
if ( ( sock_fd = ::socket( domain, type, protocol ) ) < 0 ) {
throw SocketException( "Socket::Socket() -> ::socket()", errno );
}
谢谢!
干杯,
-克里斯
更新:基于以下答案,我总结了以下宏:
#define SOCK_SYSCALL_TRY(call,error) \
while ( (call) < 0 ) { \
switch ( errno ) { \
case EINTR: \
continue; \
default: \
throw SocketException( (error), errno ); \
} \
} \
用于将我的原始代码片段转换为以下示例:
SOCK_SYSCALL_TRY( sock_fd = ::socket( domain, type, protocol ), "Socket::Socket() -> ::socket()" )
希望这对其他人有帮助!
据我所知,套接字系统调用无法在errno设置为EINTR的情况下返回. 对于其他情况,我使用循环:
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;
}
}
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;
}
}
这篇关于处理EINTR(使用goto吗?)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!