fd_file: don't report failure when trying to flush a pipe.

At least one user of FdFile (SignalCatcher) will attempt to create an
FdFile with either a real file or a pipe. When it does so with a pipe,
fdatasync fails in Flush(), causing a bunch of spurious logging to be
emitted. Check to see if the file we're flushing is actually a file
before calling fdatasync.

Bug: http://b/67327501
Test: fd_file_test on host
Change-Id: I70103fb20f4fceb36a806c4fd530a0a77c328a96
diff --git a/runtime/base/unix_file/fd_file.cc b/runtime/base/unix_file/fd_file.cc
index 6d1de00..58b047f 100644
--- a/runtime/base/unix_file/fd_file.cc
+++ b/runtime/base/unix_file/fd_file.cc
@@ -174,13 +174,20 @@
 
 int FdFile::Flush() {
   DCHECK(!read_only_mode_);
+
 #ifdef __linux__
   int rc = TEMP_FAILURE_RETRY(fdatasync(fd_));
 #else
   int rc = TEMP_FAILURE_RETRY(fsync(fd_));
 #endif
+
   moveUp(GuardState::kFlushed, "Flushing closed file.");
-  return (rc == -1) ? -errno : rc;
+  if (rc == 0) {
+    return 0;
+  }
+
+  // Don't report failure if we just tried to flush a pipe or socket.
+  return errno == EINVAL ? 0 : -errno;
 }
 
 int64_t FdFile::Read(char* buf, int64_t byte_count, int64_t offset) const {
diff --git a/runtime/base/unix_file/fd_file.h b/runtime/base/unix_file/fd_file.h
index 91b08bc..3fb70f6 100644
--- a/runtime/base/unix_file/fd_file.h
+++ b/runtime/base/unix_file/fd_file.h
@@ -94,6 +94,7 @@
   int SetLength(int64_t new_length) OVERRIDE WARN_UNUSED;
   int64_t GetLength() const OVERRIDE;
   int64_t Write(const char* buf, int64_t byte_count, int64_t offset) OVERRIDE WARN_UNUSED;
+
   int Flush() OVERRIDE WARN_UNUSED;
 
   // Short for SetLength(0); Flush(); Close();
diff --git a/runtime/base/unix_file/fd_file_test.cc b/runtime/base/unix_file/fd_file_test.cc
index 8b1a115..042fbc9 100644
--- a/runtime/base/unix_file/fd_file_test.cc
+++ b/runtime/base/unix_file/fd_file_test.cc
@@ -274,4 +274,15 @@
   EXPECT_EQ(reset_compare(tmp, tmp6), 0);
 }
 
+TEST_F(FdFileTest, PipeFlush) {
+  int pipefd[2];
+  ASSERT_EQ(0, pipe2(pipefd, O_CLOEXEC));
+
+  FdFile file(pipefd[1], true);
+  ASSERT_TRUE(file.WriteFully("foo", 3));
+  ASSERT_EQ(0, file.Flush());
+  ASSERT_EQ(0, file.FlushCloseOrErase());
+  close(pipefd[0]);
+}
+
 }  // namespace unix_file