在 C++ 中捕获 SIGINT 并调用析构函数的程序结构
Program structure to catch SIGINT and call destructor in C++
与 How can I handle interrupt signal and call destructor in c++? 相关,但我的问题围绕着构建程序。
我正在编写一个将数据写出到 HDF5 文件的模拟程序。但是在程序中断的情况下,我希望正确关闭 HDF5,这样累积的数据仍然可读。我已经编写了一个包含 HDF5 文件句柄的 HDF5 编写器 class,如果调用了 class 的析构函数,则应该关闭 HDF5 文件。因此,在 Ctrl-C 中断程序的情况下,我想捕获 SIGINT,并调用析构函数。
根据我的阅读,包括Is destructor called if SIGINT or SIGSTP issued?,sigaction
的handler函数应该很简单,无非就是改个flag。这导致如下程序(从第二个 link 复制)...
#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
将 运行 我的模拟,直到满足指定的停止条件,这可能需要几个 minutes/hours。我如何设置我的程序来监视一些标志,以便它在及时收到 SIGINT 后关闭东西?
也许您可以在 run_simulation() 例程中放置一个循环而不是主循环。此例程中的循环等待上述 "global" volatile 原子变量。这将允许您的例程在自行关闭之前完成
// 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;
}
与 How can I handle interrupt signal and call destructor in c++? 相关,但我的问题围绕着构建程序。
我正在编写一个将数据写出到 HDF5 文件的模拟程序。但是在程序中断的情况下,我希望正确关闭 HDF5,这样累积的数据仍然可读。我已经编写了一个包含 HDF5 文件句柄的 HDF5 编写器 class,如果调用了 class 的析构函数,则应该关闭 HDF5 文件。因此,在 Ctrl-C 中断程序的情况下,我想捕获 SIGINT,并调用析构函数。
根据我的阅读,包括Is destructor called if SIGINT or SIGSTP issued?,sigaction
的handler函数应该很简单,无非就是改个flag。这导致如下程序(从第二个 link 复制)...
#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
将 运行 我的模拟,直到满足指定的停止条件,这可能需要几个 minutes/hours。我如何设置我的程序来监视一些标志,以便它在及时收到 SIGINT 后关闭东西?
也许您可以在 run_simulation() 例程中放置一个循环而不是主循环。此例程中的循环等待上述 "global" volatile 原子变量。这将允许您的例程在自行关闭之前完成
// 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;
}