When to check for EINTR and repeat the function call?

36.5k views Asked by At

I am programming a user application for a embedded Linux system, and I am using the common functions such as open, close, read, ioctl, etc. for the devices. Now, I read about EINTR, indicates that the function was interrupted by a signal, but I am not sure about the implications. In all the example programs I have, sometimes it is done, e.g. ioctl(), sometimes it is not done, e.g. read(). So, I am a little bit confused.

When do I preferably check for EINTR and repeat the function call?

4

There are 4 answers

10
Yann Droneaud On BEST ANSWER

See 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.

By default, you have the SA_RESTART behavior, so you don't have to worry about EINTR, if you don't play with signals.

0
Maxim Egorushkin On

Is your application event driven? (Meaning its main loop include select()/epoll_wait() call).

In an event driven application you can block all signals and only unblock them for the duration of pselect()/epoll_pwait() call. This way the rest of your code never have to deal with EINTR.

0
lobosch On

I had a similar problem when waiting for input from a named pipe with read().

I found an explanation and a useful macro for primitives in GNU libc documentation: TEMP_FAILURE_RETRY

Example:

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);
}
13
R.. GitHub STOP HELPING ICE On

I know this question is old but I think there's more to be said. To answer the specific question in the title: basically, never.

Aside from select and poll, EINTR can only happen if you've installed (either by mistake/not understanding how to use sigaction, or because you want to be able to interrupt blocking operations) interrupting signal handlers. Looping to retry when a function fails with EINTR just undoes that. Doing so is an old anti-pattern from the 80s and early to mid 90s when lots of operating systems were buggy and reportedly generated EINTR under non-conforming circumstances, but these bugs are long gone.

It is possible that, even in an application where you want to be able to interrupt things with signals, there is some code whose successful completion is so important that you can't treat EINTR as an error condition and return back to the caller without completing the operation. In such a circumstance, it might make sense to install a retry loop, but it's probably better to mask signals (at least the potentially-interrupting ones) during the operation and unmasks after it finishes.