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
This commit is contained in:
Jonathan Wakely 2015-09-17 16:06:42 +01:00 committed by Jonathan Wakely
parent 2eb57e545b
commit a2b4d73daf
2 changed files with 21 additions and 7 deletions

View File

@ -1,5 +1,9 @@
2015-09-17 Jonathan Wakely <jwakely@redhat.com>
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.

View File

@ -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;
}