I am going through the book "UNIX Systems Programming", and came across the below point.
It is good practice to check for EINTR
error code whenever a C library functions are called (say close()
) because the library functions can fail if any signal is received by the process. If EINTR
error has occurred, the corresponding C library call should be restarted.
while ((close(fd) == -1) && errno == EINTR); // close is restarted if it fails with EINTR error.
Question: Why the library function should fail if it gets a signal ? When a signal is received, the corresponding handler is called. After the completion of the handler can't the library functions continue from the point it stopped ?
The sigaction() function supersedes the signal() interface, and should be the preferred usage. In particular, sigaction() and signal() must not be used in the same process to control the same signal.
...the signal handler calls any function in the standard library other than the abort function, the _Exit function, the quick_exit function, or the signal function with the first argument equal to the signal number corresponding to the signal that caused the invocation of the handler.
(Two signals, SIGKILL and SIGSTOP , cannot be blocked. These signals also cannot be handled and, therefore, always cause their default actions.)
The signal() function does not (necessarily) block other signals from arriving while the current handler is executing; sigaction() can block other signals until the current handler returns. The signal() function (usually) resets the signal action back to SIG_DFL (default) for almost all signals.
Why the library function should fail if it gets a Signal ?
Because that's how it's designed, and the goal is that if a signal arrives while you are stuck in a blocking system call, the system call returns, and you have a chance to act on the signal.
However, this has traditionally been implemented in many variants on different platforms.
After the completion of the handler can't the library functions continue from the point it stoped ?
Absolutely. If you want this behavior, you can set the SA_RESTART
flag when you install a signal handler with sigaction().
Note, even with the SA_RESTART flag, there are still some system calls that are not automatically restarted. For Linux, you can see a list of which calls in the "Interruption of system calls and library functions by signal handlers" paragraph in the signal(7) man page . (If anyone knows a similar list defined by posix, I'd be grateful).
If you install a signal handler using signal() instead of sigaction()
, it varies among unix variants whether system calls are automatically restarted or not. SySV derived platform typically does not restart system calls, while BSD dervied platform does.
while ((close(fd) == -1) && errno == EINTR); // close is restarted if it fails with EINTR error.
This is actually quite dangerouos. If close() fails with EINTR, the state of the file descriptor is unknown, meaning if the file descriptor really was closed, you risk a race condition that closes another unrelated file descriptor. This is considered a bug in the posix specification.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With