diff options
| author | bors <bors@rust-lang.org> | 2014-04-01 11:11:51 -0700 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2014-04-01 11:11:51 -0700 |
| commit | b71c02e512fcfe18ea7a5a8a99ac758b4fa564a6 (patch) | |
| tree | 7842aad2f7ad07256764e22d6ab2fad0b6f624ed /src/libstd | |
| parent | b8ef9fd9c9f642ce7b8aed82782a1ed745d08d64 (diff) | |
| parent | bc7a2d72a3fea324fa432de9b6ce6073302d3d8c (diff) | |
| download | rust-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/libstd')
| -rw-r--r-- | src/libstd/fmt/num.rs | 20 | ||||
| -rw-r--r-- | src/libstd/io/fs.rs | 2 | ||||
| -rw-r--r-- | src/libstd/io/mod.rs | 84 | ||||
| -rw-r--r-- | src/libstd/num/strconv.rs | 22 | ||||
| -rw-r--r-- | src/libstd/os.rs | 26 | ||||
| -rw-r--r-- | src/libstd/rt/task.rs | 2 |
6 files changed, 122 insertions, 34 deletions
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(); } |
