6

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 ?

Yu Hao
  • 119,891
  • 44
  • 235
  • 294
  • 1
    In the UNIX Hater's Handbook, there's an anecdote according to which it *should*, but the makers of UNIX and associated standards instead chose to dump this on the user's lap because it made the OS easier to implement. – Medinoc Feb 26 '14 at 10:26
  • Note: close() is not a library function, but a (wrapper around a) system call. System calls can fail. (because of bad arguments, resource shortage, (assumed) races/conflicts, ...) Automatic restart is not always an option, in some cases the caller should take action itself. – wildplasser Feb 26 '14 at 10:49

1 Answers1

7

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.

nos
  • 223,662
  • 58
  • 417
  • 506