diff --git a/src/error.rs b/src/error.rs index f1eb27ef780..266bb0c2946 100644 --- a/src/error.rs +++ b/src/error.rs @@ -52,7 +52,7 @@ impl ErrorKind { /// A description of this error kind pub fn description(self) -> &'static str { match self { - ErrorKind::Unavailable => "permanent failure or unavailable", + ErrorKind::Unavailable => "permanent failure", ErrorKind::Transient => "transient failure", ErrorKind::NotReady => "not ready yet", ErrorKind::Other => "uncategorised", @@ -123,7 +123,15 @@ impl Error { impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "RNG error [{}]: {}", self.kind.description(), self.msg()) + #[cfg(feature="std")] { + if let Some(ref cause) = self.cause { + return write!(f, "{} ({}); cause: {}", + self.msg(), + self.kind.description(), + cause); + } + } + write!(f, "{} ({})", self.msg(), self.kind.description()) } } diff --git a/src/lib.rs b/src/lib.rs index b848e241469..20941633d2b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -953,8 +953,8 @@ thread_local!( static THREAD_RNG_KEY: Rc>> = { const THREAD_RNG_RESEED_THRESHOLD: u64 = 32_768; let mut entropy_source = EntropyRng::new(); - let r = StdRng::from_rng(&mut entropy_source) - .expect("could not initialize thread_rng"); + let r = StdRng::from_rng(&mut entropy_source).unwrap_or_else(|err| + panic!("could not initialize thread_rng: {}", err)); let rng = ReseedingRng::new(r, THREAD_RNG_RESEED_THRESHOLD, entropy_source); @@ -1063,7 +1063,8 @@ impl Rng for EntropyRng { } fn fill_bytes(&mut self, dest: &mut [u8]) { - self.try_fill_bytes(dest).unwrap(); + self.try_fill_bytes(dest).unwrap_or_else(|err| + panic!("all entropy sources failed; first error: {}", err)) } fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { @@ -1087,6 +1088,7 @@ impl Rng for EntropyRng { let os_rng_result = try_os_new(dest); match os_rng_result { Ok(os_rng) => { + debug!("EntropyRng: using OsRng"); switch_rng = Some(EntropySource::Os(os_rng)); } Err(os_rng_error) => { @@ -1094,6 +1096,7 @@ impl Rng for EntropyRng { os_rng_error); match try_jitter_new(dest) { Ok(jitter_rng) => { + debug!("EntropyRng: using JitterRng"); switch_rng = Some(EntropySource::Jitter(jitter_rng)); } Err(_jitter_error) => { @@ -1112,6 +1115,7 @@ impl Rng for EntropyRng { os_rng_error); match try_jitter_new(dest) { Ok(jitter_rng) => { + debug!("EntropyRng: using JitterRng"); switch_rng = Some(EntropySource::Jitter(jitter_rng)); } Err(_jitter_error) => { @@ -1124,7 +1128,7 @@ impl Rng for EntropyRng { } EntropySource::Jitter(ref mut rng) => { if let Ok(os_rng) = try_os_new(dest) { - info!("EntropyRng: OsRng available [switching back from JitterRng]"); + debug!("EntropyRng: using OsRng"); switch_rng = Some(EntropySource::Os(os_rng)); } else { return rng.try_fill_bytes(dest); // use JitterRng @@ -1217,7 +1221,7 @@ pub fn sample(rng: &mut R, iterable: I, amount: usize) -> Vec mod test { use impls; #[cfg(feature="std")] - use super::{random, thread_rng}; + use super::{random, thread_rng, EntropyRng}; use super::{Rng, SeedableRng, StdRng}; #[cfg(feature="alloc")] use alloc::boxed::Box; @@ -1263,6 +1267,13 @@ mod test { impls::fill_bytes_via_u64(self, dest) } } + + #[test] + #[cfg(feature="std")] + fn test_entropy() { + let mut rng = EntropyRng::new(); + rng.next_u32(); + } #[test] fn test_fill_bytes_default() { diff --git a/src/os.rs b/src/os.rs index 5a497cdd418..168b6295755 100644 --- a/src/os.rs +++ b/src/os.rs @@ -78,14 +78,14 @@ impl Rng for OsRng { loop { if let Err(e) = self.try_fill_bytes(dest) { if err_count >= RETRY_LIMIT { - error!("OsRng failed too many times; last error: {:?}", e); - panic!("OsRng failed too many times; last error: {:?}", e); + error!("OsRng failed too many times; last error: {}", e); + panic!("OsRng failed too many times; last error: {}", e); } match e.kind() { ErrorKind::Transient => { if !error_logged { - warn!("OsRng failed; retrying up to {} times. Error: {:?}", + warn!("OsRng failed; retrying up to {} times. Error: {}", TRANSIENT_RETRIES, e); error_logged = true; } @@ -95,7 +95,7 @@ impl Rng for OsRng { } ErrorKind::NotReady => { if !error_logged { - warn!("OsRng failed; waiting up to {}s and retrying. Error: {:?}", + warn!("OsRng failed; waiting up to {}s and retrying. Error: {}", MAX_RETRY_PERIOD, e); error_logged = true; } @@ -104,8 +104,8 @@ impl Rng for OsRng { continue; } _ => { - error!("OsRng failed: {:?}", e); - panic!("OsRng fatal error: {:?}", e); + error!("OsRng failed: {}", e); + panic!("OsRng fatal error: {}", e); } } } diff --git a/src/reseeding.rs b/src/reseeding.rs index aab46f44b91..cf47b3fea8d 100644 --- a/src/reseeding.rs +++ b/src/reseeding.rs @@ -46,7 +46,8 @@ impl ReseedingRng { pub fn reseed_if_necessary(&mut self) { if self.bytes_generated >= self.generation_threshold { trace!("Reseeding RNG after {} bytes", self.bytes_generated); - R::from_rng(&mut self.reseeder).map(|result| self.rng = result).unwrap(); + R::from_rng(&mut self.reseeder).map(|result| self.rng = result) + .unwrap_or_else(|err| panic!("reseeding failed: {}", err)); self.bytes_generated = 0; } }