From 41fc61659b017d9153b460ffcdd883e992348397 Mon Sep 17 00:00:00 2001 From: Paul Dicker Date: Mon, 22 Jan 2018 20:11:32 +0100 Subject: [PATCH] Tweak retry counter --- src/lib.rs | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 7ac9186248..1505f74206 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -986,7 +986,9 @@ impl Rng for ThreadRng { /// `EntropyRng` uses the interface for random numbers provided by the operating /// system ([`OsRng`]). If that returns an error, it will fall back to the /// [`JitterRng`] entropy collector. Occasionally it will then check if `OsRng` -/// is still not available, and switch back if possible. +/// is still not available, and switch back if possible. Once every 8 calls to +/// `try_fill_bytes` if `OsRng` failed with `ErrorKind:Unavailable`, otherwise +/// with every call. /// /// [`OsRng`]: os/struct.OsRng.html /// [`JitterRng`]: jitter/struct.JitterRng.html @@ -1074,22 +1076,28 @@ impl Rng for EntropyRng { } } EntropySource::Jitter(ref mut rng) => { - if self.counter >= 8 { - if let Ok(os_rng) = try_os_new(dest) { - switch_rng = Some(EntropySource::Os(os_rng)); - } else { - self.counter = (self.counter + 1) % 8; - return rng.try_fill_bytes(dest); // use JitterRng + if self.counter == 0 { + match try_os_new(dest) { + Ok(os_rng) => { + switch_rng = Some(EntropySource::Os(os_rng)); + } + Err(e) => { + if e.kind() == ErrorKind::Unavailable { + self.counter = 8; // Wait 8 calls before retry + } else { + self.counter = 0; // Retry on next call + } + return rng.try_fill_bytes(dest); // use JitterRng + } } } else { - self.counter = (self.counter + 1) % 8; + self.counter -= 1; return rng.try_fill_bytes(dest); // use JitterRng } } } if let Some(rng) = switch_rng { self.rng = rng; - self.counter = 0; } Ok(()) }