Revise rt::unwind
This commit is contained in:
parent
d8e4780b0b
commit
14c1a103bc
@ -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;
|
||||
|
@ -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>>,
|
||||
@ -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
|
||||
@ -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)) -> ! {
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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())
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -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,
|
||||
}));
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user