mirror of
https://github.com/fmtlib/fmt.git
synced 2026-11-09 14:50:24 +08:00
Don't lose data on short writes in fmt::ostream
flush ignored the number of bytes written by write which can be less than requested, silently dropping the rest of the buffer. Write in a loop until all data is written.
This commit is contained in:
parent
aa2ce7d30d
commit
e7e6e3f710
@ -377,10 +377,14 @@ class ostream : private detail::buffer<char> {
|
||||
|
||||
inline void flush() {
|
||||
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);
|
||||
// Write in a loop because write may write fewer bytes than requested.
|
||||
for (const char* p = data(); n != 0;) {
|
||||
size_t written = file_.write(p, n);
|
||||
p += written;
|
||||
n -= written;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename... T>
|
||||
|
||||
@ -54,6 +54,7 @@ int fclose_count;
|
||||
int fileno_count;
|
||||
size_t read_nbyte;
|
||||
size_t write_nbyte;
|
||||
size_t write_max; // Maximum number of bytes written per call if nonzero.
|
||||
bool sysconf_error;
|
||||
|
||||
enum { none, max_size, error } fstat_sim;
|
||||
@ -142,6 +143,7 @@ test::ssize_t test::read(int fildes, void* buf, test::size_t nbyte) {
|
||||
test::ssize_t test::write(int fildes, const void* buf, test::size_t nbyte) {
|
||||
write_nbyte = nbyte;
|
||||
EMULATE_EINTR(write, -1);
|
||||
if (write_max != 0 && nbyte > write_max) nbyte = write_max;
|
||||
return ::FMT_POSIX(write(fildes, buf, nbyte));
|
||||
}
|
||||
|
||||
@ -308,6 +310,17 @@ TEST(file_test, write_retry) {
|
||||
# endif
|
||||
}
|
||||
|
||||
TEST(ostream_test, short_write) {
|
||||
write_max = 1;
|
||||
{
|
||||
auto out = fmt::output_file("temp");
|
||||
out.print("abc");
|
||||
}
|
||||
write_max = 0;
|
||||
file f("temp", file::RDONLY);
|
||||
EXPECT_READ(f, "abc");
|
||||
}
|
||||
|
||||
# ifdef _WIN32
|
||||
TEST(file_test, convert_read_count) {
|
||||
auto pipe = fmt::pipe();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user