【问题标题】:Wake up std::getline through signal通过信号唤醒 std::getline
【发布时间】:2017-09-29 12:13:51
【问题描述】:

我通过std::getline() 读取来自stdin 的用户输入,并且我希望能够通过SIGINT 退出程序。不幸的是,std::getline() 似乎没有被任何信号唤醒。因此,下面的代码仅在按下 CTRL-C RETURN 后中止。

#include <csignal>
#include <string>
#include <iostream>

bool abort_ = false;

void SigIntHandler(int signum) {
  std::cout << "Received SIGINT" << std::endl;
  abort_ = true;
}


int main(int argc, char *argv[]) {
  signal(SIGINT, SigIntHandler);

  while (!abort_) {
    std::string line;

    std::cout << "> ";
    std::getline(std::cin, line);
    if (!std::cin)
      std::cin.clear();

    std::cout << line << std::endl;
  }
}

为什么会这样?除了用户输入之外,我是否有机会唤醒std::getline()?或者有什么其他方式可以读取stdin,也可以响应信号?

【问题讨论】:

    标签: c++ signals stdin


    【解决方案1】:

    std::getline 和一般的输入/输出库在进程接收到信号时没有指定的行为。 C++ 库和语言没有指定任何特定的行为。信号只是顺便提了一下,最值得注意的只是:

    对函数信号的调用与任何结果同步 调用如此安装的信号处理程序。

    这和头文件的枚举是对 C++ 库中信号的引用的总和。信号是一个高度特定于操作系统的功能,C++ 库根本没有涵盖它。

    这里讨论的 C++ 库函数和类都不是信号安全的。在显示的代码中,信号处理程序不能对输入流做任何事情,因为它的内部状态是不确定的,而且整个事情不是信号安全的。

    因此,为了处理信号,有必要求助于特定于操作系统的低级别调用,例如 open()read()write(),而不是使用 C++ 输入/输出库。当然,其中一种选择是编写您自己的std::streambuf 子类,使用低级系统调用实现其功能,并适当地处理信号。您自己的实现将适当地阻止输入并通过将流缓冲区设置为失败状态(或者,可能模拟接收ENTER 键,嘿,这是您的节目)并返回来处理任何接收到的信号。

    【讨论】:

    • 虽然不影响底层点,但是C++11添加了函数std::atomic_signal_fence 可以和信号处理器同步。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-10
    • 2011-09-09
    • 2013-07-12
    • 1970-01-01
    相关资源
    最近更新 更多