Skip to content

Commit

Permalink
Revise rt::unwind
Browse files Browse the repository at this point in the history
  • Loading branch information
aturon committed Dec 19, 2014
1 parent d8e4780 commit 14c1a10
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 46 deletions.
4 changes: 0 additions & 4 deletions src/libstd/rt/mod.rs
Expand Up @@ -72,10 +72,6 @@ mod macros;

// These should be refactored/moved/made private over time
pub mod util;
<<<<<<< HEAD
=======
pub mod task;
>>>>>>> Remove rt::{local, local_data, thread_local_storage}
pub mod unwind;

mod args;
Expand Down
42 changes: 6 additions & 36 deletions src/libstd/rt/unwind.rs
Expand Up @@ -72,16 +72,9 @@ use mem;
use raw::Closure;
use libc::c_void;

use rt::local::Local;
use rt::task::Task;

use sys_common::thread_info;
use rt::libunwind as uw;

#[allow(missing_copy_implementations)]
pub struct Unwinder {
unwinding: bool,
}

struct Exception {
uwe: uw::_Unwind_Exception,
cause: Option<Box<Any + Send>>,
Expand All @@ -104,18 +97,6 @@ static CALLBACKS: [atomic::AtomicUint, ..MAX_CALLBACKS] =
atomic::INIT_ATOMIC_UINT, atomic::INIT_ATOMIC_UINT];
static CALLBACK_CNT: atomic::AtomicUint = atomic::INIT_ATOMIC_UINT;

impl Unwinder {
pub fn new() -> Unwinder {
Unwinder {
unwinding: false,
}
}

pub fn unwinding(&self) -> bool {
self.unwinding
}
}

/// Invoke a closure, capturing the cause of panic if one occurs.
///
/// This function will return `None` if the closure did not panic, and will
Expand Down Expand Up @@ -556,7 +537,7 @@ pub fn begin_unwind<M: Any + Send>(msg: M, file_line: &(&'static str, uint)) ->
/// we need the `Any` object anyway, we're not just creating it to
/// avoid being generic.)
///
/// Do this split took the LLVM IR line counts of `fn main() { panic!()
/// Doing this split took the LLVM IR line counts of `fn main() { panic!()
/// }` from ~1900/3700 (-O/no opts) to 180/590.
#[inline(never)] #[cold] // this is the slow path, please never inline this
fn begin_unwind_inner(msg: Box<Any + Send>, file_line: &(&'static str, uint)) -> ! {
Expand All @@ -583,27 +564,16 @@ fn begin_unwind_inner(msg: Box<Any + Send>, file_line: &(&'static str, uint)) ->
};

// Now that we've run all the necessary unwind callbacks, we actually
// perform the unwinding. If we don't have a task, then it's time to die
// (hopefully someone printed something about this).
let mut task: Box<Task> = match Local::try_take() {
Some(task) => task,
None => rust_panic(msg),
};

if task.unwinder.unwinding {
// If a task panics while it's already unwinding then we
// perform the unwinding.
if thread_info::unwinding() {
// If a thread panics while it's already unwinding then we
// have limited options. Currently our preference is to
// just abort. In the future we may consider resuming
// unwinding or otherwise exiting the task cleanly.
rterrln!("task failed during unwinding. aborting.");
unsafe { intrinsics::abort() }
}
task.unwinder.unwinding = true;

// Put the task back in TLS because the unwinding process may run code which
// requires the task. We need a handle to its unwinder, however, so after
// this we unsafely extract it and continue along.
Local::put(task);
thread_info::set_unwinding(true);
rust_panic(msg);
}

Expand Down
30 changes: 24 additions & 6 deletions src/libstd/sys/common/thread_info.rs
Expand Up @@ -8,30 +8,36 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use core::prelude::*;

use thread::Thread;
use cell::RefCell;
use string::String;

struct ThreadInfo {
// This field holds the known bounds of the stack in (lo, hi)
// form. Not all threads necessarily know their precise bounds,
// hence this is optional.
stack_bounds: (uint, uint),
stack_guard: uint,
unwinder: Unwinder,
unwinding: bool,
thread: Thread,
}

thread_local!(static THREAD_INFO: RefCell<Option<ThreadInfo>> = RefCell::new(None));
thread_local!(static THREAD_INFO: RefCell<Option<ThreadInfo>> = RefCell::new(None))

impl ThreadInfo {
fn with<R>(f: |&ThreadInfo| -> R) -> R {
fn with<R>(f: |&mut ThreadInfo| -> R) -> R {
THREAD_INFO.with(|c| {
if c.borrow().is_none() {
*c.borrow_mut() = Some(ThreadInfo {
stack_bounds: (0, 0),
stack_guard: 0,
unwinder: Unwinder::new(),
unwinder: false,
thread: Thread::new(None),
})
}
f(c.borrow().as_ref().unwrap())
f(c.borrow_mut().as_ref().unwrap())
})
}
}
Expand All @@ -44,12 +50,24 @@ pub fn panicking() -> bool {
ThreadInfo::with(|info| info.unwinder.unwinding())
}

pub fn stack_guard() -> uint {
ThreadInfo::with(|info| info.stack_guard)
}

pub fn unwinding() -> bool {
ThreadInfo::with(|info| info.unwinder.unwinding)
}

pub fn set_unwinding(unwinding: bool) {
ThreadInfo::with(|info| info.unwinding = unwinding)
}

pub fn set(stack_bounds: (uint, uint), stack_guard: uint, thread: Thread) {
THREAD_INFO.with(|c| assert!(c.borrow().is_none()));
THREAD_INFO.with(|c| *c.borrow_mut() = Some(ThreadInfo{
stack_bounds: stack_bounds,
stack_guard: stack_guard,
unwinder: Unwinder::new(),
unwinding: false,
thread: thread,
}));
}
Expand Down

0 comments on commit 14c1a10

Please sign in to comment.