Ответ 1
Нет, по умолчанию большинство сигналов вызывают немедленный ненормальный выход вашей программы.
Однако вы можете легко изменить поведение по умолчанию для большинства сигналов.
Этот код показывает, как заставить сигнал нормально выходить из вашей программы, включая вызов всех обычных деструкторов:
#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;
}
Если вы запустите эту программу и нажмите Ctrl-C, вы увидите сообщение "destructor". Имейте в виду, что функции обработчика сигнала (got_signal) должны редко выполнять какую-либо работу, кроме установки флага и возвращения тихо, если вы действительно не знаете, что делаете.
Большинство сигналов улавливаются, как показано выше, но не SIGKILL, вы не контролируете его, потому что SIGKILL - это метод последней остановки для уничтожения процесса убегания, а не SIGSTOP, который позволяет пользователю заморозить процесс холода. Обратите внимание, что вы можете поймать SIGTSTP (control-Z), если это необходимо, но вам не нужно, если ваш единственный интерес к сигналам является деструкторным поведением, потому что, в конце концов, после управления Z процесс будет разбужен, будет продолжаться, и будет нормально работать со всеми деструкторами, действующими.