Вызвать обработчик сигнала, но по-прежнему игнорировать сигнал (Posix, C)

Я хочу поймать сигнал, установить глобальное сообщение о том, что сигнал был пойман, а затем вернуться к послесловию основного цикла. Вот мой код.

int main(int mainargc, char **mainargv)
{
.
.
.
    sig_handler.sa_handler = sigint_handler;
    sigemptyset(&sig_handler.sa_mask);
    sig_handler.sa_flags = 0;
    sigaction(SIGINT, &sig_handler, NULL);
.
.
. 
    while(1)
    {
    //main loop
    }
}

void sigint_handler(int signal)
{
    int saved_error = errno;

    g_sigint_happened = 1;

    //TODO -- send sigint to children

    errno = saved_error;

}

Моя проблема в том, что мой обработчик сигналов вызывается, но моя программа все еще завершается. Я не уверен, как сказать обработчику сигнала вернуться к основному.


person AlexLordThorsen    schedule 26.11.2012    source источник
comment
Обычно выполнение возобновляется после обработки сигнала, если только рассматриваемый сигнал не был SIGSEGV. Вы уверены, что SIGINT - это сигнал, который получает ваша программа?   -  person Alexey Feldgendler    schedule 26.11.2012
comment
Нет, я не уверен. Вот как выглядит мой ввод в мою программу. Я нажимаю ^C и вижу: «Прерванный системный вызов».   -  person AlexLordThorsen    schedule 26.11.2012
comment
«Прерванный системный вызов» — это не признак того, что ваша программа умирает от сигнала. Смотрите ответ @caf ниже.   -  person Alexey Feldgendler    schedule 26.11.2012


Ответы (1)


Вам не нужно делать ничего особенного, чтобы возобновить выполнение после вызова обработчика сигнала.

Ваша проблема может заключаться в том, что сигнал прервал какой-то блокирующий системный вызов в main, что приведет к возврату ошибки с errno, установленным на EINTR. Если вы специально не проверяете это и не перезапускаете системный вызов, то, вероятно, это просто происходит из-за общей ошибки, из-за которой ваш процесс завершается.

person caf    schedule 26.11.2012
comment
Это моя проблема, я умный. =П - person AlexLordThorsen; 26.11.2012
comment
Вы должны просто добавить SA_RESTART к sa_flags. Нет необходимости иметь дело с EINTR и перезапуском вручную в современных программах, если вы на самом деле не хотите прерывания (что редко полезно; даже в ситуациях, когда это теоретически может быть полезно, у него есть условия гонки, которые побеждают цель). - person R.. GitHub STOP HELPING ICE; 26.11.2012
comment
@R.: SA_RESTART не применяется к каждому системному вызову, например, к спящим вызовам и мультиплексированию файловых дескрипторов. - person caf; 26.11.2012
comment
Да, для сна это проблема. Для select/poll довольно неважно, что они возвращаются раньше, так как обычно вы все равно будете вызывать их в цикле и каждый раз проверять, какие дескрипторы готовы. - person R.. GitHub STOP HELPING ICE; 26.11.2012
comment
@R.: Это не так уж неважно, если вы рассматриваете любой возврат ошибки как фатальную ошибку, что и делал здесь OP (хотя и с read(), где SA_RESTART эффективно). - person caf; 27.11.2012