Related to How can I handle interrupt signal and call destructor in c++?, but my question revolves around structuring a program.
I am writing a simulation program that writes data out to HDF5 file. But in case of program interruption, I'd like the HDF5 to be closed properly such that the accumulated data is still readable. I've written an HDF5 writer class that contains the handles to the HDF5 file, and if the destructor of that class is called, the HDF5 file should get closed. Hence, in the event of program interruption by Ctrl-C, I'd like to catch the SIGINT, and invoke the destructor.
According to my reading, including Is destructor called if SIGINT or SIGSTP issued?, the handler function for sigaction
should be very simple, nothing more than changing a flag. This leads to a program like the following (copied from the second 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;
}
You can see in the program structure that part within the while
loop should be sufficiently short such that the program checks on the flag quit
frequently. But my trouble is my program is structured more like this:
int main()
{
// set up variables
HDF5Writer writer(...);
run_simulation(&writer, [params]);
}
run_simulation
will run my simulation until specified stop criteria are fulfilled, which can take several minutes/hours. How do I setup my program to be monitoring some flag so that it shuts things down after receiving SIGINT in a timely manner?