sigset: игнорирование ctrl-c в Unix - PullRequest
       0

sigset: игнорирование ctrl-c в Unix

3 голосов
/ 08 сентября 2010

Я пытаюсь заставить мою программу игнорировать Ctrl + C в Unix, который, кажется, работает, проблема в том, что она продолжает писать "Ошибка синтаксиса".Вот код

extern "C" void ignore( int sig )
{            
    fprintf( stderr, "\n"); // Print a new line
    // This function does nothing except ignore ctrl-c
}

int main()
{           
    // For ctrl-c
    sigset( SIGINT, ignore );

    while (1) {
        getUserInput();
    }      

    return 0;
}

Каждый раз, когда я нажимаю Ctrl + C , он снова запускается через getUserInput, что является ожидаемым поведением, но пишет «Синтаксическая ошибка»также.Я проверил, и функция «ignore» запускается, и после того, как она была выполнена, она печатает сообщение об ошибке, я не знаю, почему.

У кого-нибудь есть какие-либо подсказки, пожалуйста?

Большое спасибо,

Джари

Ответы [ 4 ]

8 голосов
/ 08 сентября 2010

Не использовать sigset(). Хотя это и есть в POSIX 2008, оно помечено как устаревшее и небезопасное в многопоточных программах.

Затем у вас есть выбор между signal(), который благословлен ISO C, но имеет некоторые нежелательные характеристики, и sigaction(), который является предпочтительным решением в системах POSIX.

Одним из ключевых моментов при обработке сигналов является обеспечение того, что вы не перехватываете любые сигналы, которые игнорируются при входе в программу - если вы не знаете что-то, что вызывающий не может (например, вам нужно перехватывать сигналы SIGCHLD для мертвых детей) .

Это приводит к стандартным формулировкам, проповедуемым с незапамятных времен, для signal():

if (signal(SIGINT, SIG_IGN) != SIG_IGN)
    signal(SIGINT, ignore);

Или, для sigaction():

struct sigaction new_sa;
struct sigaction old_sa;
sigfillset(&new_sa.sa_mask);
new_sa.sa_handler = SIG_IGN;
new_sa.sa_flags = 0;

if (sigaction(SIGINT, &new_sa, &old_sa) == 0 && old_sa.sa_handler != SIG_IGN)
{
    new_sa.sa_handler = ignore;
    sigaction(SIGINT, &new_sa, 0);
}

Поскольку вы не показываете нам функцию getUserInput(), мы не можем предсказать, почему вы видите «Ошибка синтаксиса». Однако, если у вас есть грамматика в работе, вполне возможно, что ваше чтение не возвращает действительные данные, и анализатор недоволен тем, что осталось в буфере для его обработки.

5 голосов
/ 08 сентября 2010

(Примечание: для большей переносимости вам, вероятно, следует использовать signal() (стандартная библиотека C) или sigaction() (POSIX) вместо sigset(), но я не думаю, что здесь проблема.)

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

например, возможно, вы вызвали системный вызов read для сбоя сEINTR.Я подозреваю, что реальная проблема заключается в том, что некоторый код внутри getUserInput() не обрабатывает этот случай ошибки.

Вы можете полностью игнорировать сигнал, установив обработчику специальное значение SIG_IGN, которое должно работать с любым изsigset(), signal() или sigaction().

1 голос
/ 08 сентября 2010

ignore() делает больше, чем ничего.

Когда вы запускаете этот код в UNIX, SIGINT доставляется асинхронно в том же потоке, который выполняет getUserInput(). Если SIGINT прибывает, когда getUserInput() обращается к stderr, поведение не определено, потому что fprintf() обычно не предназначен для повторного входа. (Тем не менее, поведение может включать искаженный и / или повторный вывод. Ваша программа печатала «Ошибка синтаксиса» до того, как SIGINT была доставлена?) CERT и GNU libc имеют еще немного информации об этом.

Если вы выполняете этот код на Win32, SIGINT будет доставляться асинхронно в отдельном потоке .

1 голос
/ 08 сентября 2010

Сообщение «Синтаксическая ошибка» должно поступать из функции getUserInput (или чего-то, что она вызывает, конечно) - вы могли бы выяснить, распечатав ли эта функция то, что она получает и почему она жалуется.

Обратите внимание, что каноническим способом игнорирования сигнала является использование предопределенного SIG_IGN в качестве обработчика сигнала. например sigset(SIGINT, SIG_IGN)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...