diff options
| author | Alex Crichton <alex@alexcrichton.com> | 2015-04-15 12:27:05 -0700 |
|---|---|---|
| committer | Alex Crichton <alex@alexcrichton.com> | 2015-04-27 16:15:36 -0700 |
| commit | d98ab4faf869ff0430ad73260b13ef8e473ef212 (patch) | |
| tree | 22fa7775d0ea81021b825738da48498d02ea4f5d /src/libstd | |
| parent | 0e154aaad6486fa8bf19b02bc3026ede0ceb91cf (diff) | |
| download | rust-d98ab4faf869ff0430ad73260b13ef8e473ef212.tar.gz rust-d98ab4faf869ff0430ad73260b13ef8e473ef212.zip | |
std: Don't assume thread::current() works on panic
Inspecting the current thread's info may not always work due to the TLS value having been destroyed (or is actively being destroyed). The code for printing a panic message assumed, however, that it could acquire the thread's name through this method. Instead this commit propagates the `Option` outwards to allow the `std::panicking` module to handle the case where the current thread isn't present. While it solves the immediate issue of #24313, there is still another underlying issue of panicking destructors in thread locals will abort the process. Closes #24313
Diffstat (limited to 'src/libstd')
| -rw-r--r-- | src/libstd/panicking.rs | 6 | ||||
| -rw-r--r-- | src/libstd/sys/common/thread_info.rs | 11 | ||||
| -rw-r--r-- | src/libstd/sys/unix/stack_overflow.rs | 2 | ||||
| -rw-r--r-- | src/libstd/thread/mod.rs | 4 |
4 files changed, 12 insertions, 11 deletions
diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index 11b057d0094..7366524fd7e 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -17,7 +17,7 @@ use any::Any; use cell::RefCell; use rt::{backtrace, unwind}; use sys::stdio::Stderr; -use thread; +use sys_common::thread_info; thread_local! { pub static LOCAL_STDERR: RefCell<Option<Box<Write + Send>>> = { @@ -34,8 +34,8 @@ pub fn on_panic(obj: &(Any+Send), file: &'static str, line: u32) { } }; let mut err = Stderr::new(); - let thread = thread::current(); - let name = thread.name().unwrap_or("<unnamed>"); + let thread = thread_info::current_thread(); + let name = thread.as_ref().and_then(|t| t.name()).unwrap_or("<unnamed>"); let prev = LOCAL_STDERR.with(|s| s.borrow_mut().take()); match prev { Some(mut stderr) => { diff --git a/src/libstd/sys/common/thread_info.rs b/src/libstd/sys/common/thread_info.rs index 22cb5943371..ae55bae37aa 100644 --- a/src/libstd/sys/common/thread_info.rs +++ b/src/libstd/sys/common/thread_info.rs @@ -25,10 +25,9 @@ struct ThreadInfo { thread_local! { static THREAD_INFO: RefCell<Option<ThreadInfo>> = RefCell::new(None) } impl ThreadInfo { - fn with<R, F>(f: F) -> R where F: FnOnce(&mut ThreadInfo) -> R { + fn with<R, F>(f: F) -> Option<R> where F: FnOnce(&mut ThreadInfo) -> R { if THREAD_INFO.state() == LocalKeyState::Destroyed { - panic!("Use of std::thread::current() is not possible after \ - the thread's local data has been destroyed"); + return None } THREAD_INFO.with(move |c| { @@ -38,16 +37,16 @@ impl ThreadInfo { thread: NewThread::new(None), }) } - f(c.borrow_mut().as_mut().unwrap()) + Some(f(c.borrow_mut().as_mut().unwrap())) }) } } -pub fn current_thread() -> Thread { +pub fn current_thread() -> Option<Thread> { ThreadInfo::with(|info| info.thread.clone()) } -pub fn stack_guard() -> usize { +pub fn stack_guard() -> Option<usize> { ThreadInfo::with(|info| info.stack_guard) } diff --git a/src/libstd/sys/unix/stack_overflow.rs b/src/libstd/sys/unix/stack_overflow.rs index 6887095c53a..2bc280d1274 100644 --- a/src/libstd/sys/unix/stack_overflow.rs +++ b/src/libstd/sys/unix/stack_overflow.rs @@ -81,7 +81,7 @@ mod imp { // We're calling into functions with stack checks stack::record_sp_limit(0); - let guard = thread_info::stack_guard(); + let guard = thread_info::stack_guard().unwrap_or(0); let addr = (*info).si_addr as usize; if guard == 0 || addr < guard - PAGE_SIZE || addr >= guard { diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 383726b3e83..ce531fb1381 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -407,7 +407,9 @@ pub fn scoped<'a, T, F>(f: F) -> JoinGuard<'a, T> where /// Gets a handle to the thread that invokes it. #[stable(feature = "rust1", since = "1.0.0")] pub fn current() -> Thread { - thread_info::current_thread() + thread_info::current_thread().expect("use of std::thread::current() is not \ + possible after the thread's local \ + data has been destroyed") } /// Cooperatively gives up a timeslice to the OS scheduler. |
