Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tokio::time::interval is not working #6544

Closed
rcitsz opened this issue May 7, 2024 · 4 comments
Closed

tokio::time::interval is not working #6544

rcitsz opened this issue May 7, 2024 · 4 comments
Labels
A-tokio Area: The main tokio crate C-bug Category: This is a bug.

Comments

@rcitsz
Copy link

rcitsz commented May 7, 2024

Version

root@6a2e14c7eff5:~/projects/rustprj/rs-proxy/server# cargo version
cargo 1.78.0 (54d8815d0 2024-03-26)

root@6a2e14c7eff5:~/projects/rustprj/rs-proxy/server# cargo tree | grep tokio
│   │   │   │   │   │   ├── tokio v1.37.0
│   │   │   │   │   │   │   └── tokio-macros v2.2.0 (proc-macro)
│   │   │   │   │   │   ├── tokio-util v0.7.10
│   │   │   │   │   │   │   ├── tokio v1.37.0 (*)
│   │   │   │   │   ├── tokio v1.37.0 (*)
│   │   │   │   │   ├── tokio v1.37.0 (*)
│   │   │   │   │   ├── tokio-util v0.7.10 (*)
│   │   │   │   ├── tokio v1.37.0 (*)
│   │   │   │   └── tokio-io-timeout v1.2.0
│   │   │   │       └── tokio v1.37.0 (*)
│   │   │   ├── tokio v1.37.0 (*)
│   │   │   ├── tokio-stream v0.1.15
│   │   │   │   └── tokio v1.37.0 (*)
│   ├── tokio v1.37.0 (*)
│   ├── tokio-stream v0.1.15 (*)
│   │   ├── tokio v1.37.0 (*)
│   │   └── tokio-native-tls v0.3.1
│   │       └── tokio v1.37.0 (*)
│   ├── tokio v1.37.0 (*)
│   ├── tokio-native-tls v0.3.1 (*)
├── tokio v1.37.0 (*)
├── tokio-rustls v0.24.1
│   └── tokio v1.37.0 (*)

Platform

root@6a2e14c7eff5:~/projects/rustprj/rs-proxy/server# uname -a
Linux 6a2e14c7eff5 6.6.16-linuxkit #1 SMP Fri Feb 16 11:54:02 UTC 2024 aarch64 aarch64 aarch64 GNU/Linux

Description

Test code is as follows:

#[test]
fn test() {
    tokio::runtime::Runtime::new().unwrap().block_on(async {
        tokio::spawn(async move {
            let mut timer = tokio::time::interval(tokio::time::Duration::from_secs(1));
            let mut s = true; 
            loop {
                tokio::select! {
                    _= timer.tick() => {
                       println!("-----tick");
                    }
                 _= async {
                    if s {
                        s = false; // set off
                        tokio::time::sleep(tokio::time::Duration::from_secs(3)).await;  //  If comment out this line, the timer will work properly
                    }
                 } => {}
                }
            }
        })
        .await
        .unwrap();
    });
}

I expect to output the following content every second, but it doesn't work:
-----tick
-----tick
-----tick
-----tick
-----tick
-----tick
...

@rcitsz rcitsz added A-tokio Area: The main tokio crate C-bug Category: This is a bug. labels May 7, 2024
@mox692
Copy link
Member

mox692 commented May 7, 2024

After the completion of the first loop, subsequent loops are almost always expected to terminate the second arm first, so the tick print will not continue as you expected.

@Darksonn
Copy link
Contributor

Darksonn commented May 7, 2024

You need to use an if precondition instead of placing the if inside the async block. That way, the branch will be disabled instead of triggering immediately.

See the documentation on select! for more info on if preconditions.

@Darksonn Darksonn closed this as not planned Won't fix, can't repro, duplicate, stale May 7, 2024
@rcitsz
Copy link
Author

rcitsz commented May 7, 2024

@Darksonn
Thanks!
But in another form.
If the select arm is not async block but async function:

async fn waitfor(s: &mut bool) {
    if *s {
        *s = false;

       //   If comment out this line, the timer will work properly
        tokio::time::sleep(tokio::time::Duration::from_secs(3)).await;
    }
}

#[test]
fn test() {
    tokio::runtime::Runtime::new().unwrap().block_on(async {
        tokio::spawn(async move {
            let mut timer = tokio::time::interval(tokio::time::Duration::from_secs(1));
            let mut s = true; 
            loop {
                tokio::select! {
                    _= timer.tick() => {
                       println!("----tick");
                    }
                _ = waitfor(&mut s) => {}
                }
            }
        })
        .await
        .unwrap();
    });
}

@Darksonn
Copy link
Contributor

You can also await std::future::pending() to have waitfor sleep forever / until timer.tick() triggers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-tokio Area: The main tokio crate C-bug Category: This is a bug.
Projects
None yet
Development

No branches or pull requests

3 participants