Skip to content

Commit ee37fdc

Browse files
Nemo157cramertj
authored andcommitted
Don't wake oneshot sender after it has been dropped
1 parent 89100f7 commit ee37fdc

File tree

2 files changed

+17
-0
lines changed

2 files changed

+17
-0
lines changed

futures-channel/src/oneshot.rs

+7
Original file line numberDiff line numberDiff line change
@@ -214,12 +214,19 @@ impl<T> Inner<T> {
214214
// and deadlock might be possible, as was observed in
215215
// https://github.com/rust-lang-nursery/futures-rs/pull/219.
216216
self.complete.store(true, SeqCst);
217+
217218
if let Some(mut slot) = self.rx_task.try_lock() {
218219
if let Some(task) = slot.take() {
219220
drop(slot);
220221
task.wake();
221222
}
222223
}
224+
225+
// If we registered a task for cancel notification drop it to reduce
226+
// spurious wakeups
227+
if let Some(mut slot) = self.tx_task.try_lock() {
228+
drop(slot.take());
229+
}
223230
}
224231

225232
fn close_rx(&self) {

futures-channel/tests/oneshot.rs

+10
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use futures::channel::oneshot::{self, Sender};
44
use futures::executor::block_on;
55
use futures::future::{Future, FutureExt, poll_fn};
66
use futures::task::{Context, Poll};
7+
use futures_test::task::panic_waker_ref;
78
use std::pin::Pin;
89
use std::sync::mpsc;
910
use std::thread;
@@ -69,6 +70,15 @@ fn cancel_lots() {
6970
t.join().unwrap();
7071
}
7172

73+
#[test]
74+
fn cancel_after_sender_drop_doesnt_notify() {
75+
let (mut tx, rx) = oneshot::channel::<u32>();
76+
let mut cx = Context::from_waker(panic_waker_ref());
77+
assert_eq!(tx.poll_cancel(&mut cx), Poll::Pending);
78+
drop(tx);
79+
drop(rx);
80+
}
81+
7282
#[test]
7383
fn close() {
7484
let (mut tx, mut rx) = oneshot::channel::<u32>();

0 commit comments

Comments
 (0)