8

What is the recommended etiquette when it comes to EINTR in libraries?

I'm currently writing a function that does some file system tasks with the POSIX API, but a lot of the calls I use can potentially return EINTR. Additionally, the function can block under some circumstances. (For those interested, it implements a locking mechanism.)

In the interests of making this as general as possible, I would like to know what is the proper way to deal with an interrupted system call.

  • From most sources I've read, people typically retry the call and continue on with their business. However, I'm not sure that's the right thing to do here, since there may be legitimate reasons to interrupt my function given that it can take a significant amount of time. Furthermore, it means the EINTR would simply get swallowed by the function and the caller would lose any indication that it occurred.

  • My current strategy is to immediately abort the operation if I receive EINTR and notify the caller about it. This way, the caller can decide if they want to retry my function, right? (Or perhaps my understanding of signals is flawed?)

  • 1
    What is your library doing? I tend to approve your current strategy (of aborting operation on EINTR and reporting that to the caller), but it may depend upon what is your library doing... – Basile Starynkevitch Dec 31 '14 at 14:18
  • 1
    In this case it's performing a locking operation. – Rufflewind Dec 31 '14 at 14:29
4

Signals in Unix

when some other process sends your process Signal, your program will stop what it’s doing...

1) Run the handler code you wrote. You have no idea what your program might be doing when the signal arrives. That’s the idea with signals, they can be completely asynchronous.

2) When the signal handler is done, it typically just does a return, and your program continues where it left off, as if nothing had happened.

Found some useful info in Richard Stevens

A characteristic of earlier UNIX systems is that if a process caught a signal while the process was blocked in a "slow" system call, the system call was interrupted. The system call returned an error and errno was set to EINTR. This was done under the assumption that since a signal occurred and the process caught it, there is a good chance that something has happened that should wake up the blocked system call.

POSIX.1 semantics for interrupted reads and writes changed with the 2001 version of the standard. Earlier versions gave implementations a choice for how to deal with reads and writes that have processed partial amounts of data. If read has received and transferred data to an application's buffer, but has not yet received all that the application requested and is then interrupted, the operating system could either fail the system call with errno set to EINTR or allow the system call to succeed, returning the partial amount of data received. Similarly, if write is interrupted after transferring some of the data in an application's buffer, the operation system could either fail the system call with errno set to EINTR or allow the system call to succeed, returning the partial amount of data written. Historically, implementations derived from System V fail the system call, whereas BSD-derived implementations return partial success. With the 2001 version of the POSIX.1 standard, the BSD-style semantics are required.

The problem with interrupted system calls is that we now have to handle the error return explicitly. The typical code sequence (assuming a read operation and assuming that we want to restart the read even if it's interrupted) would be

again:
    if ((n = read(fd, buf, BUFFSIZE)) < 0) {
        if (errno == EINTR)
            goto again;     /* just an interrupted system call */
        /* handle other errors */
    }

To prevent applications from having to handle interrupted system calls, 4.2BSD introduced the automatic restarting of certain interrupted system calls.

  • 2
    This doesn't answer the question. which was how libraries should approach the problem. If I know that I want to ignore EINTR in certain operations, I can do it with this call retry (goto again). But as a library developer, I don't know whether this is what my library user wants. – Messa Jul 22 '15 at 8:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.