【问题标题】:Using sigaction without SA_RESTART and preventing an infinte loop在没有 SA_RESTART 的情况下使用 sigaction 并防止无限循环
【发布时间】:2020-08-18 12:39:55
【问题描述】:

我有以下代码:

struct sigaction act = {{0}};
act.sa_handler = handler;
sigaction(SIGINT, &act, nullptr);
while (true) 
{
    std::cout << "input:";
    std::getline(std::cin, line);
    // Handle line
}

当我收到 SIGINT 时,程序陷入无限循环。我不能简单地设置 SA_RESTART(如here),因为我想在收到信号时打印一条消息。

我不想直接从处理程序中打印,所以我在其中设置了一个标志并在循环中检查它。

if (flag)
    std::count << "got SIGINT" << std::endl;

SA_RESTART 导致 getline 阻塞,所以我无法达到这个 if 并处理信号,除非 getline 返回。反正有这个吗?

编辑(完整示例):

#include <iostream>
#include <signal.h>

bool flag = false;

void handler(int signum)
{
    flag = true;
}

int main()
{

    struct sigaction act = {{0}};
    act.sa_handler = handler;
    //act.sa_flags = SA_RESTART;
    sigaction(SIGINT, &act, nullptr);
    while (true) 
    {
        std::cout << "input:";
        std::string line;
        std::getline(std::cin, line);

        if (flag) {
           std::cout << "got SIGINT" << std::endl;
           flag = false;
        }
    }
}

【问题讨论】:

  • 能否提供minimal verifiable example。也就是说,其他人可以复制并运行以重现问题的代码?
  • volatile bool flag = false;
  • @ErkiAring 这不起作用。问题是getline在被信号中断后不会阻塞下一次调用。
  • 请不要加回C标签。 C 和 C++ 是不同的语言,每种语言的答案都不同。正如您所评论的那样,两者都可能存在问题,但这并不意味着解决方案将是相同的。

标签: c++ c linux signals system-calls


【解决方案1】:

flag 由信号处理程序设置时,bool flag = false; 不正确。

正确:

std::sig_atomic_t volatile flag = false;

更多详情请见std::sig_atomic_t

【讨论】:

    【解决方案2】:

    getline 被中断时,将在cin 上设置一个错误标志。这需要清除以防止getline 不断失败。

    if (flag) {
       std::cout << "got SIGINT" << std::endl;
       flag = false;
       std::cin.clear();
    }
    

    【讨论】:

      猜你喜欢
      • 2014-12-28
      • 1970-01-01
      • 1970-01-01
      • 2017-10-30
      • 1970-01-01
      • 1970-01-01
      • 2015-11-04
      • 2014-02-13
      • 2015-12-06
      相关资源
      最近更新 更多