aboutsummaryrefslogtreecommitdiffhomepage
path: root/absl/strings
diff options
context:
space:
mode:
authorGravatar Abseil Team <absl-team@google.com>2018-10-23 18:09:41 -0700
committerGravatar Ashley Hedberg <ahedberg@google.com>2018-10-24 16:47:28 -0400
commit94c298e2a0ae409e283cab96c954a685bd865a70 (patch)
tree61581c5b86e25d374cf6abb2ae11e8850367ffe8 /absl/strings
parent8efc52608700647d7bd5ef55ef2487af1ecdaa7c (diff)
Export of internal Abseil changes.
-- 441d1aa02483cdc510eb2fef012b31384fd8e3a6 by Eric Fiselier <ericwf@google.com>: Fix str_format with non-POSIX libc implementations. PiperOrigin-RevId: 218441122 -- da6190130e74222af6eb161a5593364341370370 by Jon Cohen <cohenjon@google.com>: Refactor ExceptionSafetyTester::Test in order to remove the levels of indirection related to unpacking tuples. PiperOrigin-RevId: 218403355 GitOrigin-RevId: 441d1aa02483cdc510eb2fef012b31384fd8e3a6 Change-Id: I6f6b978eb96fe261e8ee41ecdce185e5356a601d
Diffstat (limited to 'absl/strings')
-rw-r--r--absl/strings/internal/str_format/output.cc27
-rw-r--r--absl/strings/str_format_test.cc5
2 files changed, 28 insertions, 4 deletions
diff --git a/absl/strings/internal/str_format/output.cc b/absl/strings/internal/str_format/output.cc
index 5c3795b..d7fef69 100644
--- a/absl/strings/internal/str_format/output.cc
+++ b/absl/strings/internal/str_format/output.cc
@@ -20,6 +20,16 @@
namespace absl {
namespace str_format_internal {
+namespace {
+struct ClearErrnoGuard {
+ ClearErrnoGuard() : old_value(errno) { errno = 0; }
+ ~ClearErrnoGuard() {
+ if (!errno) errno = old_value;
+ }
+ int old_value;
+};
+} // namespace
+
void BufferRawSink::Write(string_view v) {
size_t to_write = std::min(v.size(), size_);
std::memcpy(buffer_, v.data(), to_write);
@@ -30,14 +40,27 @@ void BufferRawSink::Write(string_view v) {
void FILERawSink::Write(string_view v) {
while (!v.empty() && !error_) {
+ // Reset errno to zero in case the libc implementation doesn't set errno
+ // when a failure occurs.
+ ClearErrnoGuard guard;
+
if (size_t result = std::fwrite(v.data(), 1, v.size(), output_)) {
// Some progress was made.
count_ += result;
v.remove_prefix(result);
} else {
- // Some error occurred.
- if (errno != EINTR) {
+ if (errno == EINTR) {
+ continue;
+ } else if (errno) {
error_ = errno;
+ } else if (std::ferror(output_)) {
+ // Non-POSIX compliant libc implementations may not set errno, so we
+ // have check the streams error indicator.
+ error_ = EBADF;
+ } else {
+ // We're likely on a non-POSIX system that encountered EINTR but had no
+ // way of reporting it.
+ continue;
}
}
}
diff --git a/absl/strings/str_format_test.cc b/absl/strings/str_format_test.cc
index ea9a3a1..87ed234 100644
--- a/absl/strings/str_format_test.cc
+++ b/absl/strings/str_format_test.cc
@@ -242,6 +242,7 @@ class TempFile {
std::string ReadFile() {
std::fseek(file_, 0, SEEK_END);
int size = std::ftell(file_);
+ EXPECT_GT(size, 0);
std::rewind(file_);
std::string str(2 * size, ' ');
int read_bytes = std::fread(&str[0], 1, str.size(), file_);
@@ -270,7 +271,7 @@ TEST_F(FormatEntryPointTest, FPrintFError) {
EXPECT_EQ(errno, EBADF);
}
-#if __GNUC__
+#if __GLIBC__
TEST_F(FormatEntryPointTest, FprintfTooLarge) {
std::FILE* f = std::fopen("/dev/null", "w");
int width = 2000000000;
@@ -297,7 +298,7 @@ TEST_F(FormatEntryPointTest, PrintF) {
EXPECT_EQ(result, 30);
EXPECT_EQ(tmp.ReadFile(), "STRING: ABC NUMBER: -000000019");
}
-#endif // __GNUC__
+#endif // __GLIBC__
TEST_F(FormatEntryPointTest, SNPrintF) {
char buffer[16];