【问题标题】:Handling EINTR (with goto?)处理 EINTR(使用 goto?)
【发布时间】:2011-02-26 20:06:29
【问题描述】:

背景:这是this thread 的后续问题,关于在 C++ (Linux/GCC) 中处理系统调用的 EINTR。无论我是否打算分析我的应用程序,似乎我都应该将系统调用设置为 errnoEINTR 作为特例。关于goto的使用,有manymanymany意见。

我的问题:是系统调用设置errnoEINTR goto 被认为是名义上的情况?如果不是,那么您建议如何转换以下代码来处理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 );  \
    }                                             \
  }                                               \

这是用来把我原来的sn-p转换成这个例子的:

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

希望这对其他人有帮助!

【问题讨论】:

  • 克里斯,得到这本书:unpbook.com - 你会很高兴你做到了。源代码在线unpbook.com/src.html - 有关如何处理 EINTR 的示例,请参见那里。
  • 我从没想过使用 while/continue - 好主意!

标签: c++ goto system-calls eintr


【解决方案1】:

我编写了一个 FTP 服务器,但我从未使用过 goto。我通常像这样构建可中断的系统调用:

    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 表示您的服务器已捕获到一个信号,并且在大多数情况下处理该信号很重要。

【讨论】:

  • 我认为您处理的信号不正确。在您使用 -1 和 EINTR 从系统调用返回后,signal_handler 已经被异步调用。您需要在 signal_handler 中处理信号,或者使用 signal_fd。
【解决方案2】:

据我所知,当 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;
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多