【问题标题】:Is checking EINTR necessary for all operation of socket?套接字的所有操作都需要检查 EINTR 吗?
【发布时间】:2019-02-07 08:59:33
【问题描述】:

我研究发现在使用套接字编程时可能会发生信号中断。我搜索了一下,发现万一出现信号中断,我们应该重试。也就是说,我必须捕获错误并重试。我必须像这样创建套接字。

int create_sock()
{
    int sock;

    while (1)
    {
        sock = socket(AF_INET, SOCK_STREAM, 0);

        if (sock == -1)
        {
            if (errno == EINTR)
            {
                continue;
            }
            else
            {
                perror("create_sock");
                exit(-1);
            }
        }

        break;
    }

    return sock;

}

在关闭、发送和连接功能的情况下,我是否应该按照上述程序进行操作?

【问题讨论】:

  • EINTR 绝对可以在send 期间发生。您应该阅读每个系统调用的“手册页”;他们将详细说明每个错误情况以及任何特殊要求。例如,IIRC,对于send,重试时必须传递完全相同的参数。
  • 对于connect()send() 和其他类似操作(包括read()write()),您应该考虑将函数包装在重试循环中。 close() 的情况比较棘手——最好假设它成功并且当调用返回时描述符不可用,即使 errno == EINTR 也是如此。我认为您的循环结构不好;它应该更像while ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { if (errno != EINTR) { perror("…"); exit(1); } }。循环体中有 5 行而不是 14 行(忽略循环体周围的大括号)。
  • 注意:socket() 不会被任何POSIXy 系统中的信号中断。特别是对于 Linux,您可以检查 man pages 调用是否可以返回 EINTR 错误。

标签: c linux sockets tcp


【解决方案1】:

所有套接字操作都需要检查 EINTR 吗? 是的,理想情况下你应该检查。不仅socket(),还有很多系统调用,如果在系统调用过程中发生信号,就会报告EINTR ERRORS。

来自signal(7)的手册页

信号中断系统调用和库函数 handlers 如果在系统调用时调用信号处理程序或 库函数调用被阻止,然后:

   * the *call is automatically  restarted  after  the  signal
     handler returns*; or

   * the call fails with the error **EINTR**.

如果对以下接口之一的阻塞调用是 被信号处理程序中断,然后调用将被 信号处理程序返回后自动重启 如果使用了 SA_RESTART 标志;否则通话将 失败并出现错误EINTR套接字接口: accept(2)、connect(2)、recv(2)、 recvfrom(2)、recvmsg(2)、send(2)、sendto(2) 和 sendmsg(2),除非在 插座(见下文)。

【讨论】:

  • 对于许多系统调用都是如此(如引用的,大多数与套接字相关的系统调用),但对于socket(2)不是。系统调用的一般经验法则是:如果它可能会阻塞一段时间,那么EINTR 是一个潜在的错误原因。但是socket(2) 从来没有理由阻止,因为它只是在内核中分配一些控制结构。正如@lockcmpxchg8b 在上述问题下的评论中指出的那样,请查看每个系统调用的手册页。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-31
  • 1970-01-01
  • 2015-07-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多