native: Don't deadlock the runtime on spawn failure
Previously, the call to bookkeeping::increment() was never paired with a decrement when the spawn failed (due to unwinding). This fixes the problem by returning a "bomb" from increment() which will decrement on drop, and then moving the bomb into the child task's procedure which will be dropped naturally.
This commit is contained in:
parent
e156d001c6
commit
355c798ac3
@ -71,7 +71,7 @@ pub fn spawn_opts(opts: TaskOpts, f: proc():Send) {
|
||||
// Note that this increment must happen *before* the spawn in order to
|
||||
// guarantee that if this task exits it will always end up waiting for the
|
||||
// spawned task to exit.
|
||||
bookkeeping::increment();
|
||||
let token = bookkeeping::increment();
|
||||
|
||||
// Spawning a new OS thread guarantees that __morestack will never get
|
||||
// triggered, but we must manually set up the actual stack bounds once this
|
||||
@ -93,7 +93,7 @@ pub fn spawn_opts(opts: TaskOpts, f: proc():Send) {
|
||||
let mut task = task;
|
||||
task.put_runtime(ops);
|
||||
drop(task.run(|| { f.take_unwrap()() }).destroy());
|
||||
bookkeeping::decrement();
|
||||
drop(token);
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -19,14 +19,24 @@
|
||||
//! decrement() manually.
|
||||
|
||||
use core::atomics;
|
||||
use core::ops::Drop;
|
||||
|
||||
use mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT};
|
||||
|
||||
static mut TASK_COUNT: atomics::AtomicUint = atomics::INIT_ATOMIC_UINT;
|
||||
static mut TASK_LOCK: StaticNativeMutex = NATIVE_MUTEX_INIT;
|
||||
|
||||
pub fn increment() {
|
||||
pub struct Token(());
|
||||
|
||||
impl Drop for Token {
|
||||
fn drop(&mut self) { decrement() }
|
||||
}
|
||||
|
||||
/// Increment the number of live tasks, returning a token which will decrement
|
||||
/// the count when dropped.
|
||||
pub fn increment() -> Token {
|
||||
let _ = unsafe { TASK_COUNT.fetch_add(1, atomics::SeqCst) };
|
||||
Token(())
|
||||
}
|
||||
|
||||
pub fn decrement() {
|
||||
|
Loading…
Reference in New Issue
Block a user