]> git.lizzy.rs Git - rust.git/commitdiff
std: Fix sub-second Condvar::wait_timeout_ms
authorAlex Crichton <alex@alexcrichton.com>
Wed, 29 Jul 2015 04:13:02 +0000 (21:13 -0700)
committerAlex Crichton <alex@alexcrichton.com>
Wed, 29 Jul 2015 17:24:40 +0000 (10:24 -0700)
The API we're calling requires us to pass an absolute point in time as an
argument (`pthread_cond_timedwait`) so we call `gettimeofday` ahead of time to
then add the specified duration to. Unfortuantely the current "add the duration"
logic forgot to take into account the current time's sub-second precision (e.g.
the `tv_usec` field was ignored), causing sub-second duration waits to return
spuriously.

src/libstd/sys/unix/condvar.rs

index c8708190a2e18c6f6fef8b5f3a322508a15417b7..beecb445e8d687fd6ab6aefd5804f3ec0cf68a78 100644 (file)
@@ -60,21 +60,22 @@ pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
         let r = ffi::gettimeofday(&mut sys_now, ptr::null_mut());
         debug_assert_eq!(r, 0);
 
+        let nsec = dur.extra_nanos() as libc::c_long +
+                   (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.secs() as libc::time_t;
-        let timeout = match sys_now.tv_sec.checked_add(seconds) {
-            Some(sec) => {
-                libc::timespec {
-                    tv_sec: sec,
-                    tv_nsec: dur.extra_nanos() as libc::c_long,
-                }
-            }
-            None => {
-                libc::timespec {
-                    tv_sec: <libc::time_t>::max_value(),
-                    tv_nsec: 1_000_000_000 - 1,
-                }
+
+        let timeout = sys_now.tv_sec.checked_add(extra).and_then(|s| {
+            s.checked_add(seconds)
+        }).map(|s| {
+            libc::timespec { tv_sec: s, tv_nsec: nsec }
+        }).unwrap_or_else(|| {
+            libc::timespec {
+                tv_sec: <libc::time_t>::max_value(),
+                tv_nsec: 1_000_000_000 - 1,
             }
-        };
+        });
 
         // And wait!
         let r = ffi::pthread_cond_timedwait(self.inner.get(), mutex::raw(mutex),