2017-04-05 164 views
1

How can I handle interrupt signal and call destructor in c++?相关,但我的问题是围绕着构建一个程序。在C++中捕获SIGINT和调用析构函数的程序结构

我正在写一个模拟程序,将数据写入HDF5文件。但是在程序中断的情况下,我希望HDF5能够正确关闭,以便累积的数据仍然可读。我编写了一个HDF5编写器类,它包含HDF5文件的句柄,如果调用该类的析构函数,HDF5文件应该关闭。因此,在通过Ctrl-C程序中断的情况下,我想捕获SIGINT,并调用析构函数。

根据我的阅读,包括Is destructor called if SIGINT or SIGSTP issued?sigaction的处理函数应该非常简单,只不过是改变一个标志。这导致了如下内容(从第二个链接复制)程序...

#include <iostream> 
#include <signal.h> 
#include <unistd.h> 
#include <cstring> 
#include <atomic> 

std::atomic<bool> quit(false); // signal flag 

void got_signal(int) 
{ 
    quit.store(true); 
} 

class Foo 
{ 
public: 
    ~Foo() { std::cout << "destructor\n"; } 
}; 

int main(void) 
{ 
    struct sigaction sa; 
    memset(&sa, 0, sizeof(sa)); 
    sa.sa_handler = got_signal; 
    sigfillset(&sa.sa_mask); 
    sigaction(SIGINT,&sa,NULL); 

    Foo foo; // needs destruction before exit 
    while (true) 
    { 
     // do real work here... 
     sleep(1); 
     if(quit.load()) break; // exit normally after SIGINT 
    } 
    return 0; 
} 

您可以在程序结构中看到,while环路内部分应该是足够短,使得在国旗程序检查经常使用quit。但我的问题是我的程序结构更是这样的:

int main() 
{ 
    // set up variables 

    HDF5Writer writer(...); 

    run_simulation(&writer, [params]); 
} 

run_simulation将运行我的模拟,直到指定停止准则满足,这可能需要几分钟/小时。如何设置我的程序监视某个标志,以便在及时收到SIGINT后关闭它?

+0

之前完成你总是可以扔,像这样的例外(虽然它是不是真的便携式):http://stackoverflow.com/a/5861669/2097780 – refi64

+0

我然后可以把'run_simulation'放在一个try中,除了block来捕获异常?我只需要在linux上运行的东西 – bernie

+0

是!你也需要使用'-non-call-exceptions'来编译你的代码。 – refi64

回答

0

也许你可以在你的run_simulation()例程而不是主循环中放置一个循环。此例程中的循环等待前面提到的“全局”易失性原子变量。这将使你的日常以自行关闭

// included stuff 

// flag 
volatile sig_atomic_t no_signal = 1; 

void sig_handler(int) 
{ 
    --no_signal; 
} 

void run_simulation(...) 
{ 
    // Maybe you put stuff on heap 
    CMyClass* pMyObj = new CMyClass; 

    do // at least once 
    { 
     // Maybe some stack stuff 
     CMyClass oMyObj; // Dtor called when scope ends 

     // Here you could already check if the signal has occurred, 
     // to shut down in a timely manner 
     if (no_signal) 
      p_MyObj->do_stuff_that_takes_1_hour() 
     else 
      break; 

    } while (no_signal) 

    // clean up stuff 
    delete p_MyObj; 
    p_MyObj = nullptr; // if c++11 
} 

int Main() 
{ 
    // Register sighandler 

    // set up variables 

    HDF5Writer writer(...); 
    run_simulation(&writer, [params]); 

    return 0; 
} 
+1

谢谢。我想我的问题太开放了。我没有更新,但我最终在仿真循环中添加了信号标志的监视器 – bernie