问题描述
我的代码是这样的:
#include <iostream>
#include <signal.h>
#include <cstdlib>
void handler(int) {
std::cout << "will exit..." << std::endl;
exit(0);
}
class A {
public:
A() {std::cout << "constructor" << std::endl;}
~A() {std::cout << "destructor" << std::endl;}
};
int main(void) {
signal(SIGINT, &handler);
A a;
for (;;);
return 0;
}
当我按Ctrl-C时,它会打印:
When I pressed Ctrl-C, it printed:
constructor
^Cwill exit...
没有打印析构函数。
那么,如何才能干净地退出?
There is no "destructor" printed.So, how can I exit cleanly?
推荐答案
遇到困难。您编写的代码已经具有未定义的
行为;您不得在信号处理程序中输出到流;
,您也不能拨打退出
。 (我在这里将
的断言基于Posix标准。在纯C ++中,
所要做的全部工作就是赋给 sig_atomic_t
类型。)
With difficulty. Already, the code you've written has undefinedbehavior; you're not allowed to output to a stream in a signal handler;for that matter, you're not allowed to call exit
either. (I'm basingmy assertions here on the Posix standard. In pure C++, all you'reallowed to do is assign to a variable of sig_atomic_t
type.)
在类似代码的简单情况下,您可以执行以下操作:
In a simple case like your code, you could do something like:
sig_atomic_t stopFlag = 0;
void
handler( int )
{
stopFlag = 1;
}
int
main()
{
signal( SIGINT, &handler );
A a;
while ( stopFlag == 0 ) {
}
std::cout << "will exit..." << std::endl;
return 0;
}
根据应用程序的不同,您可能可以执行类似的操作,
在适当的位置检查 stopFlag
。但是通常,如果您
尝试此操作,则会出现竞争状况:在
开始进行可互换的系统调用之前,先检查 stopFlag
,然后再进行调用;信号
在支票和通话之间到达,您进行通话,而不会中断
。 (我已经使用了这种技术,但是在
唯一可中断的系统调用是套接字读取中,且
的超时时间非常短。)
Depending on the application, you may be able to do something like this,checking the stopFlag
at appropriate places. But generally, if youtry this, there will be race conditions: you check stopFlag
beforestarting an interuptable system call, then do the call; the signalarrives between the check and the call, you do the call, and it isn'tinterrupted. (I've used this technique, but in an application where theonly interruptable system call was a socket read with a very shorttimeout.)
通常,至少在Posix下,您将不得不创建一个信号
处理线程;然后可以使用它彻底关闭所有
个其他线程。基本上,您首先需要设置信号掩码以阻止
所有信号,然后在信号处理线程中将其启动后将其设置为
接受您感兴趣的信号并调用 sigwait()
。但是,此
意味着您需要执行
干净关闭线程的所有常规操作:信号处理线程必须了解
关于所有其他线程的信息,调用 pthread_cancel
等,您就是
编译器必须生成正确的代码来处理 pthread_cancel
,或者
您需要开发其他方法来确保正确通知所有线程
。 (今天,人们希望所有的编译器都能正确地处理
pthread_cancel
。但是人们永远不知道;这样做有
很大的运行时间开销,而且不是通常需要。)
Typically, at least under Posix, you'll end up having to create a signalhandling thread; this can then be used to cleanly shut down all of theother threads. Basically, you start by setting the signal mask to blockall signals, then in the signal handling thread, once started, set it toaccept the signals you're interested in and call sigwait()
. Thisimplies, however, that you do all of the usual actions necessary for aclean shutdown of the threads: the signal handling thread has to knowabout all other threads, call pthread_cancel
on them, etc., and you'recompiler has to generate the correct code to handle pthread_cancel
, oryou need to develop some other means of ensuring that all threads arecorrectly notified. (One would hope, today, that all compilers handlepthread_cancel
correctly. But one never knows; doing so hassignificant runtime cost, and is not usually needed.)
这篇关于如何在C ++中处理中断信号并调用析构函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!