Skip to content

Commit e823bb3

Browse files
committed
---
yaml --- r: 63030 b: refs/heads/snap-stage3 c: f7e242a h: refs/heads/master v: v3
1 parent 5bc2115 commit e823bb3

File tree

2 files changed

+37
-2
lines changed

2 files changed

+37
-2
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
refs/heads/master: 2d28d645422c1617be58c8ca7ad9a457264ca850
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
4-
refs/heads/snap-stage3: 2e6d51f9cea14ff271223855454034b27ced4ce9
4+
refs/heads/snap-stage3: f7e242ab8a4ceffd87ec339086b7f8510e94aef1
55
refs/heads/try: 7b78b52e602bb3ea8174f9b2006bff3315f03ef9
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b

branches/snap-stage3/src/libstd/rt/sched.rs

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,7 @@ pub impl Coroutine {
536536

537537
priv fn build_start_wrapper(start: ~fn()) -> ~fn() {
538538
// XXX: The old code didn't have this extra allocation
539+
let start_cell = Cell(start);
539540
let wrapper: ~fn() = || {
540541
// This is the first code to execute after the initial
541542
// context switch to the task. The previous context may
@@ -547,7 +548,19 @@ pub impl Coroutine {
547548
let sched = Local::unsafe_borrow::<Scheduler>();
548549
let task = (*sched).current_task.get_mut_ref();
549550
// FIXME #6141: shouldn't neet to put `start()` in another closure
550-
task.task.run(||start());
551+
let start_cell = Cell(start_cell.take());
552+
do task.task.run {
553+
// N.B. Removing `start` from the start wrapper closure
554+
// by emptying a cell is critical for correctness. The ~Task
555+
// pointer, and in turn the closure used to initialize the first
556+
// call frame, is destroyed in scheduler context, not task context.
557+
// So any captured closures must not contain user-definable dtors
558+
// that expect to be in task context. By moving `start` out of
559+
// the closure, all the user code goes out of scope while
560+
// the task is still running.
561+
let start = start_cell.take();
562+
start();
563+
};
551564
}
552565

553566
let sched = Local::take::<Scheduler>();
@@ -840,4 +853,26 @@ mod test {
840853

841854
}
842855

856+
#[test]
857+
fn start_closure_dtor() {
858+
use ops::Drop;
859+
860+
// Regression test that the `start` task entrypoint can contain dtors
861+
// that use task resources
862+
do run_in_newsched_task {
863+
struct S { field: () }
864+
865+
impl Drop for S {
866+
fn finalize(&self) {
867+
let _foo = @0;
868+
}
869+
}
870+
871+
let s = S { field: () };
872+
873+
do spawntask {
874+
let _ss = &s;
875+
}
876+
}
877+
}
843878
}

0 commit comments

Comments
 (0)