Skip to content

Commit d2e9d99

Browse files
committed
Handle failure during select nicely. Fixes #3176
1 parent 7634e29 commit d2e9d99

File tree

2 files changed

+30
-3
lines changed

2 files changed

+30
-3
lines changed

src/libcore/pipes.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -530,16 +530,20 @@ fn sender_terminate<T: send>(p: *packet<T>) {
530530
#[doc(hidden)]
531531
fn receiver_terminate<T: send>(p: *packet<T>) {
532532
let p = unsafe { &*p };
533-
assert p.header.blocked_task.is_null();
534533
match swap_state_rel(p.header.state, terminated) {
535534
empty => {
535+
assert p.header.blocked_task.is_null();
536536
// the sender will clean up
537537
}
538538
blocked => {
539-
// this shouldn't happen.
540-
fail ~"terminating a blocked packet"
539+
let old_task = swap_task(p.header.blocked_task, ptr::null());
540+
if !old_task.is_null() {
541+
rustrt::rust_task_deref(old_task);
542+
assert old_task == rustrt::rust_get_task();
543+
}
541544
}
542545
terminated | full => {
546+
assert p.header.blocked_task.is_null();
543547
// I have to clean up, use drop_glue
544548
}
545549
}

src/test/run-pass/issue-3176.rs

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import pipes::{select2, selectable};
2+
3+
fn main() {
4+
let (c,p) = pipes::stream();
5+
do task::try {
6+
let (c2,p2) = pipes::stream();
7+
do task::spawn {
8+
p2.recv();
9+
#error["brother fails"];
10+
fail;
11+
}
12+
let (c3,p3) = pipes::stream();
13+
c.send(c3);
14+
c2.send(());
15+
#error["child blocks"];
16+
let (c, p) = pipes::stream();
17+
(p, p3).select();
18+
c.send(());
19+
};
20+
#error["parent tries"];
21+
assert !p.recv().try_send(());
22+
#error("all done!");
23+
}

0 commit comments

Comments
 (0)