Visual C++2015中的SIGINT处理程序重置
SIGINT handler reset in Visual C++ 2015
考虑以下测试程序
#include <csignal>
#include <iostream>
volatile std::sig_atomic_t signal_raised = 0;
void set_signal_raised(int signal) {
signal_raised = 1;
}
void check(std::sig_atomic_t expected) {
if (signal_raised != expected) {
std::cerr << signal_raised << " != " << expected << std::endl;
abort();
}
}
int main() {
using namespace std;
check(0);
std::signal(SIGINT, set_signal_raised);
check(0);
std::raise(SIGINT);
check(1);
signal_raised = 0;
check(0);
std::raise(SIGINT);
check(1);
cerr << "OK.n";
}
对于GCC和Clang,它输出"OK"。然而,对于Visual Studio 2015,它什么也不输出。
信号处理器在处理第一信号之后被重置。这可以通过添加来验证
auto prev = std::signal(SIGINT, set_signal_raised);
if (prev != set_signal_raised) {
std::cerr << "Unexpected handler." << std::endl;
abort();
}
到检查功能。这是允许和期望的吗?
信号处理的重置是Unix System V使用的行为。但是BSD(目前是glibc)并没有重置信号处理。POSIX标准允许任何一种行为。C标准没有规定是否允许"重置"。
来自signal(2)
:
在最初的UNIX系统中,当using signal()是通过传递信号调用的信号的处理将重置为SIG_DFL,并且系统没有阻止信号的进一步实例的传递。这是相当于用以下标志调用sigaction(2):
sa.sa_flags=sa_RESETHAND|sa_NODEFER;
系统V还为signal()提供了这些语义。这太糟糕了因为信号可能在处理程序具有重新建立自己的机会。此外相同的信号可能导致处理程序的递归调用。
因此,Visual studio似乎遵循System V的行为。
这是允许的还是预期的?
这是允许的,但肯定不可取。为此,POSIX引入了sigaction()
。如果您有sigaction()
,则使用它。否则,您只需要每次在信号处理程序中重新安装处理程序:
void set_signal_raised(int signal) {
std::signal(SIGINT, set_signal_raised);
signal_raised = 1;
}
相关文章:
- 获取日期异步信号安全吗?如果在信号处理程序中使用,它会导致死锁吗
- 如何在信号处理程序和普通函数中对全局变量进行互斥读写操作
- 为什么我的 IExtractIcon 处理程序没有被调用?
- 在遍历处理程序的向量时注册和注销处理程序
- 有可能在信号处理程序中设置promise吗
- 在信号处理程序中捕获C++未处理的异常并恢复应用程序
- 在C++程序中使用的迭代器中未处理的异常
- 有关图像处理应用程序的硬件和软件安全性的建议
- 通过安装信号处理程序关闭多线程应用程序
- QDateTime::toString() 在退出处理程序中使用时失败
- 如何在 WindowProc 处理程序中区分箭头键和数字键盘?
- async_write完成处理程序最早何时完成?
- C++事件系统 - 多态事件和事件处理程序
- 使用信号处理程序处理从 FIFO 接收的数据
- 使用独立的 c++ 程序处理用 C 编写的字符设备驱动程序
- C 程序处理两个文件,而不是一个文件
- 是什么让这个程序处理缓慢?(C++)
- QT 中的应用程序>处理消息?
- MongoDB C++驱动程序处理副本集连接故障
- 使用 OpenCV 程序处理多页 PDF