Обадете се на оператор на сигнали, но все още игнорирайте сигнала (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;

}

Проблемът ми е, че моят манипулатор на сигнали е извикан, но програмата ми все още се прекратява. Не съм сигурен как да кажа на манипулатора на сигнали да се върне към main.


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
Това е мой проблем, аз съм умен. =P - 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