diff --git a/src/impls.rs b/src/impls.rs index 6e005965391..34c17786c1f 100644 --- a/src/impls.rs +++ b/src/impls.rs @@ -167,40 +167,4 @@ pub fn next_u64_via_fill(rng: &mut R) -> u64 { impl_uint_from_fill!(rng, u64, 8) } -/// Implement `fill_bytes` via `try_fill` with implicit error handling. -pub fn fill_via_try_fill(rng: &mut R, dest: &mut [u8]) { - const WAIT_DUR_MS: u32 = 100; - const MAX_WAIT: u32 = (1 * 60 * 1000) / WAIT_DUR_MS; - const TRANSIENT_STEP: u32 = MAX_WAIT / 8; - let mut err_count = 0; - - loop { - if let Err(e) = rng.try_fill_bytes(dest) { - if e.kind().should_retry() { - if err_count > MAX_WAIT { - // TODO: log details & cause? - panic!("Too many RNG errors or timeout; last error: {}", e.msg()); - } - - if e.kind().should_wait() { - #[cfg(feature="std")]{ - let dur = ::std::time::Duration::from_millis(WAIT_DUR_MS as u64); - ::std::thread::sleep(dur); - } - err_count += 1; - } else { - err_count += TRANSIENT_STEP; - } - - continue; - } - - // TODO: log details & cause? - panic!("Fatal RNG error: {}", e.msg()); - } - - break; - } -} - // TODO: implement tests for the above diff --git a/src/os.rs b/src/os.rs index 5e0c28f3a21..248e980acb9 100644 --- a/src/os.rs +++ b/src/os.rs @@ -61,7 +61,38 @@ impl Rng for OsRng { } fn fill_bytes(&mut self, dest: &mut [u8]) { - impls::fill_via_try_fill(self, dest) + // We cannot return Err(..), so we try to handle before panicking. + const WAIT_DUR_MS: u32 = 100; // retry every 100ms + const MAX_WAIT: u32 = (10 * 1000) / WAIT_DUR_MS; // max 10s + const TRANSIENT_STEP: u32 = MAX_WAIT / 8; + let mut err_count = 0; + + loop { + if let Err(e) = self.try_fill_bytes(dest) { + // TODO: add logging to explain why we wait and the full cause + if e.kind().should_retry() { + if err_count > MAX_WAIT { + panic!("Too many RNG errors or timeout; last error: {}", e.msg()); + } + + if e.kind().should_wait() { + #[cfg(feature="std")]{ + let dur = ::std::time::Duration::from_millis(WAIT_DUR_MS as u64); + ::std::thread::sleep(dur); + } + err_count += 1; + } else { + err_count += TRANSIENT_STEP; + } + + continue; + } + + panic!("Fatal RNG error: {}", e.msg()); + } + + break; + } } fn try_fill_bytes(&mut self, v: &mut [u8]) -> Result<(), Error> {