Skip to content

Commit

Permalink
Inline fill_via_try_fill implicit error handling, and revise
Browse files Browse the repository at this point in the history
  • Loading branch information
dhardy committed Jan 9, 2018
1 parent fed7943 commit c9bfa3a
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 37 deletions.
36 changes: 0 additions & 36 deletions src/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,40 +167,4 @@ pub fn next_u64_via_fill<R: Rng+?Sized>(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<R: Rng+?Sized>(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
33 changes: 32 additions & 1 deletion src/os.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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> {
Expand Down

0 comments on commit c9bfa3a

Please sign in to comment.