Skip to content

Commit 80f92f5

Browse files
committed
std: Relax an assertion in oneshot selection
The assertion was erroneously ensuring that there was no data on the port when the port had selection aborted on it. This assertion was written in error because it's possible for data to be waiting on a port, even after it was disconnected. When aborting selection, if we see that there's data on the port, then we return true that data is available on the port. Closes #12802
1 parent 3316a0e commit 80f92f5

File tree

2 files changed

+64
-7
lines changed

2 files changed

+64
-7
lines changed

src/libstd/comm/oneshot.rs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -339,14 +339,19 @@ impl<T: Send> Packet<T> {
339339
DATA => Ok(true),
340340

341341
// If the other end has hung up, then we have complete ownership
342-
// of the port. We need to check to see if there was an upgrade
343-
// requested, and if so, the other end needs to have its selection
344-
// aborted.
342+
// of the port. First, check if there was data waiting for us. This
343+
// is possible if the other end sent something and then hung up.
344+
//
345+
// We then need to check to see if there was an upgrade requested,
346+
// and if so, the upgraded port needs to have its selection aborted.
345347
DISCONNECTED => {
346-
assert!(self.data.is_none());
347-
match mem::replace(&mut self.upgrade, SendUsed) {
348-
GoUp(port) => Err(port),
349-
_ => Ok(true),
348+
if self.data.is_some() {
349+
Ok(true)
350+
} else {
351+
match mem::replace(&mut self.upgrade, SendUsed) {
352+
GoUp(port) => Err(port),
353+
_ => Ok(true),
354+
}
350355
}
351356
}
352357

src/libstd/comm/select.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -597,4 +597,56 @@ mod test {
597597
unsafe { h.add(); }
598598
assert_eq!(s.wait2(false), h.id);
599599
})
600+
601+
test!(fn oneshot_data_waiting() {
602+
let (p, c) = Chan::new();
603+
let (p2, c2) = Chan::new();
604+
spawn(proc() {
605+
select! {
606+
() = p.recv() => {}
607+
}
608+
c2.send(());
609+
});
610+
611+
for _ in range(0, 100) { task::deschedule() }
612+
c.send(());
613+
p2.recv();
614+
})
615+
616+
test!(fn stream_data_waiting() {
617+
let (p, c) = Chan::new();
618+
let (p2, c2) = Chan::new();
619+
c.send(());
620+
c.send(());
621+
p.recv();
622+
p.recv();
623+
spawn(proc() {
624+
select! {
625+
() = p.recv() => {}
626+
}
627+
c2.send(());
628+
});
629+
630+
for _ in range(0, 100) { task::deschedule() }
631+
c.send(());
632+
p2.recv();
633+
})
634+
635+
test!(fn shared_data_waiting() {
636+
let (p, c) = Chan::new();
637+
let (p2, c2) = Chan::new();
638+
drop(c.clone());
639+
c.send(());
640+
p.recv();
641+
spawn(proc() {
642+
select! {
643+
() = p.recv() => {}
644+
}
645+
c2.send(());
646+
});
647+
648+
for _ in range(0, 100) { task::deschedule() }
649+
c.send(());
650+
p2.recv();
651+
})
600652
}

0 commit comments

Comments
 (0)