Skip to content

faketime + tokio time sleep = hang #545

Description

@loynoir

bug

faketime + tokio time sleep = hang

description

  • when under build environment using faketime to enforce absolute time point

    • tokio time sleep seems dead loop

    • std thread sleep OK

  • when under build environment using faketime to enforce 30 days back

    • tokio time sleep seems dead loop

    • std thread sleep OK

  • when during sleep, timedatectl set one month back

    • tokio time sleep OK

    • std thread sleep OK

version

  • NixOS host, ArchLinux container

  • libfaketime 0.9.12-1

  • rustc 1.99.0-nightly (ad3d0bc14 2026-07-31)

  • tokio 1.53.1

reproduce

details
[package]
name = "reproduce-sleep"
version = "0.1.0"
edition = "2024"

[dependencies]
tokio = { version = "1.53.1", features = ["rt-multi-thread", "time"] }

reproduce-sleep/src/main.rs

fn std_thread_sleep(duration: std::time::Duration) {
    println!("[std_thread_sleep] Starting sleep {:?}...", &duration);
    std::thread::sleep(duration);
    println!("[std_thread_sleep] Done sleep.");
}

fn tokio_time_sleep(duration: std::time::Duration) {
    println!("[tokio_time_sleep] Starting sleep {:?}...", &duration);
    let rt = tokio::runtime::Runtime::new().expect("Failed to create Tokio runtime");
    rt.block_on(async {
        tokio::time::sleep(duration).await;
    });
    println!("[tokio_time_sleep] Done sleep.");
}

fn main() {
    let args: Vec<String> = std::env::args().collect();

    let method = args
        .get(1)
        .map(|s| s.as_str())
        .unwrap_or("--help");

    let duration = args
        .get(2)
        .and_then(|s| s.parse::<u64>().ok())
        .map(std::time::Duration::from_secs)
        .unwrap_or_else(|| std::time::Duration::from_secs(3));

    match method {
        "std_thread_sleep" => std_thread_sleep(duration),
        "tokio_time_sleep" => tokio_time_sleep(duration),
        _ => {
            eprintln!("Usage: {} [std_thread_sleep | tokio_time_sleep] [seconds]", args[0]);
            eprintln!("  seconds (optional) defaults to 3");
            std::process::exit(1);
        }
    }
}
$ cd reproduce-sleep
...
$ cargo build
...
$

actual

When under build environment using faketime to enforce absolute time point

  • tokio time sleep seems dead loop
$ FAKETIME='1970-01-01 00:00:00' \
  LD_PRELOAD=/usr/lib/faketime/libfaketimeMT.so.1 \
  ./target/debug/reproduce-sleep tokio_time_sleep 1
[tokio_time_sleep] Starting sleep 1s...
^C

When under build environment using faketime to enforce 30 days back

  • tokio time sleep seems dead loop
$ FAKETIME='-30d' \
  LD_PRELOAD=/usr/lib/faketime/libfaketimeMT.so.1 \
  ./target/debug/reproduce-sleep tokio_time_sleep 1
[tokio_time_sleep] Starting sleep 1s...
^C

expected

When under build environment using faketime to enforce absolute time point

  • std thread sleep OK
$ FAKETIME='1970-01-01 00:00:00' \
  LD_PRELOAD=/usr/lib/faketime/libfaketimeMT.so.1 \
  ./target/debug/reproduce-sleep std_thread_sleep 1
[std_thread_sleep] Starting sleep 1s...
[std_thread_sleep] Done sleep.

When under build environment using faketime to enforce 30 days back

  • std thread sleep OK
$ FAKETIME='-30d' \
  LD_PRELOAD=/usr/lib/faketime/libfaketimeMT.so.1 \
  ./target/debug/reproduce-sleep std_thread_sleep 1
[std_thread_sleep] Starting sleep 1s...
[std_thread_sleep] Done sleep.

additional

tokio time sleep and std thread sleep OK when timedatectl set one month back during sleep

timedatectl
$ ./target/debug/reproduce-sleep tokio_time_sleep 10
[tokio_time_sleep] Starting sleep 10s...
[tokio_time_sleep] Done sleep.
$ ./target/debug/reproduce-sleep std_thread_sleep 10
[std_thread_sleep] Starting sleep 10s...
[std_thread_sleep] Done sleep.

Foreach test, after start, before done, hack systemd time.

$ sudo systemctl stop systemd-timesyncd \
  && sudo timedatectl set-time "$(date "+%Y-%m-%d %H:%M:%S" -d '1 month ago')" \
  && date "+%Y-%m-%d %H:%M:%S"
...

Foreach test, after done, revert systemd time hack.

$ sudo systemctl start systemd-timesyncd \
  && date "+%Y-%m-%d %H:%M:%S"
...

related

#545

tokio-rs/tokio#8358

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions