Handle EWOULDBLOCK as EAGAIN. And add a comment explaining why

EAGAIN and EWOULDBLOCK are used here.

Also, handle the case where a write call is interrupted after
some data has already been written.

llvm-svn: 103153
This commit is contained in:
Dan Gohman 2010-05-06 01:27:36 +00:00
parent 5fc1e951f6
commit 3a3eadef40

View File

@ -422,11 +422,30 @@ void raw_fd_ostream::write_impl(const char *Ptr, size_t Size) {
assert(FD >= 0 && "File already closed."); assert(FD >= 0 && "File already closed.");
pos += Size; pos += Size;
ssize_t ret; ssize_t ret;
do { do {
ret = ::write(FD, Ptr, Size); ret = ::write(FD, Ptr, Size);
} while (ret < 0 && (errno == EAGAIN || errno == EINTR));
if (ret != (ssize_t) Size) if (ret < 0) {
// If it's a recoverable error, swallow it and retry the write.
// EAGAIN and EWOULDBLOCK are not unambiguously recoverable, but
// some programs, such as bjam, assume that their child processes
// will treat them as if they are. If you don't want this code to
// spin, don't use O_NONBLOCK file descriptors with raw_ostream.
if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)
continue;
// Otherwise it's a non-recoverable error. Note it and quit.
error_detected(); error_detected();
break;
}
// The write may have written some or all of the data. Update the
// size and buffer pointer to reflect the remainder that needs
// to be written. If there are no bytes left, we're done.
Ptr += ret;
Size -= ret;
} while (Size > 0);
} }
void raw_fd_ostream::close() { void raw_fd_ostream::close() {