-
-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Description
Version
└── tokio v1.44.2
└── tokio-macros v2.5.0 (proc-macro)
Platform
Linux beroal 6.14.3-arch1-1 #1 SMP PREEMPT_DYNAMIC Sun, 20 Apr 2025 12:38:52 +0000 x86_64 GNU/Linux
Description
Hi. When exploring whether Receiver
can detect that the corresponding Sender
s are dropped, I found the following behavior demonstrated by the program below.
use std::error::Error;
use tokio::sync::watch;
fn new_watch<T: Clone>(initial: T)
-> Result<(watch::Sender<T>, watch::Receiver<T>), watch::error::SendError<T>> {
let (tx, rx) = watch::channel(initial.clone());
let () = tx.send(initial)?;
Ok((tx, rx))
}
async fn has_changed() -> Result<(), Box<dyn Error>> {
let (_tx, rx) = new_watch(()).map_err(Box::new)?;
rx.has_changed().map_err(Box::new)?;
Ok(())
}
async fn drop_sender_then_has_changed() -> Result<(), Box<dyn Error>> {
let rx = new_watch(()).map_err(Box::new)?.1;
rx.has_changed().map_err(Box::new)?;
Ok(())
}
async fn drop_sender_then_changed() -> Result<(), Box<dyn Error>> {
let mut rx = new_watch(()).map_err(Box::new)?.1;
rx.changed().await.map_err(Box::new)?;
Ok(())
}
#[tokio::main]
async fn main() {
eprintln!("has_changed: {:?}", has_changed().await);
eprintln!(
"drop_sender_then_has_changed: {:?}",
drop_sender_then_has_changed().await,
);
eprintln!(
"drop_sender_then_changed: {:?}",
drop_sender_then_changed().await,
);
}
drop_sender_then_has_changed
returns an error. The specification of watch::Receiver::has_changed
says,
Returns an error if the channel has been closed.
However, not all receivers have been dropped. It's likely that the fact that all senders have been dropped is responsible for the error because my has_changed
does not return an error.
The specification of watch::Receiver::changed
says,
This method returns an error if and only if the
Sender
is dropped.
All senders have been dropped, yet drop_sender_then_changed
does not return an error.
Personally, I think that neither has_changed
nor changed
should return an error. If you allow for two Sender
s, why wouldn't you allow for zero Sender
s?
P.S. I suggest that you move the definition of “closed channel” to the top-level page instead of copying it to methods (such as watch::Sender::is_closed
and watch::Sender::send
).