mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-25 14:13:38 +00:00
Fix select deschedule environment race for real this time, in light of task killing.
This commit is contained in:
parent
0d817ee869
commit
65cf75af67
@ -20,6 +20,7 @@ use rt::select::{SelectInner, SelectPortInner};
|
||||
use rt::local::Local;
|
||||
use rt::rtio::EventLoop;
|
||||
use task;
|
||||
use unstable::finally::Finally;
|
||||
use vec::{OwnedVector, MutableVector};
|
||||
|
||||
/// Trait for message-passing primitives that can be select()ed on.
|
||||
@ -57,6 +58,8 @@ pub fn select<A: Select>(ports: &mut [A]) -> uint {
|
||||
let p = Cell::new(p);
|
||||
let c = Cell::new(c);
|
||||
|
||||
do (|| {
|
||||
let c = Cell::new(c.take());
|
||||
let sched = Local::take::<Scheduler>();
|
||||
do sched.deschedule_running_task_and_then |sched, task| {
|
||||
let task_handles = task.make_selectable(ports.len());
|
||||
@ -73,11 +76,13 @@ pub fn select<A: Select>(ports: &mut [A]) -> uint {
|
||||
let c = Cell::new(c.take());
|
||||
do sched.event_loop.callback { c.take().send_deferred(()) }
|
||||
}
|
||||
|
||||
}).finally {
|
||||
let p = Cell::new(p.take());
|
||||
// Unkillable is necessary not because getting killed is dangerous here,
|
||||
// but to force the recv not to use the same kill-flag that we used for
|
||||
// selecting. Otherwise a user-sender could spuriously wakeup us here.
|
||||
do task::unkillable { p.take().recv(); }
|
||||
}
|
||||
|
||||
// Task resumes. Now unblock ourselves from all the ports we blocked on.
|
||||
// If the success index wasn't reset, 'take' will just take all of them.
|
||||
|
Loading…
Reference in New Issue
Block a user