diff --git a/include/fmt/format-inl.h b/include/fmt/format-inl.h index 66ee747a..46f949ea 100644 --- a/include/fmt/format-inl.h +++ b/include/fmt/format-inl.h @@ -1526,9 +1526,8 @@ template class glibc_file : public file_base { } void init_buffer() { - if (this->file_->_IO_write_ptr) return; + if (this->file_->_IO_write_ptr < this->file_->_IO_write_end) return; // Force buffer initialization by placing and removing a char in a buffer. - assume(this->file_->_IO_write_ptr >= this->file_->_IO_write_end); putc_unlocked(0, this->file_); --this->file_->_IO_write_ptr; } diff --git a/test/os-test.cc b/test/os-test.cc index 425cc0ee..db861e55 100644 --- a/test/os-test.cc +++ b/test/os-test.cc @@ -540,7 +540,7 @@ TEST(file_test, line_buffering) { reader.join(); } -# endif // _WIN32 +# endif // _WIN32 TEST(file_test, buffer_boundary) { auto pipe = fmt::pipe(); @@ -559,4 +559,34 @@ TEST(file_test, buffer_boundary) { EXPECT_STREQ(fgets(buf, sizeof(buf), read_end.get()), "1234 567"); } +TEST(file_test, io_putting) { + auto pipe = fmt::pipe(); + auto read_end = pipe.read_end.fdopen("r"); + auto write_end = pipe.write_end.fdopen("w"); + + size_t read_size = 0; + auto reader = std::thread([&]() { + size_t n = 0; + do { + char buf[4096] = {}; + n = fread(buf, 1, sizeof(buf), read_end.get()); + read_size += n; + } while (n != 0); + }); + + // This initialize buffers but doesn't set _IO_CURRENTLY_PUTTING. + fseek(write_end.get(), 0, SEEK_SET); + + size_t write_size = 0; + for (int i = 0; i <= 20000; ++i) { + auto s = fmt::format("{}\n", i); + fmt::print(write_end.get(), "{}", s); + write_size += s.size(); + } + + write_end.close(); + reader.join(); + EXPECT_EQ(read_size, write_size); +} + #endif // FMT_USE_FCNTL