Когда проверить EINTR и повторить вызов функции? - PullRequest
37 голосов
/ 10 февраля 2011

Я программирую пользовательское приложение для встроенной системы Linux и использую для устройств общие функции, такие как open, close, read, ioctl и т. Д.Теперь, я прочитал о EINTR, указывает, что функция была прервана сигналом, но я не уверен в последствиях.Во всех примерах программ, которые у меня есть, иногда это делается, например, ioctl (), иногда это не делается, например, read ().Итак, я немного запутался.

Когда мне желательно проверять EINTR и повторять вызов функции?

Ответы [ 4 ]

14 голосов
/ 10 февраля 2011

см. Sigaction: http://pubs.opengroup.org/onlinepubs/009695399/functions/sigaction.html

SA_RESTART
  This flag affects the behavior of interruptible functions; that is, those 
  specified to fail with errno set to EINTR. If set, and a function specified 
  as interruptible is interrupted by this signal, the function shall restart 
  and shall not fail with EINTR unless otherwise specified. If the flag is not 
  set, interruptible functions interrupted by this signal shall fail with errno 
  set to EINTR.

По умолчанию у вас есть поведение SA_RESTART, поэтому вам не нужно беспокоиться об EINTR, если вы не играете с сигналами.

4 голосов
/ 10 февраля 2011

Управляется ли событие вашего приложения?(Это означает, что его основной цикл включает select()/epoll_wait() вызов).

В приложении, управляемом событиями, вы можете блокировать все сигналы и разблокировать их только на время вызова pselect()/epoll_pwait().Таким образом, остальная часть вашего кода никогда не будет иметь дело с EINTR.

3 голосов
/ 10 февраля 2011

Эта ссылка имеет довольно хорошее объяснение.

http://www.ibm.com/developerworks/linux/library/l-reent.html

Ура!

1 голос
/ 12 февраля 2013

У меня была похожая проблема при ожидании ввода из именованного канала с помощью read ().

Я нашел объяснение и полезный макрос для примитивов в документации GNU libc : TEMP_FAILURE_RETRY

Пример:

TEMP_FAILURE_RETRY (read_return = read((int)example_fifo, buffer, (size_t)n));
if (read_return==-1){
    fprintf(stderr, "reader.c: read_fifo: read(): %s \n", strerror(errno));
    fflush(stderr);
}
...