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