about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-04-01 11:11:51 -0700
committerbors <bors@rust-lang.org>2014-04-01 11:11:51 -0700
commitb71c02e512fcfe18ea7a5a8a99ac758b4fa564a6 (patch)
tree7842aad2f7ad07256764e22d6ab2fad0b6f624ed /src
parentb8ef9fd9c9f642ce7b8aed82782a1ed745d08d64 (diff)
parentbc7a2d72a3fea324fa432de9b6ce6073302d3d8c (diff)
downloadrust-b71c02e512fcfe18ea7a5a8a99ac758b4fa564a6.tar.gz
rust-b71c02e512fcfe18ea7a5a8a99ac758b4fa564a6.zip
auto merge of #13115 : huonw/rust/rand-errors, r=alexcrichton
move errno -> IoError converter into std, bubble up OSRng errors

Also adds a general errno -> `~str` converter to `std::os`, and makes the failure messages for the things using `OSRng` (e.g. (transitively) the task-local RNG, meaning hashmap initialisation failures aren't such a black box).
Diffstat (limited to 'src')
-rw-r--r--src/libcollections/deque.rs4
-rw-r--r--src/libgreen/sched.rs7
-rw-r--r--src/libnative/io/addrinfo.rs4
-rw-r--r--src/libnative/io/mod.rs67
-rw-r--r--src/libnative/io/net.rs2
-rw-r--r--src/libnative/io/process.rs2
-rw-r--r--src/librand/distributions/exponential.rs2
-rw-r--r--src/librand/distributions/gamma.rs6
-rw-r--r--src/librand/distributions/normal.rs2
-rw-r--r--src/librand/isaac.rs34
-rw-r--r--src/librand/lib.rs55
-rw-r--r--src/librand/os.rs21
-rw-r--r--src/librand/reseeding.rs10
-rw-r--r--src/libstd/fmt/num.rs20
-rw-r--r--src/libstd/io/fs.rs2
-rw-r--r--src/libstd/io/mod.rs84
-rw-r--r--src/libstd/num/strconv.rs22
-rw-r--r--src/libstd/os.rs26
-rw-r--r--src/libstd/rt/task.rs2
-rw-r--r--src/test/bench/noise.rs2
20 files changed, 216 insertions, 158 deletions
diff --git a/src/libcollections/deque.rs b/src/libcollections/deque.rs
index 9c1427d0225..6c1391e7ca8 100644
--- a/src/libcollections/deque.rs
+++ b/src/libcollections/deque.rs
@@ -52,7 +52,7 @@ pub mod bench {
                                                   map: &mut M,
                                                   bh: &mut BenchHarness) {
         // setup
-        let mut rng = rand::XorShiftRng::new();
+        let mut rng = rand::weak_rng();
 
         map.clear();
         for _ in range(0, n) {
@@ -89,7 +89,7 @@ pub mod bench {
                                                 map: &mut M,
                                                 bh: &mut BenchHarness) {
         // setup
-        let mut rng = rand::XorShiftRng::new();
+        let mut rng = rand::weak_rng();
         let mut keys = slice::from_fn(n, |_| rng.gen::<uint>() % n);
 
         for k in keys.iter() {
diff --git a/src/libgreen/sched.rs b/src/libgreen/sched.rs
index adfd5908de2..683df846d62 100644
--- a/src/libgreen/sched.rs
+++ b/src/libgreen/sched.rs
@@ -967,7 +967,12 @@ impl ClosureConverter for UnsafeTaskReceiver {
 // worry there.
 #[cfg(windows)]
 fn new_sched_rng() -> XorShiftRng {
-    XorShiftRng::new()
+    match XorShiftRng::new() {
+        Ok(r) => r,
+        Err(e) => {
+            rtabort!("sched: failed to create seeded RNG: {}", e)
+        }
+    }
 }
 #[cfg(unix)]
 fn new_sched_rng() -> XorShiftRng {
diff --git a/src/libnative/io/addrinfo.rs b/src/libnative/io/addrinfo.rs
index ff617e5a230..bca564870e2 100644
--- a/src/libnative/io/addrinfo.rs
+++ b/src/libnative/io/addrinfo.rs
@@ -96,10 +96,8 @@ extern "system" {
 
 #[cfg(windows)]
 fn get_error(_: c_int) -> IoError {
-    use super::translate_error;
-
     unsafe {
-        translate_error(WSAGetLastError() as i32, true)
+        IoError::from_errno(WSAGetLastError() as uint, true)
     }
 }
 
diff --git a/src/libnative/io/mod.rs b/src/libnative/io/mod.rs
index e6e9cbb7ce3..34843102456 100644
--- a/src/libnative/io/mod.rs
+++ b/src/libnative/io/mod.rs
@@ -86,73 +86,10 @@ fn unimpl() -> IoError {
     }
 }
 
-fn translate_error(errno: i32, detail: bool) -> IoError {
-    #[cfg(windows)]
-    fn get_err(errno: i32) -> (io::IoErrorKind, &'static str) {
-        match errno {
-            libc::EOF => (io::EndOfFile, "end of file"),
-            libc::ERROR_NO_DATA => (io::BrokenPipe, "the pipe is being closed"),
-            libc::ERROR_FILE_NOT_FOUND => (io::FileNotFound, "file not found"),
-            libc::ERROR_INVALID_NAME => (io::InvalidInput, "invalid file name"),
-            libc::WSAECONNREFUSED => (io::ConnectionRefused, "connection refused"),
-            libc::WSAECONNRESET => (io::ConnectionReset, "connection reset"),
-            libc::WSAEACCES => (io::PermissionDenied, "permission denied"),
-            libc::WSAEWOULDBLOCK => {
-                (io::ResourceUnavailable, "resource temporarily unavailable")
-            }
-            libc::WSAENOTCONN => (io::NotConnected, "not connected"),
-            libc::WSAECONNABORTED => (io::ConnectionAborted, "connection aborted"),
-            libc::WSAEADDRNOTAVAIL => (io::ConnectionRefused, "address not available"),
-            libc::WSAEADDRINUSE => (io::ConnectionRefused, "address in use"),
-            libc::ERROR_BROKEN_PIPE => (io::EndOfFile, "the pipe has ended"),
-
-            // libuv maps this error code to EISDIR. we do too. if it is found
-            // to be incorrect, we can add in some more machinery to only
-            // return this message when ERROR_INVALID_FUNCTION after certain
-            // win32 calls.
-            libc::ERROR_INVALID_FUNCTION => (io::InvalidInput,
-                                             "illegal operation on a directory"),
-
-            _ => (io::OtherIoError, "unknown error")
-        }
-    }
-
-    #[cfg(not(windows))]
-    fn get_err(errno: i32) -> (io::IoErrorKind, &'static str) {
-        // FIXME: this should probably be a bit more descriptive...
-        match errno {
-            libc::EOF => (io::EndOfFile, "end of file"),
-            libc::ECONNREFUSED => (io::ConnectionRefused, "connection refused"),
-            libc::ECONNRESET => (io::ConnectionReset, "connection reset"),
-            libc::EPERM | libc::EACCES =>
-                (io::PermissionDenied, "permission denied"),
-            libc::EPIPE => (io::BrokenPipe, "broken pipe"),
-            libc::ENOTCONN => (io::NotConnected, "not connected"),
-            libc::ECONNABORTED => (io::ConnectionAborted, "connection aborted"),
-            libc::EADDRNOTAVAIL => (io::ConnectionRefused, "address not available"),
-            libc::EADDRINUSE => (io::ConnectionRefused, "address in use"),
-            libc::ENOENT => (io::FileNotFound, "no such file or directory"),
-            libc::EISDIR => (io::InvalidInput, "illegal operation on a directory"),
-
-            // These two constants can have the same value on some systems, but
-            // different values on others, so we can't use a match clause
-            x if x == libc::EAGAIN || x == libc::EWOULDBLOCK =>
-                (io::ResourceUnavailable, "resource temporarily unavailable"),
-
-            _ => (io::OtherIoError, "unknown error")
-        }
-    }
-
-    let (kind, desc) = get_err(errno);
-    IoError {
-        kind: kind,
-        desc: desc,
-        detail: if detail {Some(os::last_os_error())} else {None},
-    }
+fn last_error() -> IoError {
+    IoError::last_error()
 }
 
-fn last_error() -> IoError { translate_error(os::errno() as i32, true) }
-
 // unix has nonzero values as errors
 fn mkerr_libc(ret: libc::c_int) -> IoResult<()> {
     if ret != 0 {
diff --git a/src/libnative/io/net.rs b/src/libnative/io/net.rs
index bf751be1f7f..6ddd69eb019 100644
--- a/src/libnative/io/net.rs
+++ b/src/libnative/io/net.rs
@@ -120,7 +120,7 @@ fn last_error() -> io::IoError {
     extern "system" {
         fn WSAGetLastError() -> libc::c_int;
     }
-    super::translate_error(unsafe { WSAGetLastError() }, true)
+    io::IoError::from_errno(unsafe { WSAGetLastError() } as uint, true)
 }
 
 #[cfg(not(windows))]
diff --git a/src/libnative/io/process.rs b/src/libnative/io/process.rs
index c729473eecd..d2e2db63c1b 100644
--- a/src/libnative/io/process.rs
+++ b/src/libnative/io/process.rs
@@ -481,7 +481,7 @@ fn spawn_process_os(config: p::ProcessConfig,
                                     (bytes[1] << 16) as i32 |
                                     (bytes[2] <<  8) as i32 |
                                     (bytes[3] <<  0) as i32;
-                        Err(super::translate_error(errno, false))
+                        Err(io::IoError::from_errno(errno as uint, false))
                     }
                     Err(e) => {
                         assert!(e.kind == io::BrokenPipe ||
diff --git a/src/librand/distributions/exponential.rs b/src/librand/distributions/exponential.rs
index 5a6b925c53f..5cd53ca88a9 100644
--- a/src/librand/distributions/exponential.rs
+++ b/src/librand/distributions/exponential.rs
@@ -126,7 +126,7 @@ mod bench {
 
     #[bench]
     fn rand_exp(bh: &mut BenchHarness) {
-        let mut rng = XorShiftRng::new();
+        let mut rng = XorShiftRng::new().unwrap();
         let mut exp = Exp::new(2.71828 * 3.14159);
 
         bh.iter(|| {
diff --git a/src/librand/distributions/gamma.rs b/src/librand/distributions/gamma.rs
index 1e9b5cbe99e..a1557b84212 100644
--- a/src/librand/distributions/gamma.rs
+++ b/src/librand/distributions/gamma.rs
@@ -370,14 +370,14 @@ mod bench {
     use self::test::BenchHarness;
     use std::mem::size_of;
     use distributions::IndependentSample;
-    use {StdRng, RAND_BENCH_N};
+    use {XorShiftRng, RAND_BENCH_N};
     use super::Gamma;
 
 
     #[bench]
     fn bench_gamma_large_shape(bh: &mut BenchHarness) {
         let gamma = Gamma::new(10., 1.0);
-        let mut rng = StdRng::new();
+        let mut rng = XorShiftRng::new().unwrap();
 
         bh.iter(|| {
             for _ in range(0, RAND_BENCH_N) {
@@ -390,7 +390,7 @@ mod bench {
     #[bench]
     fn bench_gamma_small_shape(bh: &mut BenchHarness) {
         let gamma = Gamma::new(0.1, 1.0);
-        let mut rng = StdRng::new();
+        let mut rng = XorShiftRng::new().unwrap();
 
         bh.iter(|| {
             for _ in range(0, RAND_BENCH_N) {
diff --git a/src/librand/distributions/normal.rs b/src/librand/distributions/normal.rs
index 42fb76ad4eb..7340d00929e 100644
--- a/src/librand/distributions/normal.rs
+++ b/src/librand/distributions/normal.rs
@@ -193,7 +193,7 @@ mod bench {
 
     #[bench]
     fn rand_normal(bh: &mut BenchHarness) {
-        let mut rng = XorShiftRng::new();
+        let mut rng = XorShiftRng::new().unwrap();
         let mut normal = Normal::new(-2.71828, 3.14159);
 
         bh.iter(|| {
diff --git a/src/librand/isaac.rs b/src/librand/isaac.rs
index 5c14d2c9f5b..de3d471c7bd 100644
--- a/src/librand/isaac.rs
+++ b/src/librand/isaac.rs
@@ -11,6 +11,7 @@
 //! The ISAAC random number generator.
 
 use {Rng, SeedableRng, OSRng};
+use std::io::IoResult;
 use std::iter::{range_step, Repeat};
 use std::slice::raw;
 use std::mem;
@@ -44,19 +45,23 @@ static EMPTY: IsaacRng = IsaacRng {
 
 impl IsaacRng {
     /// Create an ISAAC random number generator with a random seed.
-    pub fn new() -> IsaacRng {
+    ///
+    /// This reads randomness from the operating system (via `OSRng`)
+    /// which may fail, any error is propagated via the `IoResult`
+    /// return value.
+    pub fn new() -> IoResult<IsaacRng> {
         let mut rng = EMPTY;
-
+        let mut os_rng = try!(OSRng::new());
         unsafe {
             let ptr = rng.rsl.as_mut_ptr();
 
             raw::mut_buf_as_slice(ptr as *mut u8, mem::size_of_val(&rng.rsl), |slice| {
-                OSRng::new().fill_bytes(slice);
+                os_rng.fill_bytes(slice);
             })
         }
 
         rng.init(true);
-        rng
+        Ok(rng)
     }
 
     /// Create an ISAAC random number generator using the default
@@ -249,19 +254,24 @@ static EMPTY_64: Isaac64Rng = Isaac64Rng {
 impl Isaac64Rng {
     /// Create a 64-bit ISAAC random number generator with a random
     /// seed.
-    pub fn new() -> Isaac64Rng {
+    ///
+    /// This reads randomness from the operating system (via `OSRng`)
+    /// which may fail, any error is propagated via the `IoResult`
+    /// return value.
+    pub fn new() -> IoResult<Isaac64Rng> {
         let mut rng = EMPTY_64;
+        let mut os_rng = try!(OSRng::new());
 
         unsafe {
             let ptr = rng.rsl.as_mut_ptr();
 
             raw::mut_buf_as_slice(ptr as *mut u8, mem::size_of_val(&rng.rsl), |slice| {
-                OSRng::new().fill_bytes(slice);
+                os_rng.fill_bytes(slice);
             })
         }
 
         rng.init(true);
-        rng
+        Ok(rng)
     }
 
     /// Create a 64-bit ISAAC random number generator using the
@@ -430,19 +440,19 @@ impl<'a> SeedableRng<&'a [u64]> for Isaac64Rng {
 #[cfg(test)]
 mod test {
     use super::{IsaacRng, Isaac64Rng};
-    use {Rng, SeedableRng, OSRng};
+    use {Rng, SeedableRng, task_rng};
     use std::slice;
 
     #[test]
     fn test_rng_32_rand_seeded() {
-        let s = OSRng::new().gen_vec::<u32>(256);
+        let s = task_rng().gen_vec::<u32>(256);
         let mut ra: IsaacRng = SeedableRng::from_seed(s.as_slice());
         let mut rb: IsaacRng = SeedableRng::from_seed(s.as_slice());
         assert_eq!(ra.gen_ascii_str(100u), rb.gen_ascii_str(100u));
     }
     #[test]
     fn test_rng_64_rand_seeded() {
-        let s = OSRng::new().gen_vec::<u64>(256);
+        let s = task_rng().gen_vec::<u64>(256);
         let mut ra: Isaac64Rng = SeedableRng::from_seed(s.as_slice());
         let mut rb: Isaac64Rng = SeedableRng::from_seed(s.as_slice());
         assert_eq!(ra.gen_ascii_str(100u), rb.gen_ascii_str(100u));
@@ -465,7 +475,7 @@ mod test {
 
     #[test]
     fn test_rng_32_reseed() {
-        let s = OSRng::new().gen_vec::<u32>(256);
+        let s = task_rng().gen_vec::<u32>(256);
         let mut r: IsaacRng = SeedableRng::from_seed(s.as_slice());
         let string1 = r.gen_ascii_str(100);
 
@@ -476,7 +486,7 @@ mod test {
     }
     #[test]
     fn test_rng_64_reseed() {
-        let s = OSRng::new().gen_vec::<u64>(256);
+        let s = task_rng().gen_vec::<u64>(256);
         let mut r: Isaac64Rng = SeedableRng::from_seed(s.as_slice());
         let string1 = r.gen_ascii_str(100);
 
diff --git a/src/librand/lib.rs b/src/librand/lib.rs
index d9920501ab0..56d52e78466 100644
--- a/src/librand/lib.rs
+++ b/src/librand/lib.rs
@@ -78,6 +78,7 @@ println!("{:?}", tuple_ptr)
 #[phase(syntax, link)] extern crate log;
 
 use std::cast;
+use std::io::IoResult;
 use std::kinds::marker;
 use std::local_data;
 use std::str;
@@ -403,7 +404,7 @@ pub trait SeedableRng<Seed>: Rng {
 /// appropriate.
 #[deprecated="use `task_rng` or `StdRng::new`"]
 pub fn rng() -> StdRng {
-    StdRng::new()
+    StdRng::new().unwrap()
 }
 
 /// The standard RNG. This is designed to be efficient on the current
@@ -425,9 +426,12 @@ impl StdRng {
     /// number of random numbers, or doesn't need the utmost speed for
     /// generating each number, `task_rng` and/or `random` may be more
     /// appropriate.
+    ///
+    /// Reading the randomness from the OS may fail, and any error is
+    /// propagated via the `IoResult` return value.
     #[cfg(not(target_word_size="64"))]
-    pub fn new() -> StdRng {
-        StdRng { rng: IsaacRng::new() }
+    pub fn new() -> IoResult<StdRng> {
+        IsaacRng::new().map(|r| StdRng { rng: r })
     }
     /// Create a randomly seeded instance of `StdRng`.
     ///
@@ -437,9 +441,12 @@ impl StdRng {
     /// number of random numbers, or doesn't need the utmost speed for
     /// generating each number, `task_rng` and/or `random` may be more
     /// appropriate.
+    ///
+    /// Reading the randomness from the OS may fail, and any error is
+    /// propagated via the `IoResult` return value.
     #[cfg(target_word_size="64")]
-    pub fn new() -> StdRng {
-        StdRng { rng: Isaac64Rng::new() }
+    pub fn new() -> IoResult<StdRng> {
+        Isaac64Rng::new().map(|r| StdRng { rng: r })
     }
 }
 
@@ -477,7 +484,10 @@ impl<'a> SeedableRng<&'a [uint]> for StdRng {
 /// This will read randomness from the operating system to seed the
 /// generator.
 pub fn weak_rng() -> XorShiftRng {
-    XorShiftRng::new()
+    match XorShiftRng::new() {
+        Ok(r) => r,
+        Err(e) => fail!("weak_rng: failed to create seeded RNG: {}", e)
+    }
 }
 
 /// An Xorshift[1] random number
@@ -539,10 +549,10 @@ impl SeedableRng<[u32, .. 4]> for XorShiftRng {
 
 impl XorShiftRng {
     /// Create an xor shift random number generator with a random seed.
-    pub fn new() -> XorShiftRng {
+    pub fn new() -> IoResult<XorShiftRng> {
         let mut s = [0u8, ..16];
+        let mut r = try!(OSRng::new());
         loop {
-            let mut r = OSRng::new();
             r.fill_bytes(s);
 
             if !s.iter().all(|x| *x == 0) {
@@ -550,7 +560,7 @@ impl XorShiftRng {
             }
         }
         let s: [u32, ..4] = unsafe { cast::transmute(s) };
-        SeedableRng::from_seed(s)
+        Ok(SeedableRng::from_seed(s))
     }
 }
 
@@ -559,7 +569,10 @@ struct TaskRngReseeder;
 
 impl reseeding::Reseeder<StdRng> for TaskRngReseeder {
     fn reseed(&mut self, rng: &mut StdRng) {
-        *rng = StdRng::new();
+        *rng = match StdRng::new() {
+            Ok(r) => r,
+            Err(e) => fail!("could not reseed task_rng: {}", e)
+        }
     }
 }
 static TASK_RNG_RESEED_THRESHOLD: uint = 32_768;
@@ -596,7 +609,11 @@ local_data_key!(TASK_RNG_KEY: ~TaskRngInner)
 pub fn task_rng() -> TaskRng {
     local_data::get_mut(TASK_RNG_KEY, |rng| match rng {
         None => {
-            let mut rng = ~reseeding::ReseedingRng::new(StdRng::new(),
+            let r = match StdRng::new() {
+                Ok(r) => r,
+                Err(e) => fail!("could not initialize task_rng: {}", e)
+            };
+            let mut rng = ~reseeding::ReseedingRng::new(r,
                                                         TASK_RNG_RESEED_THRESHOLD,
                                                         TaskRngReseeder);
             let ptr = &mut *rng as *mut TaskRngInner;
@@ -679,7 +696,7 @@ pub struct Closed01<F>(F);
 #[cfg(test)]
 mod test {
     use std::slice;
-    use super::{Rng, task_rng, random, OSRng, SeedableRng, StdRng};
+    use super::{Rng, task_rng, random, SeedableRng, StdRng};
 
     struct ConstRng { i: u64 }
     impl Rng for ConstRng {
@@ -841,7 +858,7 @@ mod test {
 
     #[test]
     fn test_std_rng_seeded() {
-        let s = OSRng::new().gen_vec::<uint>(256);
+        let s = task_rng().gen_vec::<uint>(256);
         let mut ra: StdRng = SeedableRng::from_seed(s.as_slice());
         let mut rb: StdRng = SeedableRng::from_seed(s.as_slice());
         assert_eq!(ra.gen_ascii_str(100u), rb.gen_ascii_str(100u));
@@ -849,7 +866,7 @@ mod test {
 
     #[test]
     fn test_std_rng_reseed() {
-        let s = OSRng::new().gen_vec::<uint>(256);
+        let s = task_rng().gen_vec::<uint>(256);
         let mut r: StdRng = SeedableRng::from_seed(s.as_slice());
         let string1 = r.gen_ascii_str(100);
 
@@ -872,7 +889,7 @@ mod bench {
 
     #[bench]
     fn rand_xorshift(bh: &mut BenchHarness) {
-        let mut rng = XorShiftRng::new();
+        let mut rng = XorShiftRng::new().unwrap();
         bh.iter(|| {
             for _ in range(0, RAND_BENCH_N) {
                 rng.gen::<uint>();
@@ -883,7 +900,7 @@ mod bench {
 
     #[bench]
     fn rand_isaac(bh: &mut BenchHarness) {
-        let mut rng = IsaacRng::new();
+        let mut rng = IsaacRng::new().unwrap();
         bh.iter(|| {
             for _ in range(0, RAND_BENCH_N) {
                 rng.gen::<uint>();
@@ -894,7 +911,7 @@ mod bench {
 
     #[bench]
     fn rand_isaac64(bh: &mut BenchHarness) {
-        let mut rng = Isaac64Rng::new();
+        let mut rng = Isaac64Rng::new().unwrap();
         bh.iter(|| {
             for _ in range(0, RAND_BENCH_N) {
                 rng.gen::<uint>();
@@ -905,7 +922,7 @@ mod bench {
 
     #[bench]
     fn rand_std(bh: &mut BenchHarness) {
-        let mut rng = StdRng::new();
+        let mut rng = StdRng::new().unwrap();
         bh.iter(|| {
             for _ in range(0, RAND_BENCH_N) {
                 rng.gen::<uint>();
@@ -916,7 +933,7 @@ mod bench {
 
     #[bench]
     fn rand_shuffle_100(bh: &mut BenchHarness) {
-        let mut rng = XorShiftRng::new();
+        let mut rng = XorShiftRng::new().unwrap();
         let x : &mut[uint] = [1,..100];
         bh.iter(|| {
             rng.shuffle_mut(x);
diff --git a/src/librand/os.rs b/src/librand/os.rs
index 6ba919a7e65..86960af7a4d 100644
--- a/src/librand/os.rs
+++ b/src/librand/os.rs
@@ -17,7 +17,7 @@ pub use self::imp::OSRng;
 mod imp {
     use Rng;
     use reader::ReaderRng;
-    use std::io::File;
+    use std::io::{IoResult, File};
 
     /// A random number generator that retrieves randomness straight from
     /// the operating system. Platform sources:
@@ -35,12 +35,11 @@ mod imp {
 
     impl OSRng {
         /// Create a new `OSRng`.
-        pub fn new() -> OSRng {
-            let reader = File::open(&Path::new("/dev/urandom"));
-            let reader = reader.ok().expect("Error opening /dev/urandom");
+        pub fn new() -> IoResult<OSRng> {
+            let reader = try!(File::open(&Path::new("/dev/urandom")));
             let reader_rng = ReaderRng::new(reader);
 
-            OSRng { inner: reader_rng }
+            Ok(OSRng { inner: reader_rng })
         }
     }
 
@@ -61,6 +60,7 @@ mod imp {
 mod imp {
     use Rng;
     use std::cast;
+    use std::io::{IoResult, IoError};
     use std::libc::{c_ulong, DWORD, BYTE, LPCSTR, BOOL};
     use std::os;
     use std::rt::stack;
@@ -99,7 +99,7 @@ mod imp {
 
     impl OSRng {
         /// Create a new `OSRng`.
-        pub fn new() -> OSRng {
+        pub fn new() -> IoResult<OSRng> {
             let mut hcp = 0;
             let mut ret = unsafe {
                 CryptAcquireContextA(&mut hcp, 0 as LPCSTR, 0 as LPCSTR,
@@ -143,9 +143,10 @@ mod imp {
             }
 
             if ret == 0 {
-                fail!("couldn't create context: {}", os::last_os_error());
+                Err(IoError::last_error())
+            } else {
+                Ok(OSRng { hcryptprov: hcp })
             }
-            OSRng { hcryptprov: hcp }
         }
     }
 
@@ -191,7 +192,7 @@ mod test {
 
     #[test]
     fn test_os_rng() {
-        let mut r = OSRng::new();
+        let mut r = OSRng::new().unwrap();
 
         r.next_u32();
         r.next_u64();
@@ -213,7 +214,7 @@ mod test {
 
                 // deschedule to attempt to interleave things as much
                 // as possible (XXX: is this a good test?)
-                let mut r = OSRng::new();
+                let mut r = OSRng::new().unwrap();
                 task::deschedule();
                 let mut v = [0u8, .. 1000];
 
diff --git a/src/librand/reseeding.rs b/src/librand/reseeding.rs
index 70108d76b56..c069c7389c2 100644
--- a/src/librand/reseeding.rs
+++ b/src/librand/reseeding.rs
@@ -100,12 +100,12 @@ impl<S, R: SeedableRng<S>, Rsdr: Reseeder<R>>
 /// # Example
 ///
 /// ```rust
-/// use rand::{Rng, SeedableRng};
+/// use rand::{Rng, SeedableRng, StdRng};
 /// use rand::reseeding::{Reseeder, ReseedingRng};
 ///
 /// struct TickTockReseeder { tick: bool }
-/// impl Reseeder<rand::StdRng> for TickTockReseeder {
-///     fn reseed(&mut self, rng: &mut rand::StdRng) {
+/// impl Reseeder<StdRng> for TickTockReseeder {
+///     fn reseed(&mut self, rng: &mut StdRng) {
 ///         let val = if self.tick {0} else {1};
 ///         rng.reseed(&[val]);
 ///         self.tick = !self.tick;
@@ -113,7 +113,9 @@ impl<S, R: SeedableRng<S>, Rsdr: Reseeder<R>>
 /// }
 /// fn main() {
 ///     let rsdr = TickTockReseeder { tick: true };
-///     let mut rng = ReseedingRng::new(rand::StdRng::new(), 10, rsdr);
+///
+///     let inner = StdRng::new().unwrap();
+///     let mut rng = ReseedingRng::new(inner, 10, rsdr);
 ///
 ///     // this will repeat, because it gets reseeded very regularly.
 ///     println!("{}", rng.gen_ascii_str(100));
diff --git a/src/libstd/fmt/num.rs b/src/libstd/fmt/num.rs
index b10a9584df9..4d1d08551a6 100644
--- a/src/libstd/fmt/num.rs
+++ b/src/libstd/fmt/num.rs
@@ -400,31 +400,31 @@ mod bench {
 
         #[bench]
         fn format_bin(bh: &mut BenchHarness) {
-            let mut rng = XorShiftRng::new();
+            let mut rng = XorShiftRng::new().unwrap();
             bh.iter(|| { format!("{:t}", rng.gen::<uint>()); })
         }
 
         #[bench]
         fn format_oct(bh: &mut BenchHarness) {
-            let mut rng = XorShiftRng::new();
+            let mut rng = XorShiftRng::new().unwrap();
             bh.iter(|| { format!("{:o}", rng.gen::<uint>()); })
         }
 
         #[bench]
         fn format_dec(bh: &mut BenchHarness) {
-            let mut rng = XorShiftRng::new();
+            let mut rng = XorShiftRng::new().unwrap();
             bh.iter(|| { format!("{:u}", rng.gen::<uint>()); })
         }
 
         #[bench]
         fn format_hex(bh: &mut BenchHarness) {
-            let mut rng = XorShiftRng::new();
+            let mut rng = XorShiftRng::new().unwrap();
             bh.iter(|| { format!("{:x}", rng.gen::<uint>()); })
         }
 
         #[bench]
         fn format_base_36(bh: &mut BenchHarness) {
-            let mut rng = XorShiftRng::new();
+            let mut rng = XorShiftRng::new().unwrap();
             bh.iter(|| { format!("{}", radix(rng.gen::<uint>(), 36)); })
         }
     }
@@ -436,31 +436,31 @@ mod bench {
 
         #[bench]
         fn format_bin(bh: &mut BenchHarness) {
-            let mut rng = XorShiftRng::new();
+            let mut rng = XorShiftRng::new().unwrap();
             bh.iter(|| { format!("{:t}", rng.gen::<int>()); })
         }
 
         #[bench]
         fn format_oct(bh: &mut BenchHarness) {
-            let mut rng = XorShiftRng::new();
+            let mut rng = XorShiftRng::new().unwrap();
             bh.iter(|| { format!("{:o}", rng.gen::<int>()); })
         }
 
         #[bench]
         fn format_dec(bh: &mut BenchHarness) {
-            let mut rng = XorShiftRng::new();
+            let mut rng = XorShiftRng::new().unwrap();
             bh.iter(|| { format!("{:d}", rng.gen::<int>()); })
         }
 
         #[bench]
         fn format_hex(bh: &mut BenchHarness) {
-            let mut rng = XorShiftRng::new();
+            let mut rng = XorShiftRng::new().unwrap();
             bh.iter(|| { format!("{:x}", rng.gen::<int>()); })
         }
 
         #[bench]
         fn format_base_36(bh: &mut BenchHarness) {
-            let mut rng = XorShiftRng::new();
+            let mut rng = XorShiftRng::new().unwrap();
             bh.iter(|| { format!("{}", radix(rng.gen::<int>(), 36)); })
         }
     }
diff --git a/src/libstd/io/fs.rs b/src/libstd/io/fs.rs
index b6efdfad9d3..410b841545e 100644
--- a/src/libstd/io/fs.rs
+++ b/src/libstd/io/fs.rs
@@ -1286,7 +1286,7 @@ mod test {
         use rand::{StdRng, Rng};
 
         let mut bytes = [0, ..1024];
-        StdRng::new().fill_bytes(bytes);
+        StdRng::new().unwrap().fill_bytes(bytes);
 
         let tmpdir = tmpdir();
 
diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs
index 50f8b0b28c4..403e0e48fd5 100644
--- a/src/libstd/io/mod.rs
+++ b/src/libstd/io/mod.rs
@@ -216,6 +216,8 @@ use container::Container;
 use fmt;
 use int;
 use iter::Iterator;
+use libc;
+use os;
 use option::{Option, Some, None};
 use path::Path;
 use result::{Ok, Err, Result};
@@ -290,6 +292,88 @@ pub struct IoError {
     pub detail: Option<~str>
 }
 
+impl IoError {
+    /// Convert an `errno` value into an `IoError`.
+    ///
+    /// If `detail` is `true`, the `detail` field of the `IoError`
+    /// struct is filled with an allocated string describing the error
+    /// in more detail, retrieved from the operating system.
+    pub fn from_errno(errno: uint, detail: bool) -> IoError {
+        #[cfg(windows)]
+        fn get_err(errno: i32) -> (IoErrorKind, &'static str) {
+            match errno {
+                libc::EOF => (EndOfFile, "end of file"),
+                libc::ERROR_NO_DATA => (BrokenPipe, "the pipe is being closed"),
+                libc::ERROR_FILE_NOT_FOUND => (FileNotFound, "file not found"),
+                libc::ERROR_INVALID_NAME => (InvalidInput, "invalid file name"),
+                libc::WSAECONNREFUSED => (ConnectionRefused, "connection refused"),
+                libc::WSAECONNRESET => (ConnectionReset, "connection reset"),
+                libc::WSAEACCES => (PermissionDenied, "permission denied"),
+                libc::WSAEWOULDBLOCK => {
+                    (ResourceUnavailable, "resource temporarily unavailable")
+                }
+                libc::WSAENOTCONN => (NotConnected, "not connected"),
+                libc::WSAECONNABORTED => (ConnectionAborted, "connection aborted"),
+                libc::WSAEADDRNOTAVAIL => (ConnectionRefused, "address not available"),
+                libc::WSAEADDRINUSE => (ConnectionRefused, "address in use"),
+                libc::ERROR_BROKEN_PIPE => (EndOfFile, "the pipe has ended"),
+
+                // libuv maps this error code to EISDIR. we do too. if it is found
+                // to be incorrect, we can add in some more machinery to only
+                // return this message when ERROR_INVALID_FUNCTION after certain
+                // win32 calls.
+                libc::ERROR_INVALID_FUNCTION => (InvalidInput,
+                                                 "illegal operation on a directory"),
+
+                _ => (OtherIoError, "unknown error")
+            }
+        }
+
+        #[cfg(not(windows))]
+        fn get_err(errno: i32) -> (IoErrorKind, &'static str) {
+            // FIXME: this should probably be a bit more descriptive...
+            match errno {
+                libc::EOF => (EndOfFile, "end of file"),
+                libc::ECONNREFUSED => (ConnectionRefused, "connection refused"),
+                libc::ECONNRESET => (ConnectionReset, "connection reset"),
+                libc::EPERM | libc::EACCES =>
+                    (PermissionDenied, "permission denied"),
+                libc::EPIPE => (BrokenPipe, "broken pipe"),
+                libc::ENOTCONN => (NotConnected, "not connected"),
+                libc::ECONNABORTED => (ConnectionAborted, "connection aborted"),
+                libc::EADDRNOTAVAIL => (ConnectionRefused, "address not available"),
+                libc::EADDRINUSE => (ConnectionRefused, "address in use"),
+                libc::ENOENT => (FileNotFound, "no such file or directory"),
+                libc::EISDIR => (InvalidInput, "illegal operation on a directory"),
+
+                // These two constants can have the same value on some systems, but
+                // different values on others, so we can't use a match clause
+                x if x == libc::EAGAIN || x == libc::EWOULDBLOCK =>
+                    (ResourceUnavailable, "resource temporarily unavailable"),
+
+                _ => (OtherIoError, "unknown error")
+            }
+        }
+
+        let (kind, desc) = get_err(errno as i32);
+        IoError {
+            kind: kind,
+            desc: desc,
+            detail: if detail {Some(os::error_string(errno))} else {None},
+        }
+    }
+
+    /// Retrieve the last error to occur as a (detailed) IoError.
+    ///
+    /// This uses the OS `errno`, and so there should not be any task
+    /// descheduling or migration (other than that performed by the
+    /// operating system) between the call(s) for which errors are
+    /// being checked and the call of this function.
+    pub fn last_error() -> IoError {
+        IoError::from_errno(os::errno() as uint, true)
+    }
+}
+
 impl fmt::Show for IoError {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         try!(fmt.buf.write_str(self.desc));
diff --git a/src/libstd/num/strconv.rs b/src/libstd/num/strconv.rs
index dc49da415a4..15c7b251fa7 100644
--- a/src/libstd/num/strconv.rs
+++ b/src/libstd/num/strconv.rs
@@ -821,31 +821,31 @@ mod bench {
 
         #[bench]
         fn to_str_bin(bh: &mut BenchHarness) {
-            let mut rng = XorShiftRng::new();
+            let mut rng = XorShiftRng::new().unwrap();
             bh.iter(|| { rng.gen::<uint>().to_str_radix(2); })
         }
 
         #[bench]
         fn to_str_oct(bh: &mut BenchHarness) {
-            let mut rng = XorShiftRng::new();
+            let mut rng = XorShiftRng::new().unwrap();
             bh.iter(|| { rng.gen::<uint>().to_str_radix(8); })
         }
 
         #[bench]
         fn to_str_dec(bh: &mut BenchHarness) {
-            let mut rng = XorShiftRng::new();
+            let mut rng = XorShiftRng::new().unwrap();
             bh.iter(|| { rng.gen::<uint>().to_str_radix(10); })
         }
 
         #[bench]
         fn to_str_hex(bh: &mut BenchHarness) {
-            let mut rng = XorShiftRng::new();
+            let mut rng = XorShiftRng::new().unwrap();
             bh.iter(|| { rng.gen::<uint>().to_str_radix(16); })
         }
 
         #[bench]
         fn to_str_base_36(bh: &mut BenchHarness) {
-            let mut rng = XorShiftRng::new();
+            let mut rng = XorShiftRng::new().unwrap();
             bh.iter(|| { rng.gen::<uint>().to_str_radix(36); })
         }
     }
@@ -857,31 +857,31 @@ mod bench {
 
         #[bench]
         fn to_str_bin(bh: &mut BenchHarness) {
-            let mut rng = XorShiftRng::new();
+            let mut rng = XorShiftRng::new().unwrap();
             bh.iter(|| { rng.gen::<int>().to_str_radix(2); })
         }
 
         #[bench]
         fn to_str_oct(bh: &mut BenchHarness) {
-            let mut rng = XorShiftRng::new();
+            let mut rng = XorShiftRng::new().unwrap();
             bh.iter(|| { rng.gen::<int>().to_str_radix(8); })
         }
 
         #[bench]
         fn to_str_dec(bh: &mut BenchHarness) {
-            let mut rng = XorShiftRng::new();
+            let mut rng = XorShiftRng::new().unwrap();
             bh.iter(|| { rng.gen::<int>().to_str_radix(10); })
         }
 
         #[bench]
         fn to_str_hex(bh: &mut BenchHarness) {
-            let mut rng = XorShiftRng::new();
+            let mut rng = XorShiftRng::new().unwrap();
             bh.iter(|| { rng.gen::<int>().to_str_radix(16); })
         }
 
         #[bench]
         fn to_str_base_36(bh: &mut BenchHarness) {
-            let mut rng = XorShiftRng::new();
+            let mut rng = XorShiftRng::new().unwrap();
             bh.iter(|| { rng.gen::<int>().to_str_radix(36); })
         }
     }
@@ -893,7 +893,7 @@ mod bench {
 
         #[bench]
         fn float_to_str(bh: &mut BenchHarness) {
-            let mut rng = XorShiftRng::new();
+            let mut rng = XorShiftRng::new().unwrap();
             bh.iter(|| { f64::to_str(rng.gen()); })
         }
     }
diff --git a/src/libstd/os.rs b/src/libstd/os.rs
index 5485aaec085..a5583afb31d 100644
--- a/src/libstd/os.rs
+++ b/src/libstd/os.rs
@@ -663,10 +663,12 @@ pub fn errno() -> uint {
     }
 }
 
-/// Get a string representing the platform-dependent last error
-pub fn last_os_error() -> ~str {
+/// Return the string corresponding to an `errno()` value of `errnum`.
+pub fn error_string(errnum: uint) -> ~str {
+    return strerror(errnum);
+
     #[cfg(unix)]
-    fn strerror() -> ~str {
+    fn strerror(errnum: uint) -> ~str {
         #[cfg(target_os = "macos")]
         #[cfg(target_os = "android")]
         #[cfg(target_os = "freebsd")]
@@ -702,7 +704,7 @@ pub fn last_os_error() -> ~str {
 
         let p = buf.as_mut_ptr();
         unsafe {
-            if strerror_r(errno() as c_int, p, buf.len() as libc::size_t) < 0 {
+            if strerror_r(errnum as c_int, p, buf.len() as libc::size_t) < 0 {
                 fail!("strerror_r failure");
             }
 
@@ -711,7 +713,7 @@ pub fn last_os_error() -> ~str {
     }
 
     #[cfg(windows)]
-    fn strerror() -> ~str {
+    fn strerror(errnum: uint) -> ~str {
         use libc::types::os::arch::extra::DWORD;
         use libc::types::os::arch::extra::LPWSTR;
         use libc::types::os::arch::extra::LPVOID;
@@ -735,7 +737,6 @@ pub fn last_os_error() -> ~str {
         // This value is calculated from the macro
         // MAKELANGID(LANG_SYSTEM_DEFAULT, SUBLANG_SYS_DEFAULT)
         let langId = 0x0800 as DWORD;
-        let err = errno() as DWORD;
 
         let mut buf = [0 as WCHAR, ..TMPBUF_SZ];
 
@@ -743,7 +744,7 @@ pub fn last_os_error() -> ~str {
             let res = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM |
                                      FORMAT_MESSAGE_IGNORE_INSERTS,
                                      ptr::mut_null(),
-                                     err,
+                                     errnum as DWORD,
                                      langId,
                                      buf.as_mut_ptr(),
                                      buf.len() as DWORD,
@@ -751,18 +752,21 @@ pub fn last_os_error() -> ~str {
             if res == 0 {
                 // Sometimes FormatMessageW can fail e.g. system doesn't like langId,
                 let fm_err = errno();
-                return format!("OS Error {} (FormatMessageW() returned error {})", err, fm_err);
+                return format!("OS Error {} (FormatMessageW() returned error {})", errnum, fm_err);
             }
 
             let msg = str::from_utf16(str::truncate_utf16_at_nul(buf));
             match msg {
-                Some(msg) => format!("OS Error {}: {}", err, msg),
-                None => format!("OS Error {} (FormatMessageW() returned invalid UTF-16)", err),
+                Some(msg) => format!("OS Error {}: {}", errnum, msg),
+                None => format!("OS Error {} (FormatMessageW() returned invalid UTF-16)", errnum),
             }
         }
     }
+}
 
-    strerror()
+/// Get a string representing the platform-dependent last error
+pub fn last_os_error() -> ~str {
+    error_string(errno() as uint)
 }
 
 static mut EXIT_STATUS: AtomicInt = INIT_ATOMIC_INT;
diff --git a/src/libstd/rt/task.rs b/src/libstd/rt/task.rs
index d9700ea9980..0f90135512c 100644
--- a/src/libstd/rt/task.rs
+++ b/src/libstd/rt/task.rs
@@ -435,7 +435,7 @@ mod test {
     #[test]
     fn rng() {
         use rand::{StdRng, Rng};
-        let mut r = StdRng::new();
+        let mut r = StdRng::new().unwrap();
         let _ = r.next_u32();
     }
 
diff --git a/src/test/bench/noise.rs b/src/test/bench/noise.rs
index 4954f083b36..babf3f737fb 100644
--- a/src/test/bench/noise.rs
+++ b/src/test/bench/noise.rs
@@ -41,7 +41,7 @@ struct Noise2DContext {
 
 impl Noise2DContext {
     fn new() -> Noise2DContext {
-        let mut rng = StdRng::new();
+        let mut rng = StdRng::new().unwrap();
 
         let mut rgradients = [Vec2 { x: 0.0, y: 0.0 }, ..256];
         for x in rgradients.mut_iter() {