This is an automated email from the ASF dual-hosted git repository. bbannier pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/mesos.git
The following commit(s) were added to refs/heads/master by this push: new d838f29 Correctly propagated `close` failures in some instances. d838f29 is described below commit d838f2958e18c1a75594ca4f10df132670fcd11e Author: Benjamin Bannier <benjamin.bann...@mesosphere.io> AuthorDate: Thu Jan 24 10:44:49 2019 +0100 Correctly propagated `close` failures in some instances. When e.g., writing to disk, errors from write might only manifest at ::close time. We update some instances to correctly propagate these errors instead of dropping them silently. We only propagate the ::close error if the write operation succeeded, otherwise we just propagate the error from the write operation. Review: https://reviews.apache.org/r/69082/ --- 3rdparty/stout/include/stout/os/posix/mktemp.hpp | 26 ++++++++-------- 3rdparty/stout/include/stout/os/write.hpp | 19 +++++++----- 3rdparty/stout/include/stout/protobuf.hpp | 38 ++++++++++++++---------- 3 files changed, 47 insertions(+), 36 deletions(-) diff --git a/3rdparty/stout/include/stout/os/posix/mktemp.hpp b/3rdparty/stout/include/stout/os/posix/mktemp.hpp index 63b3d1a..8dab259 100644 --- a/3rdparty/stout/include/stout/os/posix/mktemp.hpp +++ b/3rdparty/stout/include/stout/os/posix/mktemp.hpp @@ -36,23 +36,25 @@ namespace os { inline Try<std::string> mktemp( const std::string& path = path::join(os::temp(), "XXXXXX")) { - char* temp = new char[path.size() + 1]; - ::memcpy(temp, path.c_str(), path.size() + 1); + char* _path = new char[path.size() + 1]; + ::memcpy(_path, path.c_str(), path.size() + 1); + + int_fd fd = ::mkstemp(_path); + Try<std::string> temp = std::string(_path); + delete[] _path; - int_fd fd = ::mkstemp(temp); if (fd < 0) { - delete[] temp; - return ErrnoError(); + temp = ErrnoError(); } - // We ignore the return value of close(). This is because users - // calling this function are interested in the return value of - // mkstemp(). Also an unsuccessful close() doesn't affect the file. - os::close(fd); + Try<Nothing> close = os::close(fd); + + // We propagate `close` failures if creation of the temp file was successful. + if (temp.isSome() && close.isError()) { + return Error("Failed to close '" + stringify(fd) + "':" + close.error()); + } - std::string result(temp); - delete[] temp; - return result; + return temp; } } // namespace os { diff --git a/3rdparty/stout/include/stout/os/write.hpp b/3rdparty/stout/include/stout/os/write.hpp index f7538f9..89ca7b2 100644 --- a/3rdparty/stout/include/stout/os/write.hpp +++ b/3rdparty/stout/include/stout/os/write.hpp @@ -126,21 +126,24 @@ inline Try<Nothing> write( return Error(fd.error()); } - Try<Nothing> result = write(fd.get(), message); + Try<Nothing> write = os::write(fd.get(), message); - if (sync && result.isSome()) { + if (sync && write.isSome()) { // We call `fsync()` before closing the file instead of opening it with the // `O_SYNC` flag for better performance. See: // http://lkml.iu.edu/hypermail/linux/kernel/0105.3/0353.html - result = os::fsync(fd.get()); + write = os::fsync(fd.get()); } - // We ignore the return value of `close()` because users calling this function - // are interested in the return value of `write()`, or `fsync()` if `sync` is - // set to true. Also an unsuccessful `close()` doesn't affect the write. - os::close(fd.get()); + Try<Nothing> close = os::close(fd.get()); - return result; + // We propagate `close` failures if `write` on the file was successful. + if (write.isSome() && close.isError()) { + write = + Error("Failed to close '" + stringify(fd.get()) + "':" + close.error()); + } + + return write; } diff --git a/3rdparty/stout/include/stout/protobuf.hpp b/3rdparty/stout/include/stout/protobuf.hpp index eb4adef..4b3db7e 100644 --- a/3rdparty/stout/include/stout/protobuf.hpp +++ b/3rdparty/stout/include/stout/protobuf.hpp @@ -147,21 +147,24 @@ Try<Nothing> write(const std::string& path, const T& t, bool sync = false) return Error("Failed to open file '" + path + "': " + fd.error()); } - Try<Nothing> result = write(fd.get(), t); + Try<Nothing> write = ::protobuf::write(fd.get(), t); - if (sync && result.isSome()) { + if (sync && write.isSome()) { // We call `fsync()` before closing the file instead of opening it with the // `O_SYNC` flag for better performance. See: // http://lkml.iu.edu/hypermail/linux/kernel/0105.3/0353.html - result = os::fsync(fd.get()); + write = os::fsync(fd.get()); } - // We ignore the return value of `close()` because users calling this function - // are interested in the return value of `write()`, or `fsync()` if `sync` is - // set to true. Also an unsuccessful `close()` doesn't affect the write. - os::close(fd.get()); + Try<Nothing> close = os::close(fd.get()); - return result; + // We propagate `close` failures if `write` on the file was successful. + if (write.isSome() && close.isError()) { + return Error( + "Failed to close '" + stringify(fd.get()) + "':" + close.error()); + } + + return write; } @@ -181,20 +184,23 @@ inline Try<Nothing> append( return Error("Failed to open file '" + path + "': " + fd.error()); } - Try<Nothing> result = write(fd.get(), message); + Try<Nothing> write = protobuf::write(fd.get(), message); - if (sync && result.isSome()) { + if (sync && write.isSome()) { // We call `fsync()` before closing the file instead of opening it with the // `O_SYNC` flag for better performance. - result = os::fsync(fd.get()); + write = os::fsync(fd.get()); } - // NOTE: We ignore the return value of close(). This is because - // users calling this function are interested in the return value of - // write(). Also an unsuccessful close() doesn't affect the write. - os::close(fd.get()); + Try<Nothing> close = os::close(fd.get()); - return result; + // We propagate `close` failures if `write` on the file was successful. + if (write.isSome() && close.isError()) { + return Error( + "Failed to close '" + stringify(fd.get()) + "':" + close.error()); + } + + return write; }