about summary refs log tree commit diff
path: root/src/libstd
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/libstd
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/libstd')
-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
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();
     }