Handle EWOULDBLOCK as EAGAIN. And add a comment explaining why
authorDan Gohman <gohman@apple.com>
Thu, 6 May 2010 01:27:36 +0000 (01:27 +0000)
committerDan Gohman <gohman@apple.com>
Thu, 6 May 2010 01:27:36 +0000 (01:27 +0000)
EAGAIN and EWOULDBLOCK are used here.

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

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@103153 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Support/raw_ostream.cpp

index f8ac65d7e136ae73e6f35ecbd1b56f2f18c4c73c..ad47cb6cf5e917f697d78d8850f388ebd3479780 100644 (file)
@@ -422,11 +422,30 @@ void raw_fd_ostream::write_impl(const char *Ptr, size_t Size) {
   assert(FD >= 0 && "File already closed.");
   pos += Size;
   ssize_t ret;
+
   do {
     ret = ::write(FD, Ptr, Size);
-  } while (ret < 0 && (errno == EAGAIN || errno == EINTR));
-  if (ret != (ssize_t) Size)
-    error_detected();
+
+    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();
+      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() {