about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2014-01-24 10:02:27 -0800
committerAlex Crichton <alex@alexcrichton.com>2014-01-24 10:05:58 -0800
commit35e26e94d8a13ef3f24a66374aff815e370f8843 (patch)
treea9b1083e808c9b25238b213141de708c9d481285 /src
parent657e3530225410d167d7f1ee827f15bc69cd965e (diff)
downloadrust-35e26e94d8a13ef3f24a66374aff815e370f8843.tar.gz
rust-35e26e94d8a13ef3f24a66374aff815e370f8843.zip
Fix a spuriously tripped assert in select()
The race here happened when a port had its deschedule in select() canceled, but
the other chan had already been dropped. This meant that the DISCONNECTED case
was hit in abort_selection, but the to_wake cell hadn't been emptied yet (this
was done after aborting), causing an assert in abort_selection to trip.

To fix this, the to_wake cell is just emptied before abort_selection is called
(we know that we're the owner of it already).
Diffstat (limited to 'src')
-rw-r--r--src/libstd/comm/select.rs5
1 files changed, 4 insertions, 1 deletions
diff --git a/src/libstd/comm/select.rs b/src/libstd/comm/select.rs
index 6a10ac56a4e..5aa8687a5bb 100644
--- a/src/libstd/comm/select.rs
+++ b/src/libstd/comm/select.rs
@@ -199,11 +199,14 @@ impl Select {
                 if (*packet).decrement() {
                     Ok(())
                 } else {
+                    // Empty to_wake first to avoid tripping an assertion in
+                    // abort_selection in the disconnected case.
+                    let task = (*packet).to_wake.take_unwrap();
                     (*packet).abort_selection(false);
                     (*packet).selecting.store(false, SeqCst);
                     ready_index = i;
                     ready_id = (*packet).selection_id;
-                    Err((*packet).to_wake.take_unwrap())
+                    Err(task)
                 }
             });