1

如何在 C++ 中处理中断信号和调用析构函数有关?,但我的问题围绕着构建程序。

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

根据我的阅读,包括如果发出 SIGINT 或 SIGSTP,是否调用析构函数?, 的处理函数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 后关闭它?

4

1 回答 1

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;
}
于 2017-08-04T08:42:26.840 回答