@@ -22,6 +22,7 @@ use ops::Drop;
22
22
use kinds:: Owned ;
23
23
use rt:: sched:: { Scheduler , Coroutine } ;
24
24
use rt:: local:: Local ;
25
+ use rt:: rtio:: EventLoop ;
25
26
use unstable:: intrinsics:: { atomic_xchg, atomic_load} ;
26
27
use util:: Void ;
27
28
use comm:: { GenericChan , GenericSmartChan , GenericPort , Peekable } ;
@@ -172,9 +173,17 @@ impl<T> PortOne<T> {
172
173
}
173
174
STATE_ONE => {
174
175
// Channel is closed. Switch back and check the data.
176
+ // NB: We have to drop back into the scheduler event loop here
177
+ // instead of switching immediately back or we could end up
178
+ // triggering infinite recursion on the scheduler's stack.
175
179
let task: ~Coroutine = cast:: transmute ( task_as_state) ;
176
- let sched = Local :: take :: < Scheduler > ( ) ;
177
- sched. resume_task_immediately ( task) ;
180
+ let task = Cell ( task) ;
181
+ let mut sched = Local :: take :: < Scheduler > ( ) ;
182
+ do sched. event_loop . callback {
183
+ let sched = Local :: take :: < Scheduler > ( ) ;
184
+ sched. resume_task_immediately ( task. take ( ) ) ;
185
+ }
186
+ Local :: put ( sched) ;
178
187
}
179
188
_ => util:: unreachable ( )
180
189
}
@@ -614,5 +623,15 @@ mod test {
614
623
}
615
624
}
616
625
}
626
+
627
+ #[ test]
628
+ fn recv_a_lot( ) {
629
+ // Regression test that we don't run out of stack in scheduler context
630
+ do run_in_newsched_task {
631
+ let ( port, chan) = stream( ) ;
632
+ for 10000 . times { chan. send( ( ) ) }
633
+ for 10000 . times { port. recv( ) }
634
+ }
635
+ }
617
636
}
618
637
0 commit comments