mirror of
https://github.com/fmtlib/fmt.git
synced 2026-11-09 14:50:24 +08:00
Don't terminate when fmt::ostream fails to write in the destructor
The destructor flushed the buffer and let write errors escape, calling std::terminate on errors like a full disk. Report the error instead, like file and buffered_file do on close errors. Also clear the buffer before writing in flush so that data from a failed write, e.g. in close, is not written again by the destructor.
This commit is contained in:
parent
bee9426a64
commit
aa2ce7d30d
@ -376,9 +376,11 @@ class ostream : private detail::buffer<char> {
|
||||
}
|
||||
|
||||
inline void flush() {
|
||||
if (size() == 0) return;
|
||||
file_.write(data(), size() * sizeof(data()[0]));
|
||||
size_t n = size();
|
||||
if (n == 0) return;
|
||||
// Clear before writing to not write the data again if the write fails.
|
||||
clear();
|
||||
file_.write(data(), n);
|
||||
}
|
||||
|
||||
template <typename... T>
|
||||
|
||||
@ -396,7 +396,8 @@ ostream::ostream(ostream&& other) noexcept
|
||||
}
|
||||
|
||||
ostream::~ostream() {
|
||||
flush();
|
||||
FMT_TRY { flush(); }
|
||||
FMT_CATCH(...) { report_system_error(errno, "cannot write to file"); }
|
||||
delete[] data();
|
||||
}
|
||||
#endif // FMT_USE_FCNTL
|
||||
|
||||
@ -328,6 +328,23 @@ TEST(ostream_test, flush) {
|
||||
EXPECT_READ(in, "x");
|
||||
}
|
||||
|
||||
TEST(ostream_test, write_error_in_dtor) {
|
||||
auto test_file = uniq_file_name(__LINE__);
|
||||
EXPECT_WRITE(
|
||||
stderr,
|
||||
fmt::output_file(test_file, file::RDONLY | file::CREATE).print("x"),
|
||||
system_error_message(EBADF, "cannot write to file") + "\n");
|
||||
}
|
||||
|
||||
TEST(ostream_test, close_error) {
|
||||
auto out =
|
||||
fmt::output_file(uniq_file_name(__LINE__), file::RDONLY | file::CREATE);
|
||||
out.print("x");
|
||||
EXPECT_THROW(out.close(), std::system_error);
|
||||
// Check that the destructor doesn't try to write the data again.
|
||||
EXPECT_WRITE(stderr, { auto moved = std::move(out); }, "");
|
||||
}
|
||||
|
||||
TEST(file_test, default_ctor) {
|
||||
file f;
|
||||
EXPECT_EQ(-1, f.descriptor());
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user