Skip to content

Commit 9c8813f

Browse files
committed
Guarantee that native tasks wait for children
There was a scheduling race where a child may not increment the global task count before the parent exits, and the parent would then think that there are no more tasks left.
1 parent b432e82 commit 9c8813f

File tree

2 files changed

+33
-1
lines changed

2 files changed

+33
-1
lines changed

src/libnative/task.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,11 @@ pub fn spawn_opts(opts: TaskOpts, f: proc()) {
7272
let task = task;
7373
let ops = ops();
7474

75+
// Note that this increment must happen *before* the spawn in order to
76+
// guarantee that if this task exits it will always end up waiting for the
77+
// spawned task to exit.
78+
bookeeping::increment();
79+
7580
// Spawning a new OS thread guarantees that __morestack will never get
7681
// triggered, but we must manually set up the actual stack bounds once this
7782
// function starts executing. This raises the lower limit by a bit because
@@ -88,7 +93,6 @@ pub fn spawn_opts(opts: TaskOpts, f: proc()) {
8893
let mut ops = ops;
8994
ops.stack_bounds = Some((my_stack - stack + 1024, my_stack));
9095

91-
bookeeping::increment();
9296
let mut f = Some(f);
9397
let mut task = task;
9498
task.put_runtime(ops as ~rt::Runtime);
+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// xfail-fast
12+
13+
extern mod native;
14+
15+
static mut set: bool = false;
16+
17+
#[start]
18+
fn start(argc: int, argv: **u8) -> int {
19+
// make sure that native::start always waits for all children to finish
20+
do native::start(argc, argv) {
21+
do spawn {
22+
unsafe { set = true; }
23+
}
24+
};
25+
26+
// if we didn't set the global, then return a nonzero code
27+
if unsafe {set} {0} else {1}
28+
}

0 commit comments

Comments
 (0)