Recognize EMSGSIZE as non-fatal on OS X.

BUG=29225
TEST=PageCyclerTest.Intl2File test should succeed.

Review URL: http://codereview.chromium.org/460102

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@34056 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/test/page_cycler/page_cycler_test.cc b/chrome/test/page_cycler/page_cycler_test.cc
index 845391a..099beab 100644
--- a/chrome/test/page_cycler/page_cycler_test.cc
+++ b/chrome/test/page_cycler/page_cycler_test.cc
@@ -184,7 +184,8 @@
     test_path = test_path.Append(FILE_PATH_LITERAL("data"));
     test_path = test_path.Append(FILE_PATH_LITERAL("page_cycler"));
     test_path = test_path.AppendASCII(name);
-    ASSERT_TRUE(file_util::PathExists(test_path)) << "Missing test data";
+    ASSERT_TRUE(file_util::PathExists(test_path)) << "Missing test data"
+                                                  << test_path.value();
 
 #if defined(OS_MACOSX)
     PopulateUBC(test_path);
diff --git a/ipc/ipc_channel_posix.cc b/ipc/ipc_channel_posix.cc
index 0d178d5..545ad0c 100644
--- a/ipc/ipc_channel_posix.cc
+++ b/ipc/ipc_channel_posix.cc
@@ -241,6 +241,25 @@
   return true;
 }
 
+bool SocketWriteErrorIsRecoverable() {
+#if defined(OS_MACOSX)
+  // On OS X if sendmsg() is trying to send fds between processes and there
+  // isn't enough room in the output buffer to send the fd structure over
+  // atomically then EMSGSIZE is returned.
+  //
+  // EMSGSIZE presents a problem since the system APIs can only call us when
+  // there's room in the socket buffer and not when there is "enough" room.
+  //
+  // The current behavior is to return to the event loop when EMSGSIZE is
+  // received and hopefull service another FD.  This is however still
+  // technically a busy wait since the event loop will call us right back until
+  // the receiver has read enough data to allow passing the FD over atomically.
+  return errno == EAGAIN || errno == EMSGSIZE;
+#else
+  return errno == EAGAIN;
+#endif
+}
+
 }  // namespace
 //------------------------------------------------------------------------------
 
@@ -815,7 +834,7 @@
     if (bytes_written > 0)
       msg->file_descriptor_set()->CommitAll();
 
-    if (bytes_written < 0 && errno != EAGAIN) {
+    if (bytes_written < 0 && !SocketWriteErrorIsRecoverable()) {
 #if defined(OS_MACOSX)
       // On OSX writing to a pipe with no listener returns EPERM.
       if (errno == EPERM) {
@@ -830,13 +849,7 @@
       PLOG(ERROR) << "pipe error on "
                   << fd_written
                   << " Currently writing message of size:"
-                  << msg->size()
-                  << " msgh.msg_iovlen:"
-                  << msgh.msg_iovlen
-                  << " amt_to_write: "
-                  << amt_to_write
-                  << " num FDs to send:"
-                  << msg->file_descriptor_set()->size();
+                  << msg->size();
       return false;
     }