about summary refs log tree commit diff
path: root/src/libstd/sys
diff options
context:
space:
mode:
authorGiles Cope <gilescope@gmail.com>2017-06-19 23:00:45 +0100
committerGiles Cope <gilescope@gmail.com>2017-06-19 23:00:45 +0100
commit4b8446a2333ca7a22a594a24e3eb541cf5265792 (patch)
tree84ac480b1cb9c6172ec41fb17aa1e526e163ed38 /src/libstd/sys
parent1ec1b1f1eb1bd0ea1f9396ade1015d00f9149a1d (diff)
parent04145943a25c3b8c7e7d7fe8c2efb04f259c25fb (diff)
downloadrust-4b8446a2333ca7a22a594a24e3eb541cf5265792.tar.gz
rust-4b8446a2333ca7a22a594a24e3eb541cf5265792.zip
Merge remote-tracking branch 'upstream/master'
Diffstat (limited to 'src/libstd/sys')
-rw-r--r--src/libstd/sys/redox/os_str.rs27
-rw-r--r--src/libstd/sys/unix/condvar.rs34
-rw-r--r--src/libstd/sys/unix/os_str.rs27
-rw-r--r--src/libstd/sys/unix/pipe.rs29
-rw-r--r--src/libstd/sys/windows/os_str.rs26
5 files changed, 112 insertions, 31 deletions
diff --git a/src/libstd/sys/redox/os_str.rs b/src/libstd/sys/redox/os_str.rs
index c2bba07f68c..c54286353a9 100644
--- a/src/libstd/sys/redox/os_str.rs
+++ b/src/libstd/sys/redox/os_str.rs
@@ -12,10 +12,11 @@
 /// a `Vec<u8>`/`[u8]`.
 
 use borrow::Cow;
-use fmt::{self, Debug};
+use fmt;
 use str;
 use mem;
 use sys_common::{AsInner, IntoInner};
+use std_unicode::lossy::Utf8Lossy;
 
 #[derive(Clone, Hash)]
 pub struct Buf {
@@ -26,15 +27,27 @@ pub struct Slice {
     pub inner: [u8]
 }
 
-impl Debug for Slice {
-    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
-        self.to_string_lossy().fmt(formatter)
+impl fmt::Debug for Slice {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Debug::fmt(&Utf8Lossy::from_bytes(&self.inner), formatter)
     }
 }
 
-impl Debug for Buf {
-    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
-        self.as_slice().fmt(formatter)
+impl fmt::Display for Slice {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Display::fmt(&Utf8Lossy::from_bytes(&self.inner), formatter)
+    }
+}
+
+impl fmt::Debug for Buf {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Debug::fmt(self.as_slice(), formatter)
+    }
+}
+
+impl fmt::Display for Buf {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Display::fmt(self.as_slice(), formatter)
     }
 }
 
diff --git a/src/libstd/sys/unix/condvar.rs b/src/libstd/sys/unix/condvar.rs
index 27b9f131d12..b9ea573b323 100644
--- a/src/libstd/sys/unix/condvar.rs
+++ b/src/libstd/sys/unix/condvar.rs
@@ -23,6 +23,14 @@ const TIMESPEC_MAX: libc::timespec = libc::timespec {
     tv_nsec: 1_000_000_000 - 1,
 };
 
+fn saturating_cast_to_time_t(value: u64) -> libc::time_t {
+    if value > <libc::time_t>::max_value() as u64 {
+        <libc::time_t>::max_value()
+    } else {
+        value as libc::time_t
+    }
+}
+
 impl Condvar {
     pub const fn new() -> Condvar {
         // Might be moved and address is changing it is better to avoid
@@ -79,8 +87,7 @@ impl Condvar {
 
         // Nanosecond calculations can't overflow because both values are below 1e9.
         let nsec = dur.subsec_nanos() as libc::c_long + now.tv_nsec as libc::c_long;
-        // FIXME: Casting u64 into time_t could truncate the value.
-        let sec = (dur.as_secs() as libc::time_t)
+        let sec = saturating_cast_to_time_t(dur.as_secs())
             .checked_add((nsec / 1_000_000_000) as libc::time_t)
             .and_then(|s| s.checked_add(now.tv_sec));
         let nsec = nsec % 1_000_000_000;
@@ -100,10 +107,29 @@ impl Condvar {
     // https://github.com/llvm-mirror/libcxx/blob/release_35/src/condition_variable.cpp#L46
     // https://github.com/llvm-mirror/libcxx/blob/release_35/include/__mutex_base#L367
     #[cfg(any(target_os = "macos", target_os = "ios", target_os = "android"))]
-    pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
+    pub unsafe fn wait_timeout(&self, mutex: &Mutex, mut dur: Duration) -> bool {
         use ptr;
         use time::Instant;
 
+        // 1000 years
+        let max_dur = Duration::from_secs(1000 * 365 * 86400);
+
+        if dur > max_dur {
+            // OSX implementation of `pthread_cond_timedwait` is buggy
+            // with super long durations. When duration is greater than
+            // 0x100_0000_0000_0000 seconds, `pthread_cond_timedwait`
+            // in macOS Sierra return error 316.
+            //
+            // This program demonstrates the issue:
+            // https://gist.github.com/stepancheg/198db4623a20aad2ad7cddb8fda4a63c
+            //
+            // To work around this issue, and possible bugs of other OSes, timeout
+            // is clamped to 1000 years, which is allowable per the API of `wait_timeout`
+            // because of spurious wakeups.
+
+            dur = max_dur;
+        }
+
         // First, figure out what time it currently is, in both system and
         // stable time.  pthread_cond_timedwait uses system time, but we want to
         // report timeout based on stable time.
@@ -116,7 +142,7 @@ impl Condvar {
                    (sys_now.tv_usec * 1000) as libc::c_long;
         let extra = (nsec / 1_000_000_000) as libc::time_t;
         let nsec = nsec % 1_000_000_000;
-        let seconds = dur.as_secs() as libc::time_t;
+        let seconds = saturating_cast_to_time_t(dur.as_secs());
 
         let timeout = sys_now.tv_sec.checked_add(extra).and_then(|s| {
             s.checked_add(seconds)
diff --git a/src/libstd/sys/unix/os_str.rs b/src/libstd/sys/unix/os_str.rs
index f5b942d3343..777db17e3e1 100644
--- a/src/libstd/sys/unix/os_str.rs
+++ b/src/libstd/sys/unix/os_str.rs
@@ -12,10 +12,11 @@
 /// a `Vec<u8>`/`[u8]`.
 
 use borrow::Cow;
-use fmt::{self, Debug};
+use fmt;
 use str;
 use mem;
 use sys_common::{AsInner, IntoInner};
+use std_unicode::lossy::Utf8Lossy;
 
 #[derive(Clone, Hash)]
 pub struct Buf {
@@ -26,15 +27,27 @@ pub struct Slice {
     pub inner: [u8]
 }
 
-impl Debug for Slice {
-    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
-        self.to_string_lossy().fmt(formatter)
+impl fmt::Debug for Slice {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Debug::fmt(&Utf8Lossy::from_bytes(&self.inner), formatter)
     }
 }
 
-impl Debug for Buf {
-    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
-        self.as_slice().fmt(formatter)
+impl fmt::Display for Slice {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Display::fmt(&Utf8Lossy::from_bytes(&self.inner), formatter)
+    }
+}
+
+impl fmt::Debug for Buf {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Debug::fmt(self.as_slice(), formatter)
+    }
+}
+
+impl fmt::Display for Buf {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Display::fmt(self.as_slice(), formatter)
     }
 }
 
diff --git a/src/libstd/sys/unix/pipe.rs b/src/libstd/sys/unix/pipe.rs
index 706256ff10e..ca5ef4bcfc5 100644
--- a/src/libstd/sys/unix/pipe.rs
+++ b/src/libstd/sys/unix/pipe.rs
@@ -11,8 +11,9 @@
 use io;
 use libc::{self, c_int};
 use mem;
-use sys::{cvt, cvt_r};
+use sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering};
 use sys::fd::FileDesc;
+use sys::{cvt, cvt_r};
 
 ////////////////////////////////////////////////////////////////////////////////
 // Anonymous pipes
@@ -21,6 +22,9 @@ use sys::fd::FileDesc;
 pub struct AnonPipe(FileDesc);
 
 pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> {
+    weak! { fn pipe2(*mut c_int, c_int) -> c_int }
+    static INVALID: AtomicBool = ATOMIC_BOOL_INIT;
+
     let mut fds = [0; 2];
 
     // Unfortunately the only known way right now to create atomically set the
@@ -31,13 +35,26 @@ pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> {
                 target_os = "freebsd",
                 target_os = "linux",
                 target_os = "netbsd",
-                target_os = "openbsd"))
+                target_os = "openbsd")) &&
+       !INVALID.load(Ordering::SeqCst)
     {
-        weak! { fn pipe2(*mut c_int, c_int) -> c_int }
+
         if let Some(pipe) = pipe2.get() {
-            cvt(unsafe { pipe(fds.as_mut_ptr(), libc::O_CLOEXEC) })?;
-            return Ok((AnonPipe(FileDesc::new(fds[0])),
-                       AnonPipe(FileDesc::new(fds[1]))));
+            // Note that despite calling a glibc function here we may still
+            // get ENOSYS. Glibc has `pipe2` since 2.9 and doesn't try to
+            // emulate on older kernels, so if you happen to be running on
+            // an older kernel you may see `pipe2` as a symbol but still not
+            // see the syscall.
+            match cvt(unsafe { pipe(fds.as_mut_ptr(), libc::O_CLOEXEC) }) {
+                Ok(_) => {
+                    return Ok((AnonPipe(FileDesc::new(fds[0])),
+                               AnonPipe(FileDesc::new(fds[1]))));
+                }
+                Err(ref e) if e.raw_os_error() == Some(libc::ENOSYS) => {
+                    INVALID.store(true, Ordering::SeqCst);
+                }
+                Err(e) => return Err(e),
+            }
         }
     }
     cvt(unsafe { libc::pipe(fds.as_mut_ptr()) })?;
diff --git a/src/libstd/sys/windows/os_str.rs b/src/libstd/sys/windows/os_str.rs
index f401e7b35c8..3eb4582718b 100644
--- a/src/libstd/sys/windows/os_str.rs
+++ b/src/libstd/sys/windows/os_str.rs
@@ -12,7 +12,7 @@
 /// wrapper around the "WTF-8" encoding; see the `wtf8` module for more.
 
 use borrow::Cow;
-use fmt::{self, Debug};
+use fmt;
 use sys_common::wtf8::{Wtf8, Wtf8Buf};
 use mem;
 use sys_common::{AsInner, IntoInner};
@@ -34,9 +34,15 @@ impl AsInner<Wtf8> for Buf {
     }
 }
 
-impl Debug for Buf {
-    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
-        self.as_slice().fmt(formatter)
+impl fmt::Debug for Buf {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Debug::fmt(self.as_slice(), formatter)
+    }
+}
+
+impl fmt::Display for Buf {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Display::fmt(self.as_slice(), formatter)
     }
 }
 
@@ -44,9 +50,15 @@ pub struct Slice {
     pub inner: Wtf8
 }
 
-impl Debug for Slice {
-    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
-        self.inner.fmt(formatter)
+impl fmt::Debug for Slice {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Debug::fmt(&self.inner, formatter)
+    }
+}
+
+impl fmt::Display for Slice {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Display::fmt(&self.inner, formatter)
     }
 }