如何在C ++中处理中断信号并调用析构函数? [英] How can I handle interrupt signal and call destructor in c++?

查看:273
本文介绍了如何在C ++中处理中断信号并调用析构函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


可能重复:

我的代码是这样的:

#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 undefined behavior; 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 basing my assertions here on the Posix standard. In pure C++, all you're allowed 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 you try this, there will be race conditions: you check stopFlag before starting an interuptable system call, then do the call; the signal arrives between the check and the call, you do the call, and it isn't interrupted. (I've used this technique, but in an application where the only interruptable system call was a socket read with a very short timeout.)

通常,至少在Posix下,您将不得不创建一个信号
处理线程;然后可以使用它彻底关闭所有
个其他线程。基本上,您首先需要设置信号掩码以阻止
所有信号,然后在信号处理线程中将其启动后将其设置为
接受您感兴趣的信号并调用 sigwait()。但是,此
意味着您需要执行
干净关闭线程的所有常规操作:信号处理线程必须了解
关于所有其他线程的信息,调用 pthread_cancel 等,您就是
编译器必须生成正确的代码来处理 pthread_cancel ,或者
您需要开发其他方法来确保正确通知所有线程
。 (今天,人们希望所有的编译器都能正确地处理
pthread_cancel 。但是人们永远不知道;这样做有
很大的运行时间开销,而且不是通常需要。)

Typically, at least under Posix, you'll end up having to create a signal handling thread; this can then be used to cleanly shut down all of the other threads. Basically, you start by setting the signal mask to block all signals, then in the signal handling thread, once started, set it to accept the signals you're interested in and call sigwait(). This implies, however, that you do all of the usual actions necessary for a clean shutdown of the threads: the signal handling thread has to know about all other threads, call pthread_cancel on them, etc., and you're compiler has to generate the correct code to handle pthread_cancel, or you need to develop some other means of ensuring that all threads are correctly notified. (One would hope, today, that all compilers handle pthread_cancel correctly. But one never knows; doing so has significant runtime cost, and is not usually needed.)

这篇关于如何在C ++中处理中断信号并调用析构函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆