mirror of
https://github.com/rust-lang/rust.git
synced 2026-05-17 05:25:37 +03:00
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.
This commit is contained in:
@@ -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,
|
||||
}
|
||||
|
||||
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,
|
||||
}
|
||||
None => {
|
||||
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),
|
||||
|
||||
Reference in New Issue
Block a user