diff options
| author | Brian Anderson <banderson@mozilla.com> | 2013-05-29 18:22:28 -0700 |
|---|---|---|
| committer | Brian Anderson <banderson@mozilla.com> | 2013-05-29 18:22:28 -0700 |
| commit | f4ed554ddbd2dacfaa5dcc1dda99a3121f8cf2a4 (patch) | |
| tree | 45f24486e6f2d6d39928462e40d2c4b5f3de2154 /src/libstd/rt/comm.rs | |
| parent | bd30285c8467b33b6fea16be79198f7492107af3 (diff) | |
| parent | 134bb0f3eeed69bbf6dc672bbbfbc802f1a018a9 (diff) | |
| download | rust-f4ed554ddbd2dacfaa5dcc1dda99a3121f8cf2a4.tar.gz rust-f4ed554ddbd2dacfaa5dcc1dda99a3121f8cf2a4.zip | |
Merge remote-tracking branch 'brson/io' into incoming
Conflicts: src/libstd/rt/sched.rs
Diffstat (limited to 'src/libstd/rt/comm.rs')
| -rw-r--r-- | src/libstd/rt/comm.rs | 23 |
1 files changed, 20 insertions, 3 deletions
diff --git a/src/libstd/rt/comm.rs b/src/libstd/rt/comm.rs index 54db03b6069..ebfa9e263ef 100644 --- a/src/libstd/rt/comm.rs +++ b/src/libstd/rt/comm.rs @@ -22,6 +22,7 @@ use ops::Drop; use kinds::Owned; use rt::sched::{Scheduler, Coroutine}; use rt::local::Local; +use rt::rtio::EventLoop; use unstable::intrinsics::{atomic_xchg, atomic_load}; use util::Void; use comm::{GenericChan, GenericSmartChan, GenericPort, Peekable}; @@ -158,7 +159,7 @@ impl<T> PortOne<T> { // Switch to the scheduler to put the ~Task into the Packet state. let sched = Local::take::<Scheduler>(); - do sched.deschedule_running_task_and_then |task| { + do sched.deschedule_running_task_and_then |sched, task| { unsafe { // Atomically swap the task pointer into the Packet state, issuing // an acquire barrier to prevent reordering of the subsequent read @@ -172,9 +173,15 @@ impl<T> PortOne<T> { } STATE_ONE => { // Channel is closed. Switch back and check the data. + // NB: We have to drop back into the scheduler event loop here + // instead of switching immediately back or we could end up + // triggering infinite recursion on the scheduler's stack. let task: ~Coroutine = cast::transmute(task_as_state); - let sched = Local::take::<Scheduler>(); - sched.resume_task_immediately(task); + let task = Cell(task); + do sched.event_loop.callback { + let sched = Local::take::<Scheduler>(); + sched.resume_task_immediately(task.take()); + } } _ => util::unreachable() } @@ -614,5 +621,15 @@ mod test { } } } + + #[test] + fn recv_a_lot() { + // Regression test that we don't run out of stack in scheduler context + do run_in_newsched_task { + let (port, chan) = stream(); + for 10000.times { chan.send(()) } + for 10000.times { port.recv() } + } + } } |
