A signal can arrive and be handled while an I/O primitive such as
read is waiting for an I/O device. If the signal
handler returns, the system faces the question: what should happen next?
POSIX specifies one approach: make the primitive fail right away. The
error code for this kind of failure is
EINTR. This is flexible,
but usually inconvenient. Typically, POSIX applications that use signal
handlers must check for
EINTR after each library function that
can return it, in order to try the call again. Often programmers forget
to check, which is a common source of error.
The GNU C Library provides a convenient way to retry a call after a
temporary failure, with the macro
This macro evaluates expression once, and examines its value as
long int. If the value equals
-1, that indicates a
errno should be set to show what kind of failure.
If it fails and reports error code
TEMP_FAILURE_RETRY evaluates it again, and over and over until
the result is not a temporary failure.
The value returned by
TEMP_FAILURE_RETRY is whatever value
EINTR entirely and provides a more convenient
approach: to restart the interrupted primitive, instead of making it
fail. If you choose this approach, you need not be concerned with
You can choose either approach with the GNU C Library. If you use
sigaction to establish a signal handler, you can specify how that
handler should behave. If you specify the
return from that handler will resume a primitive; otherwise, return from
that handler will cause
EINTR. See Flags for Sigaction.
Another way to specify the choice is with the
function. See BSD Signal Handling.
When you don’t specify with
a particular handler should do, it uses a default choice. The default
choice in the GNU C Library is to make primitives fail with
The description of each primitive affected by this issue
EINTR among the error codes it can return.
There is one situation where resumption never happens no matter which
choice you make: when a data-transfer function such as
write is interrupted by a signal after transferring part of the
data. In this case, the function returns the number of bytes already
transferred, indicating partial success.
This might at first appear to cause unreliable behavior on
record-oriented devices (including datagram sockets; see Datagrams),
where splitting one
write into two would read or
write two records. Actually, there is no problem, because interruption
after a partial transfer cannot happen on such devices; they always
transfer an entire record in one burst, with no waiting once data
transfer has started.