From ecb81ae24786a0da0461a7718ee21c164fa5b9a2 Mon Sep 17 00:00:00 2001 From: James Stone Date: Thu, 19 Oct 2017 14:20:23 -0700 Subject: [PATCH] Make posix_fallocate robust against interruption, report right errors --- CHANGELOG.md | 4 +++- src/realm/util/file.cpp | 16 ++++++++++++---- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 35c197f2602..304173402b3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,9 @@ ### Bugfixes -* Lorem ipsum. +* Make calls to posix_fallocate() robust against interruption and report + the correct error on failure. + PR [#2905](https://github.com/realm/realm-core/pull/2905). ### Breaking changes diff --git a/src/realm/util/file.cpp b/src/realm/util/file.cpp index 4f7ba871c8c..5c16c3ce900 100644 --- a/src/realm/util/file.cpp +++ b/src/realm/util/file.cpp @@ -714,11 +714,19 @@ void File::prealloc_if_supported(SizeType offset, size_t size) if (int_cast_with_overflow_detect(size, size2)) throw std::runtime_error("File size overflow"); - if (::posix_fallocate(m_fd, offset, size2) == 0) + // posix_fallocate() does not set errno, it returns the error (if any) or zero. + // It is also possible for it to be interrupted by EINTR according to some man pages (ex fedora 24) + int status; + do { + status = ::posix_fallocate(m_fd, offset, size2); + } while (status == EINTR); + + if (REALM_LIKELY(status == 0)) { return; - int err = errno; // Eliminate any risk of clobbering - std::string msg = get_errno_msg("posix_fallocate() failed: ", err); - if (err == ENOSPC || err == EDQUOT) { + } + + std::string msg = get_errno_msg("posix_fallocate() failed: ", status); + if (status == ENOSPC || status == EDQUOT) { throw OutOfDiskSpace(msg); } throw std::runtime_error(msg);