From a2b4d73daf5854c40b71e0b655a9507bf6977279 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Thu, 17 Sep 2015 16:06:42 +0100 Subject: [PATCH] Make std::random_device retry after short reads PR libstdc++/65142 * src/c++11/random.cc (random_device::_M_getval()): Retry after short reads. From-SVN: r227872 --- libstdc++-v3/ChangeLog | 4 ++++ libstdc++-v3/src/c++11/random.cc | 24 +++++++++++++++++------- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index c70ad43a2eb..25aa16b2973 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,9 @@ 2015-09-17 Jonathan Wakely + PR libstdc++/65142 + * src/c++11/random.cc (random_device::_M_getval()): Retry after short + reads. + * include/std/system_error (error_code::operator bool(), error_condition::operator bool()): Remove redundant conditional expression. diff --git a/libstdc++-v3/src/c++11/random.cc b/libstdc++-v3/src/c++11/random.cc index 1d102c755b2..f1d6125128a 100644 --- a/libstdc++-v3/src/c++11/random.cc +++ b/libstdc++-v3/src/c++11/random.cc @@ -130,16 +130,26 @@ namespace std _GLIBCXX_VISIBILITY(default) #endif result_type __ret; - + void* p = &__ret; + size_t n = sizeof(result_type); #ifdef _GLIBCXX_HAVE_UNISTD_H - auto e = read(fileno(static_cast(_M_file)), - static_cast(&__ret), sizeof(result_type)); + do + { + const int e = read(fileno(static_cast(_M_file)), p, n); + if (e > 0) + { + n -= e; + p = static_cast(p) + e; + } + else if (e != -1 || errno != EINTR) + __throw_runtime_error(__N("random_device could not be read")); + } + while (n > 0); #else - auto e = std::fread(static_cast(&__ret), sizeof(result_type), - 1, static_cast(_M_file)); + const size_t e = std::fread(p, n, 1, static_cast(_M_file)); + if (e != 1) + __throw_runtime_error(__N("random_device could not be read")); #endif - if (e != sizeof(result_type)) - __throw_runtime_error(__N("random_device could not read enough bytes")); return __ret; } -- 2.30.2