Структура программы для перехвата SIGINT и вызова деструктора в переполнении стека

Относится к Как я могу обработать сигнал прерывания и вызвать деструктор в 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?

1

Решение

Возможно, вы могли бы поместить цикл в подпрограмму 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;
}
0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]