Skip to content

Commit

Permalink
auto merge of #13115 : huonw/rust/rand-errors, r=alexcrichton
Browse files Browse the repository at this point in the history
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).
  • Loading branch information
bors committed Apr 1, 2014
2 parents b8ef9fd + bc7a2d7 commit b71c02e
Show file tree
Hide file tree
Showing 20 changed files with 216 additions and 158 deletions.
4 changes: 2 additions & 2 deletions src/libcollections/deque.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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() {
Expand Down
7 changes: 6 additions & 1 deletion src/libgreen/sched.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
4 changes: 1 addition & 3 deletions src/libnative/io/addrinfo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}

Expand Down
67 changes: 2 additions & 65 deletions src/libnative/io/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion src/libnative/io/net.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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))]
Expand Down
2 changes: 1 addition & 1 deletion src/libnative/io/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 ||
Expand Down
2 changes: 1 addition & 1 deletion src/librand/distributions/exponential.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(|| {
Expand Down
6 changes: 3 additions & 3 deletions src/librand/distributions/gamma.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion src/librand/distributions/normal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(|| {
Expand Down
34 changes: 22 additions & 12 deletions src/librand/isaac.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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));
Expand All @@ -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);

Expand All @@ -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);

Expand Down
Loading

0 comments on commit b71c02e

Please sign in to comment.