about summary refs log tree commit diff
path: root/src/libnative
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2013-12-15 00:42:21 -0800
committerAlex Crichton <alex@alexcrichton.com>2013-12-24 19:59:54 -0800
commit51c03c1f35f6b076928a1e5b94ec81e6d00c3ac2 (patch)
tree5503ef16e6be59f8a0c8948fe347d48be9267a47 /src/libnative
parent282f3d99a5ad85acbc58c03b5dfcdabf649c0c85 (diff)
downloadrust-51c03c1f35f6b076928a1e5b94ec81e6d00c3ac2.tar.gz
rust-51c03c1f35f6b076928a1e5b94ec81e6d00c3ac2.zip
green: Properly wait for main before shutdown
There was a race in the code previously where schedulers would *immediately*
shut down after spawning the main task (because the global task count would
still be 0). This fixes the logic by blocking the sched pool task in receving on
a port instead of spawning a task into the pool to receive on a port.

The modifications necessary were to have a "simple task" running by the time the
code is executing, but this is a simple enough thing to implement and I forsee
this being necessary to have implemented in the future anyway.
Diffstat (limited to 'src/libnative')
-rw-r--r--src/libnative/lib.rs25
-rw-r--r--src/libnative/task.rs10
2 files changed, 17 insertions, 18 deletions
diff --git a/src/libnative/lib.rs b/src/libnative/lib.rs
index 44b66a7804d..60ae239ee97 100644
--- a/src/libnative/lib.rs
+++ b/src/libnative/lib.rs
@@ -33,15 +33,16 @@
 //    answer is that you don't need them)
 
 use std::os;
+use std::rt::local::Local;
+use std::rt::task::Task;
 use std::rt;
-use stdtask = std::rt::task;
 
 pub mod io;
 pub mod task;
 
 
 // XXX: this should not exist here
-#[cfg(stage0, notready)]
+#[cfg(stage0)]
 #[lang = "start"]
 pub fn lang_start(main: *u8, argc: int, argv: **u8) -> int {
     use std::cast;
@@ -72,9 +73,13 @@ pub fn lang_start(main: *u8, argc: int, argv: **u8) -> int {
 /// exited.
 pub fn start(argc: int, argv: **u8, main: proc()) -> int {
     rt::init(argc, argv);
-    let exit_code = run(main);
+    let mut exit_code = None;
+    let mut main = Some(main);
+    task::new().run(|| {
+        exit_code = Some(run(main.take_unwrap()));
+    });
     unsafe { rt::cleanup(); }
-    return exit_code;
+    return exit_code.unwrap();
 }
 
 /// Executes a procedure on the current thread in a Rust task context.
@@ -82,11 +87,11 @@ pub fn start(argc: int, argv: **u8, main: proc()) -> int {
 /// This function has all of the same details as `start` except for a different
 /// number of arguments.
 pub fn run(main: proc()) -> int {
-    // Create a task, run the procedure in it, and then wait for everything.
-    task::run(task::new(), main);
-
-    // Block this OS task waiting for everything to finish.
-    unsafe { stdtask::wait_for_completion() }
-
+    // Run the main procedure and then wait for everything to finish
+    main();
+    unsafe {
+        let mut task = Local::borrow(None::<Task>);
+        task.get().wait_for_other_tasks();
+    }
     os::get_exit_status()
 }
diff --git a/src/libnative/task.rs b/src/libnative/task.rs
index 48768def067..0d5e08979ca 100644
--- a/src/libnative/task.rs
+++ b/src/libnative/task.rs
@@ -77,17 +77,11 @@ pub fn spawn_opts(opts: TaskOpts, f: proc()) {
             stack::record_stack_bounds(my_stack - stack + 1024, my_stack);
         }
 
-        run(task, f);
+        let mut f = Some(f);
+        task.run(|| { f.take_unwrap()() });
     })
 }
 
-/// Runs a task once, consuming the task. The given procedure is run inside of
-/// the task.
-pub fn run(t: ~Task, f: proc()) {
-    let mut f = Some(f);
-    t.run(|| { f.take_unwrap()(); });
-}
-
 // This structure is the glue between channels and the 1:1 scheduling mode. This
 // structure is allocated once per task.
 struct Ops {