Hi,
On Linux, reading from /dev/[u]random can fail with an EINTR or EAGAIN
error. In that case, one should just retry. No sleep is required.
If this error occured on the blocking class, an error was thrown which
is not correct. Also the blocking case had some issues.
Attached you find a patch that solves this.
Note: this solution makes the non-blocking code _somewhat_ blocking. To
solve this, the get-routine for the non-blocking should return a boolean
indicatin data was available or not. Because in theory, read might also
return 0.
diff -uNrBbd
cr.org/osrng.cpp cr.new/osrng.cpp
---
cr.org/osrng.cpp 2010-08-06 18:44:30.000000000 +0200
+++
cr.new/osrng.cpp 2012-10-17 17:22:01.151537879 +0200
@@ -83,8 +83,22 @@
if (!CryptGenRandom(m_Provider.GetProviderHandle(), (DWORD)size, output))
throw OS_RNG_Err("CryptGenRandom");
#else
- if (read(m_fd, output, size) != size)
+ while(size)
+ {
+ int rc = read(m_fd, output, size);
+
+ if (rc == -1)
+ {
+ // /dev/urandom reads CAN give EAGAIN errors! (maybe EINTR as well)
+ if (errno != EINTR && errno != EAGAIN)
throw OS_RNG_Err("read /dev/urandom");
+
+ continue;
+ }
+
+ output += rc;
+ size -= rc;
+ }
#endif
}
@@ -119,10 +133,17 @@
while (size)
{
// on some systems /dev/random will block until all bytes
- // are available, on others it will returns immediately
+ // are available, on others it returns immediately
ssize_t len = read(m_fd, output, size);
if (len < 0)
+ {
+ // /dev/random reads CAN give EAGAIN errors! (maybe EINTR as well)
+ if (errno != EINTR && errno != EAGAIN)
throw OS_RNG_Err("read " CRYPTOPP_BLOCKING_RNG_FILENAME);
+
+ continue;
+ }
+
size -= len;
output += len;
if (size)
Folkert van Heusden
--
Looking for a cheap but fast webhoster with an excellent helpdesk?
http://keetweej.vanheusden.com/redir.php?id=1001
----------------------------------------------------------------------
Phone:
+31-6-41278122, PGP-key: 1F28D8AE,
www.vanheusden.com