【问题标题】:Accept call interfered by signal handler接受信号处理程序干扰的呼叫
【发布时间】:2023-03-06 00:24:01
【问题描述】:

我在套接字上使用接受调用,该套接字应该只接受与客户端进程的连接。但是,使用 sigaction 为信号 SIGALRM 实现的信号处理程序被注册为可行连接。我想我应该检查与 select 或 poll 的连接,但我不确定这是否会使它复杂化。任何帮助将不胜感激。

编辑:很抱歉说这是一个连接。它似乎只是一种联系。我的代码有一个 while 循环,其条件只要接受不计算为 0 就运行。

更新:所以我刚刚发现了我的问题。 sigaction 标志是默认值。我将其更改为 SA_RESTART 并接受现在可以正常工作。我认为这与忽略原始 I/O 并返回 EINTR 有关,但我对此并不完全确定。有人知道吗?

【问题讨论】:

  • 信号处理程序如何成为“可行的连接”?这毫无意义……连接由文件描述符表示,accept 返回一个文件描述符,而信号处理程序不是文件描述符。
  • 这就是我如此困惑的原因。由于某种原因,当信号处理程序捕获信号时会建立连接。
  • 你怎么知道建立了连接?
  • 现在看看我的代码,我不会说它正在建立连接。看起来是这样,所以我将在问题中澄清这一点。接受调用是 while 循环中的一个条件,如下所示:(client_sock = accept(stuff here))

标签: c sockets signals


【解决方案1】:

在 Linux 上,系统调用(包括accept)可以被信号中断。

如果在系统调用进行时收到信号,系统调用将被中止并返回错误EINTR。尽管这是一个“错误”,但这并不意味着出了什么问题,它只是意味着您必须再次尝试调用。这种设计背后的推理相当复杂,超出了这个问题的范围。

正如您所发现的,您可以设置 sigaction 标志 SA_RESTART 以使特定信号不会发生这种情况。 accept 如果遇到错误则返回 -1,所以这看起来像:

while(1)
{
    int client_sock = accept(...);
    if(client_sock == -1)
    {
        if(errno == EINTR)
            continue; // try again
        ... normal error handling here ...
    }
    else
    {
        ... normal connection handling here ...
    }
}

更强大的解决方案是专门检查 EINTR - 以防您的程序收到未准备好的信号,或者其他代码使用信号但未设置 SA_RESTART。 (这可能是您在 3 个月后编写的您的代码)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多