通过信号唤醒std :: getline

时间:2017-09-29 12:13:51

标签: c++ signals stdin

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

std::getline()

为什么会这样?除了用户输入之外,我有没有机会唤醒#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()读取,这也是对信号的响应吗?

1 个答案:

答案 0 :(得分:1)

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

  

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

这和头文件的枚举是C ++库中信号引用的总和。信号是一种高度运行的特定于系统的功能,C ++库根本不包含这些功能。

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

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