How to handle EINTR (interrupted System Call)

后端 未结 1 1891
终归单人心
终归单人心 2020-12-14 05:35

My user-space application sometimes blocks after receiving an EINTR-Signal, somehow.

What I recorded with strace:

time(NULL)                                


        
相关标签:
1条回答
  • 2020-12-14 06:20

    The code which calls write (or other blocking operations) has to be aware of EINTR. If a signal occurs during a blocking operation, then the operation will either (a) return partial completion, or (b) return failure, do nothing, and set errno to EINTR.

    So, for an all-or-fail write operation which retries after interruptions, you'd do something like this:

    while(size > 0) {
        int written = write(filedes, buf, size);
        if (written == -1) {
            if (errno == EINTR) continue;
            return -1;
        }
        buf += written;
        size -= written;
    }
    return 0; // success
    

    Or for something a bit better behaved, which retries EINTR, writes as much as it can, and reports how much is written on failure (so the caller can decide whether and how to continue partial writes which fail for a reason other than interruption by signal):

    int total = 0;
    while(size > 0) {
        int written = write(filedes, buf, size);
        if (written == -1) {
            if (errno == EINTR) continue;
            return (total == 0) ? -1 : total;
        }
        buf += written;
        total += written;
        size -= written;
    }
    return total; // bytes written
    

    GNU has a non-standard TEMP_FAILURE_RETRY macro that might be of interest, although I can never find the docs for it when I want them. Including now.

    0 讨论(0)
提交回复
热议问题