Skip to content

Commit 43b2c47

Browse files
committed
std: Fix sub-second Condvar::wait_timeout_ms
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.
1 parent 68fc2d9 commit 43b2c47

File tree

1 file changed

+14
-13
lines changed

1 file changed

+14
-13
lines changed

src/libstd/sys/unix/condvar.rs

+14-13
Original file line numberDiff line numberDiff line change
@@ -60,21 +60,22 @@ impl Condvar {
6060
let r = ffi::gettimeofday(&mut sys_now, ptr::null_mut());
6161
debug_assert_eq!(r, 0);
6262

63+
let nsec = dur.extra_nanos() as libc::c_long +
64+
(sys_now.tv_usec * 1000) as libc::c_long;
65+
let extra = (nsec / 1_000_000_000) as libc::time_t;
66+
let nsec = nsec % 1_000_000_000;
6367
let seconds = dur.secs() as libc::time_t;
64-
let timeout = match sys_now.tv_sec.checked_add(seconds) {
65-
Some(sec) => {
66-
libc::timespec {
67-
tv_sec: sec,
68-
tv_nsec: dur.extra_nanos() as libc::c_long,
69-
}
70-
}
71-
None => {
72-
libc::timespec {
73-
tv_sec: <libc::time_t>::max_value(),
74-
tv_nsec: 1_000_000_000 - 1,
75-
}
68+
69+
let timeout = sys_now.tv_sec.checked_add(extra).and_then(|s| {
70+
s.checked_add(seconds)
71+
}).map(|s| {
72+
libc::timespec { tv_sec: s, tv_nsec: nsec }
73+
}).unwrap_or_else(|| {
74+
libc::timespec {
75+
tv_sec: <libc::time_t>::max_value(),
76+
tv_nsec: 1_000_000_000 - 1,
7677
}
77-
};
78+
});
7879

7980
// And wait!
8081
let r = ffi::pthread_cond_timedwait(self.inner.get(), mutex::raw(mutex),

0 commit comments

Comments
 (0)