Skip to content

Commit 695b3d8

Browse files
authored
Auto merge of #34866 - cynicaldevil:panic-counter, r=alexcrichton
Refactored code to access TLS only in case of panic (II) Fixes #34787 r? @alexcrichton Do it **very** carefully this time!
2 parents 1222f5d + ea2216c commit 695b3d8

File tree

4 files changed

+40
-23
lines changed

4 files changed

+40
-23
lines changed

src/libstd/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,7 @@
278278
#![feature(unwind_attributes)]
279279
#![feature(vec_push_all)]
280280
#![feature(zero_one)]
281+
#![cfg_attr(test, feature(update_panic_count))]
281282

282283
// Issue# 30592: Systematically use alloc_system during stage0 since jemalloc
283284
// might be unavailable or disabled

src/libstd/panic.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -340,5 +340,5 @@ pub fn catch_unwind<F: FnOnce() -> R + UnwindSafe, R>(f: F) -> Result<R> {
340340
/// ```
341341
#[stable(feature = "resume_unwind", since = "1.9.0")]
342342
pub fn resume_unwind(payload: Box<Any + Send>) -> ! {
343-
panicking::rust_panic(payload)
343+
panicking::update_count_then_panic(payload)
344344
}

src/libstd/panicking.rs

+37-21
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ use prelude::v1::*;
2121
use io::prelude::*;
2222

2323
use any::Any;
24-
use cell::Cell;
2524
use cell::RefCell;
2625
use fmt;
2726
use intrinsics;
@@ -39,8 +38,6 @@ thread_local! {
3938
}
4039
}
4140

42-
thread_local! { pub static PANIC_COUNT: Cell<usize> = Cell::new(0) }
43-
4441
// Binary interface to the panic runtime that the standard library depends on.
4542
//
4643
// The standard library is tagged with `#![needs_panic_runtime]` (introduced in
@@ -187,7 +184,7 @@ fn default_hook(info: &PanicInfo) {
187184
// for this panic. Otherwise only print it if logging is enabled.
188185
#[cfg(any(not(cargobuild), feature = "backtrace"))]
189186
let log_backtrace = {
190-
let panics = PANIC_COUNT.with(|c| c.get());
187+
let panics = update_panic_count(0);
191188

192189
panics >= 2 || backtrace::log_enabled()
193190
};
@@ -238,14 +235,31 @@ fn default_hook(info: &PanicInfo) {
238235
}
239236
}
240237

238+
239+
#[cfg(not(test))]
240+
#[doc(hidden)]
241+
#[unstable(feature = "update_panic_count", issue = "0")]
242+
pub fn update_panic_count(amt: isize) -> usize {
243+
use cell::Cell;
244+
thread_local! { static PANIC_COUNT: Cell<usize> = Cell::new(0) }
245+
246+
PANIC_COUNT.with(|c| {
247+
let next = (c.get() as isize + amt) as usize;
248+
c.set(next);
249+
return next
250+
})
251+
}
252+
253+
#[cfg(test)]
254+
pub use realstd::rt::update_panic_count;
255+
241256
/// Invoke a closure, capturing the cause of an unwinding panic if one occurs.
242257
pub unsafe fn try<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<Any + Send>> {
243258
let mut slot = None;
244259
let mut f = Some(f);
245-
let ret = PANIC_COUNT.with(|s| {
246-
let prev = s.get();
247-
s.set(0);
260+
let ret;
248261

262+
{
249263
let mut to_run = || {
250264
slot = Some(f.take().unwrap()());
251265
};
@@ -258,18 +272,18 @@ pub unsafe fn try<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<Any + Send>> {
258272
dataptr,
259273
&mut any_data,
260274
&mut any_vtable);
261-
s.set(prev);
262-
263275
if r == 0 {
264-
Ok(())
276+
ret = Ok(());
265277
} else {
266-
Err(mem::transmute(raw::TraitObject {
278+
update_panic_count(-1);
279+
ret = Err(mem::transmute(raw::TraitObject {
267280
data: any_data as *mut _,
268281
vtable: any_vtable as *mut _,
269-
}))
282+
}));
270283
}
271-
});
284+
}
272285

286+
debug_assert!(update_panic_count(0) == 0);
273287
return ret.map(|()| {
274288
slot.take().unwrap()
275289
});
@@ -285,7 +299,7 @@ pub unsafe fn try<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<Any + Send>> {
285299

286300
/// Determines whether the current thread is unwinding because of panic.
287301
pub fn panicking() -> bool {
288-
PANIC_COUNT.with(|c| c.get() != 0)
302+
update_panic_count(0) != 0
289303
}
290304

291305
/// Entry point of panic from the libcore crate.
@@ -350,18 +364,14 @@ fn rust_panic_with_hook(msg: Box<Any + Send>,
350364
file_line: &(&'static str, u32)) -> ! {
351365
let (file, line) = *file_line;
352366

353-
let panics = PANIC_COUNT.with(|c| {
354-
let prev = c.get();
355-
c.set(prev + 1);
356-
prev
357-
});
367+
let panics = update_panic_count(1);
358368

359369
// If this is the third nested call (e.g. panics == 2, this is 0-indexed),
360370
// the panic hook probably triggered the last panic, otherwise the
361371
// double-panic check would have aborted the process. In this case abort the
362372
// process real quickly as we don't want to try calling it again as it'll
363373
// probably just panic again.
364-
if panics > 1 {
374+
if panics > 2 {
365375
util::dumb_print(format_args!("thread panicked while processing \
366376
panic. aborting.\n"));
367377
unsafe { intrinsics::abort() }
@@ -383,7 +393,7 @@ fn rust_panic_with_hook(msg: Box<Any + Send>,
383393
HOOK_LOCK.read_unlock();
384394
}
385395

386-
if panics > 0 {
396+
if panics > 1 {
387397
// If a thread panics while it's already unwinding then we
388398
// have limited options. Currently our preference is to
389399
// just abort. In the future we may consider resuming
@@ -396,6 +406,12 @@ fn rust_panic_with_hook(msg: Box<Any + Send>,
396406
rust_panic(msg)
397407
}
398408

409+
/// Shim around rust_panic. Called by resume_unwind.
410+
pub fn update_count_then_panic(msg: Box<Any + Send>) -> ! {
411+
update_panic_count(1);
412+
rust_panic(msg)
413+
}
414+
399415
/// A private no-mangle function on which to slap yer breakpoints.
400416
#[no_mangle]
401417
#[allow(private_no_mangle_fns)] // yes we get it, but we like breakpoints

src/libstd/rt.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525

2626

2727
// Reexport some of our utilities which are expected by other crates.
28-
pub use panicking::{begin_panic, begin_panic_fmt};
28+
pub use panicking::{begin_panic, begin_panic_fmt, update_panic_count};
2929

3030
#[cfg(not(test))]
3131
#[lang = "start"]

0 commit comments

Comments
 (0)