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.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…