#c #signals #sigint
#c #сигналы #sigint
Вопрос:
Итак, вот мой код:
void sigHandle(int sig)
{
signal(SIGINT, sigHandle); //Is this line necessairy?
cout<<"Signal: "<<sig<<endl;
}
int main(){
signal(SIGINT, sigHandle);
while(true){ //Supposed to loop until user exits.
//rest of my code
}
}
Теперь я понимаю signal(), что при получении команды SIGINT (Ctrl C верно?) Моя функция sigHandle должна вызываться с целым значением 2 (номер SIGINT), метод должен выполняться, и программа НЕ должна завершаться.
Все, что я хотел бы сделать, это просто напечатать номер сигнала и двигаться дальше, однако после распечатки «Signal: 2» он завершается.
(В конечном итоге я должен обработать первые 32 прерывания, но я решилCtrl, что C будет самым сложным, поэтому я начинаю здесь.)
В main, если я делаю signal(SIGINT, SIG_IGN); он правильно игнорирует сигнал и не завершается, но теперь у меня нет способа узнать, получил ли я прерывание SIGINT.
Ранее я играл со структурой sigaction, но я не мог найти никакой реальной всеобъемлющей документации по ней, поэтому я решил использовать только «сырую» обработку сигналов.
Это был мой код sigaction (та же проблема, что и выше):
struct sigaction action;
action.sa_handler = sigHandle;
sigemptyset(amp;action.sa_mask);
action.sa_flags = 0;
sigaction(SIGINT, amp;action, 0);
Спасибо за вашу помощь!
Редактировать
ИТАК, после многих, многих, многих часов хмурого просмотра справочных страниц и Интернета я столкнулся с (очень) гетто-решением, включающим сохранение стека до бесконечного цикла, затем, когда приходит прерывание, делаю то, что мне нужно сделать, затем перенастраиваю стек туда, где он был, и вызываюкоманда sigrelse() для переустановки любых состояний, которые могли быть изменены и не загружены повторно.
Я понимаю, что это не самое элегантное / эффективное / или даже социально приемлемое решение этой проблемы, но оно работает, и, насколько я могу судить, я нигде не пропускаю память, так что все хорошо…
Я все еще ищу решение этой проблемы, и я рассматриваю свои махинации с повторной настройкой стека только как временное решение…
Спасибо!
Комментарии:
1.
signal(2)
использование устарело, вы должны использоватьsigaction(2)
. Обратитесь к своей локальной справочной странице .
Ответ №1:
Также обратите внимание, что вы не должны вызывать stdio (или другие нереентерабельные функции) в обработчиках сигналов. (ваш обработчик сигнала может быть вызван в середине malloc или его эквивалента на C )
Ответ №2:
Это не так. Вы просто заменяете дескрипторы SIGINT той же функцией. Как ваша программа выполняет ожидание?
Если у вас есть что-то вроде:
int main
{
// ...
int r = read(fd, amp;buff, read_size); // your program hangs here, waiting for the data.
// but if signal occurred during this period of time
// read will return immediately, and r may != read_size
return 0; // then it will go straight to return.
}
Комментарии:
1. Я где-то читал, что в определенных средах unix команда signal() повторно устанавливается на значение по умолчанию после каждого вызова. Однако я знаю, что эта строка не является причиной моей проблемы, потому что я добавил ее позже, надеясь, что это решит мою проблему.
2. сигналы прерывают системные вызовы, и чтение немедленно возвращается. это может быть причиной завершения работы вашей программы. linux.die.net/man/2/read — «… или потому, что чтение() было прервано сигналом …»
3. Даже если внутри sigHandle ничего нет, программа все равно завершается, чего не должно быть. (правильно?)
4. ДА. Это происходит не потому, что что-то находится внутри обработчика, а из-за того, что произошел сигнал. Я отредактировал свой пост.
5. Ах, хорошо. Я понимаю. Все входные данные, которые я получаю от пользователя, происходят внутри цикла while (true). Итак, используя ваш пример, если вы вставили команду read в цикл while (true), даже если read возвращается сразу после сигнала, не следует ли ему просто вернуться и снова зависнуть?