- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
考虑下面的测试程序
#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)
:
POSIX.1 solved the portability mess by specifying sigaction(2), which provides explicit control of the semantics when a signal handler is invoked; use that interface instead of signal().
In the original UNIX systems, when a handler that was established using signal() was invoked by the delivery of a signal, the disposition of the signal would be reset to SIG_DFL, and the system did not block delivery of further instances of the signal. This is equivalent to calling sigaction(2) with the following flags:
sa.sa_flags = SA_RESETHAND | SA_NODEFER;
System V also provides these semantics for signal(). This was bad because the signal might be delivered again before the handler had a chance to reestablish itself. Furthermore, rapid deliveries of the same signal could result in recursive invocations of the handler.
因此,Visual Studio 似乎遵循了 System V 的行为。
Is this allowed and expected?
这是允许的,但绝对不希望这样做。为此,POSIX 引入了 sigaction()
.如果你有 sigaction()
然后使用它。否则,您只需每次在信号处理程序中重新安装处理程序:
void set_signal_raised(int signal) {
std::signal(SIGINT, set_signal_raised);
signal_raised = 1;
}
关于c++ - Visual C++ 2015 中的 SIGINT 处理程序重置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41552081/
我是一名优秀的程序员,十分优秀!