Вызывается ли деструктор, если выдается SIGINT или SIGSTP? - PullRequest
33 голосов
/ 22 ноября 2010

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

Ответы [ 3 ]

30 голосов
/ 23 ноября 2010

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

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

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

#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, вы должны увидеть слово «деструктор». Помните, что ваши функции-обработчики сигналов (got_signal) редко должны выполнять какую-либо работу, кроме установки флага и тихого возврата, если вы действительно не знаете, что делаете.

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

9 голосов
/ 22 ноября 2010

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

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

7 голосов
/ 22 ноября 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.

...