diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2015-09-17 15:06:42 +0000 |
---|---|---|
committer | Jonathan Wakely <jwakely@redhat.com> | 2015-09-17 15:06:42 +0000 |
commit | 419488cffdf62bf81440085936e8ba763437ed5f (patch) | |
tree | 0dd3c7308998c3b62b6757ec7e3b42426e1828b6 /libstdc++-v3/src | |
parent | fead086995d70855198101104206d065f2f24ad9 (diff) |
Make std::random_device retry after short reads
PR libstdc++/65142
* src/c++11/random.cc (random_device::_M_getval()): Retry after short
reads.
git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@227872 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libstdc++-v3/src')
-rw-r--r-- | libstdc++-v3/src/c++11/random.cc | 24 |
1 files changed, 17 insertions, 7 deletions
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<FILE*>(_M_file)), - static_cast<void*>(&__ret), sizeof(result_type)); + do + { + const int e = read(fileno(static_cast<FILE*>(_M_file)), p, n); + if (e > 0) + { + n -= e; + p = static_cast<char*>(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<void*>(&__ret), sizeof(result_type), - 1, static_cast<FILE*>(_M_file)); + const size_t e = std::fread(p, n, 1, static_cast<FILE*>(_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; } |