处理EINTR(使用goto吗?) [英] Handling EINTR (with goto?)

查看:86
本文介绍了处理EINTR(使用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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆