Вызывается ли деструктор, если выдается SIGINT или SIGSTP?

У меня есть класс с определяемым пользователем деструктором. Если класс был создан изначально, а затем выдается сигнал SIGINT (с использованием CTRL+C в unix) во время работы программы, будет ли вызван деструктор? Как ведет себя SIGSTP (CTRL + Z в unix)?


person SkypeMeSM    schedule 22.11.2010    source источник


Ответы (3)


Нет, по умолчанию большинство сигналов вызывают немедленный аварийный выход из вашей программы.

Однако вы можете легко изменить поведение по умолчанию для большинства сигналов.

Этот код показывает, как заставить сигнал выйти из вашей программы в обычном режиме, включая вызов всех обычных деструкторов:

#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;
}

Если вы запустите эту программу и нажмете control-C, вы должны увидеть напечатанное слово «destructor». Имейте в виду, что ваши функции обработчика сигналов (got_signal) редко должны выполнять какую-либо работу, кроме установки флага и тихого возврата, если вы действительно не знаете, что делаете.

Большинство сигналов можно перехватить, как показано выше, но не SIGKILL, вы не можете его контролировать, потому что SIGKILL — это последний метод уничтожения неконтролируемого процесса, а не SIGSTOP, который позволяет пользователю заморозить процесс в холодном состоянии. Обратите внимание, что вы можете поймать SIGTSTP (control-Z), если хотите, но вам это не нужно, если вас интересует только поведение деструктора, потому что в конечном итоге после control-Z процесс будет разбужен, продолжит работу и завершится нормально со всеми действующими деструкторами.

person Shawn Yarbrough    schedule 22.11.2010
comment
IIRC, правильный тип quit должен быть volatile std::sig_atomic_t. Это UB использовать bool для этой цели. - person MSalters; 23.11.2010
comment
@MSalters: Верно, я должен был включить вызов sigfillset() перед sigaction(), что, вероятно, было бы даже лучше, чем sig_atomic_t. Использование bool более привычно и совершенно безопасно, когда дополнительные сигналы заблокированы от прерывания обработчика сигналов. Отредактировал мой пример кода, спасибо. - person Shawn Yarbrough; 23.11.2010
comment
На самом деле я получаю сообщение об ошибке с этим кодом: use of deleted function для строки quit = false. Вы должны сделать quit(false) вместо quit = false. Также стоит отметить, что этот код не работает в Windows; вы должны использовать SetConsoleCtrlHandler(). - person Timmmm; 03.02.2016

Если вы сами не обрабатываете эти сигналы, то нет, деструкторы не вызываются. Однако операционная система вернет все ресурсы, использованные вашей программой, когда она завершится.

Если вы хотите самостоятельно обрабатывать сигналы, рассмотрите возможность использования стандартной библиотечной функции sigaction.

person pr1268    schedule 22.11.2010
comment
Восстановление ресурсов, принадлежащих ОС. Внутри приложения есть другие другие ресурсы, и они обычно упакованы таким образом, что требуется их правильное закрытие (в противном случае вы получите поврежденные ресурсы (например, файл, который не завершен должным образом)). - person Martin York; 23.11.2010

Давай попробуем:

#include <stdio.h>
#include <unistd.h>

class Foo {
public:
  Foo() {};
  ~Foo() { printf("Yay!\n"); }
} bar;

int main(int argc, char **argv) {
  sleep(5);
}

А потом:

$ g++ -o test ./test.cc 
$ ./test 
^C
$ ./test 
Yay!

Так что, боюсь, нет, вам придется его поймать.

Что касается SIGSTOP, его нельзя перехватить, и процесс приостанавливается до тех пор, пока не будет отправлено SIGCONT.

person Stéphan Kochen    schedule 22.11.2010