-
Notifications
You must be signed in to change notification settings - Fork 13.7k
Description
I have encountered what I think is unexpected behavior from std::thread::park_timeout
on OSX: when called with "large" values the park_timeout
call will return immediately, instead of waiting for an unpark
call. What constitutes "large" is variable, and appears to correspond to the current value in the system monotonic clock source.
The following code reproduces the issue:
use std::thread;
use std::time::Duration;
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
use std::u64;
// "Small" value that will properly sleep until `unpark` is called.
const TEST_VALUE: u64 = 10_000u64;
// "Large" value that will return almost immediately.
// const TEST_VALUE: u64 = u64::MAX;
fn main() {
let stop = Arc::new(AtomicBool::new(false));
let stop2 = stop.clone();
let handle = thread::spawn(move || {
loop {
if stop2.load(Ordering::Relaxed) { break }
println!("Parking for 0x{:08x} millis", TEST_VALUE);
thread::park_timeout(Duration::from_millis(TEST_VALUE));
}
});
thread::sleep(Duration::new(1, 0));
stop.store(true, Ordering::Relaxed);
handle.thread().unpark();
handle.join().unwrap();
}
If you run the code above with the "small" value uncommented the internal loop only runs once, waiting for the 1-second sleep to expire before unpark
is called. But if you run with the "large" value uncommented, the internal loop runs a very large number of times as each call to thread::park_timeout
returns almost immediately.
As noted above, the actual value of "large" decreases over time, I believe based on u64::MAX - (current_monotonic_time)
. I unfortunately couldn't come up with a way to prove this is the case.
I've seen this behavior on OSX Yosemite and Sierra.
Edit: this happens on 1.11, 1.12, beta, and nightly.