-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Open
Labels
A-tokioArea: The main tokio crateArea: The main tokio crateC-bugCategory: This is a bug.Category: This is a bug.M-syncModule: tokio/syncModule: tokio/sync
Description
Version
Latest (1.48.0)
Platform
Doesn't matter.
Description
Even though not documented explicitly, but the current behavior is, all values stored in the channel are dropped when the sole receiver is dropped:
tokio/tokio/src/sync/mpsc/chan.rs
Lines 490 to 526 in 5a709e3
| fn drop(&mut self) { | |
| use super::block::Read::Value; | |
| self.close(); | |
| self.inner.rx_fields.with_mut(|rx_fields_ptr| { | |
| let rx_fields = unsafe { &mut *rx_fields_ptr }; | |
| struct Guard<'a, T, S: Semaphore> { | |
| list: &'a mut list::Rx<T>, | |
| tx: &'a list::Tx<T>, | |
| sem: &'a S, | |
| } | |
| impl<'a, T, S: Semaphore> Guard<'a, T, S> { | |
| fn drain(&mut self) { | |
| // call T's destructor. | |
| while let Some(Value(_)) = self.list.pop(self.tx) { | |
| self.sem.add_permit(); | |
| } | |
| } | |
| } | |
| impl<'a, T, S: Semaphore> Drop for Guard<'a, T, S> { | |
| fn drop(&mut self) { | |
| self.drain(); | |
| } | |
| } | |
| let mut guard = Guard { | |
| list: &mut rx_fields.list, | |
| tx: &self.inner.tx, | |
| sem: &self.inner.semaphore, | |
| }; | |
| guard.drain(); | |
| }); | |
| } |
It is natural for user to consider "receiver dropped -> values dropped" an invariant.
But it doesn't hold in this sequence of event:
- Sender acquires a permit
- Receiver is dropped
- Sender publishes a value using the permit
Metadata
Metadata
Assignees
Labels
A-tokioArea: The main tokio crateArea: The main tokio crateC-bugCategory: This is a bug.Category: This is a bug.M-syncModule: tokio/syncModule: tokio/sync