Skip to content

Unexpected behavior using std::thread::park_timeout on OSX #37440

@nastevens

Description

@nastevens

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    O-macosOperating system: macOST-libs-apiRelevant to the library API team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions