2017-01-21 2 views
2

Мой первый пост здесь, извините, если что-то не соответствует правилам. Нужна консультация по проблеме в C.Можно ли изменить точку возврата обработчика сигнала?

Я использую обработчик сигналов (SIGALRM) с таймаутом на входе от пользователя (Stdin). Если пользователь не набирали ничего тогда:

  1. таймауту

  2. обработчик сигнала называется

  3. (ПРОБЛЕМА) -> он возвращается к той же линии до наступления тайм-аута.

ВАЖНО: я не могу использовать выбора и не может использовать опрос функции, потому что это механизм третьей стороны я использую и должны использовать свои методы. В конечном итоге они используют select, но это не просто, и мне просто нужно использовать их метод.

Проблема заключается в том: После возвращения из обработчика сигнала я "м еще„застряли“на той же линии, ожидая ввода я не могу использовать longjmp, не может вызвать другой метод, не может напечатать сообщение. пользователь не может использовать Гото все небезопасные от обработчика и создания ошибок

код выглядит примерно так:..

sa.sigaction(SIGALRM, &handler,Null): 
. 
. 
While(done! =1) 
{ 
    alarm(20); //20 seconds timeout started 
    If(ReadLineMethod()>0) //wait for successful input from stdin 
    { 
     If(inputErr ==1) 
     { 
      **here(for example) I want to print user that timeout  occured and return from the program (exit) ** 
      } 
    alarm(0); 
    done==1; 
    // Do stuff here 
    } 
} 



/* Rest of the program before exit */ 

это время для просить удельном пока он печатает это право или таймаут удаляет его.

void handler (int signum) 
{ 
inputErr==1;// global parameter 
} 

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

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

+0

Да. Вы можете использовать комбинацию 'setjmp()' и 'longjmp()'. – DyZ

+0

Почему бы не распечатать и не выйти из самой функции обработчика? Вы можете сделать это, если вы выйдете из программы. – user1952500

+0

Ну, вы можете прервать вызов 'read' через' siginterrupt (SIGALRM, 1) 'и проверить флаг отмены в ветви ошибки EINTR. Затем снова 'longjmp' также должен быть безопасным сигналом. Все становится сложно, если 'ReadLineMethod' не находится под вашим собственным контролем, хотя в этом случае вам может понадобиться какой-то болезненный взлом, например, закрытие стандартного дескриптора входного файла. – doynax

ответ

0

Используйте флаг, который поднимает обработчик. Условие печати с этим флагом. Вам нужно будет защитить этот флаг с помощью мьютекса.

+0

Где разместить кондиционирование? Поскольку обработчик возвращается к строке If (ReadLineMethod()> 0), на которой я застрял. – rozmanro

0

Если вам не разрешено переопределять ReadLineMethod(), чтобы быть более разумным, как об использовании потоков? Я не специалист по pthread, но вы, вероятно, могли бы настроить все так, чтобы ReadLineMethod происходил в одном потоке, а опрос на ошибку происходит в другом потоке. Там даже, кажется, функция pthread_cancel, которая может принудительно остановить читателя нить, если это необходимо: http://man7.org/linux/man-pages/man3/pthread_cancel.3.html

+1

У меня уже много потоков, лучше избегать использования большего количества потоков для этого. Спасибо. – rozmanro

0

Потому что у вас так много ограничений, один из способов, чтобы получить полный контроль над этой системой будет:

  1. Создать нить и запустить ReadLineMethod() в этой теме.
  2. Создайте еще один поток и используйте таймер в этой теме. Не используйте сигналы, но обнаруживайте, что время ожидания закончилось.
  3. Когда поток таймера понимает, что таймер запустил наш, позвольте ему убить поток в (1).
  4. Else, если ReadLineMethod() работает до конца, пусть поток таймера ничего не делает и не завершает.

Конечно, это извивается из-за требований. Если фундаментальное требование известно, могут быть лучшие альтернативы.

Смежные вопросы