Skip to content

Commit 4df07c9

Browse files
committed
---
yaml --- r: 142594 b: refs/heads/try2 c: f7e242a h: refs/heads/master v: v3
1 parent 93158c3 commit 4df07c9

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
@@ -5,7 +5,7 @@ refs/heads/snap-stage3: 78a7676898d9f80ab540c6df5d4c9ce35bb50463
55
refs/heads/try: 519addf6277dbafccbb4159db4b710c37eaa2ec5
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b
8-
refs/heads/try2: 2e6d51f9cea14ff271223855454034b27ced4ce9
8+
refs/heads/try2: f7e242ab8a4ceffd87ec339086b7f8510e94aef1
99
refs/heads/dist-snap: ba4081a5a8573875fed17545846f6f6902c8ba8d
1010
refs/tags/release-0.2: c870d2dffb391e14efb05aa27898f1f6333a9596
1111
refs/tags/release-0.3: b5f0d0f648d9a6153664837026ba1be43d3e2503

branches/try2/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)