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

If tokio::sync::Notify notify() is invoked prior to tokio::sync::Notify notfied().await, then the call to notified().await will result in perpetual blocking without being notified. #6952

Open
ybbh opened this issue Nov 5, 2024 · 1 comment
Labels
A-tokio Area: The main tokio crate C-bug Category: This is a bug. M-sync Module: tokio/sync

Comments

@ybbh
Copy link

ybbh commented Nov 5, 2024

Version
List the versions of all tokio crates you are using.

cargo tree | grep tokio

tokio-notify v0.1.0 
└── tokio v1.41.0
    └── tokio-macros v2.4.0 (proc-macro)

Platform
The output of uname -a (UNIX), or version and 32 or 64-bit (Windows)

Linux ybbh-ubuntu24 6.8.0-48-generic #48-Ubuntu SMP PREEMPT_DYNAMIC Fri Sep 27 14:04:52 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux

Description

If notify() is invoked prior to notfied().await, then the call to notified().await will result in perpetual blocking without the possibility of being notified.

I tried this code:

use tokio::sync::Notify;
use std::sync::Arc;
use std::thread;
use std::thread::sleep;
use std::time::Duration;

fn main() {
    let notify = Arc::new(Notify::new());
    let notify2 = notify.clone();
    let thd = thread::spawn(move ||{
        let runtime = tokio::runtime::Builder::new_current_thread()
            .enable_all()
            .build()
            .unwrap();
        runtime.block_on(async move {
            println!("waiting notification");
            notify2.notified().await;
            println!("notified");
        })
    });
    // uncomment this line would be OK, when notify() is called after notfied().await
    // sleep(Duration::from_secs(1));
    notify.notify_waiters();
    println!("sending notification");
    thd.join().unwrap();
}

I expected to see this happen:

The call to notified().await should be notified.
Or if it is unsafe to invoke notify() before notified().await, this should be clearly documented to avoid potential issues.

Instead, this happened:

The call to notified().await cannot be notified.

@ybbh ybbh added A-tokio Area: The main tokio crate C-bug Category: This is a bug. labels Nov 5, 2024
@Darksonn Darksonn added the M-sync Module: tokio/sync label Nov 6, 2024
@Darksonn
Copy link
Contributor

Darksonn commented Nov 6, 2024

Your program sleeps forever for the same reason as this program:

use tokio::sync::Notify;

#[tokio::main]
async fn main() {
    let notify = Notify::new();
    notify.notify_waiters();
    notify.notified().await;
    // never reaches this line
}

It has nothing to do with being inside/outside the runtime.

@ybbh ybbh changed the title If tokio::sync::Notify notify() is invoked outside the runtime and prior to tokio::sync::Notify notfied().await, then the call to notified().await will result in perpetual blocking without being notified. If tokio::sync::Notify notify() is invoked prior to tokio::sync::Notify notfied().await, then the call to notified().await will result in perpetual blocking without being notified. Nov 6, 2024
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. M-sync Module: tokio/sync
Projects
None yet
Development

No branches or pull requests

2 participants