about summary refs log tree commit diff
path: root/src/libstd/rt/comm.rs
diff options
context:
space:
mode:
authorBrian Anderson <banderson@mozilla.com>2013-05-29 18:22:28 -0700
committerBrian Anderson <banderson@mozilla.com>2013-05-29 18:22:28 -0700
commitf4ed554ddbd2dacfaa5dcc1dda99a3121f8cf2a4 (patch)
tree45f24486e6f2d6d39928462e40d2c4b5f3de2154 /src/libstd/rt/comm.rs
parentbd30285c8467b33b6fea16be79198f7492107af3 (diff)
parent134bb0f3eeed69bbf6dc672bbbfbc802f1a018a9 (diff)
downloadrust-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.rs23
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() }
+        }
+    }
 }