diff --git a/src/libsync/comm/mod.rs b/src/libsync/comm/mod.rs index e9a303634fe37..2aec39521255e 100644 --- a/src/libsync/comm/mod.rs +++ b/src/libsync/comm/mod.rs @@ -2098,4 +2098,23 @@ mod sync_tests { }); assert_eq!(rx.recv(), 1); } #[ignore(reason = "flaky on libnative")]) + + test!(fn issue_15761() { + fn repro() { + let (tx1, rx1) = sync_channel::<()>(3); + let (tx2, rx2) = sync_channel::<()>(3); + + spawn(proc() { + rx1.recv(); + tx2.try_send(()).unwrap(); + }); + + tx1.try_send(()).unwrap(); + rx2.recv(); + } + + for _ in range(0u, 100) { + repro() + } + }) } diff --git a/src/libsync/comm/sync.rs b/src/libsync/comm/sync.rs index cc3c2197c13f0..1d5a7d6ed9f58 100644 --- a/src/libsync/comm/sync.rs +++ b/src/libsync/comm/sync.rs @@ -218,9 +218,15 @@ impl Packet { } } else { // If the buffer has some space and the capacity isn't 0, then we - // just enqueue the data for later retrieval. + // just enqueue the data for later retrieval, ensuring to wake up + // any blocked receiver if there is one. assert!(state.buf.size() < state.buf.cap()); state.buf.enqueue(t); + match mem::replace(&mut state.blocker, NoneBlocked) { + BlockedReceiver(task) => wakeup(task, guard), + NoneBlocked => {} + BlockedSender(..) => unreachable!(), + } Ok(()) } }