@@ -21,7 +21,6 @@ use prelude::v1::*;
21
21
use io:: prelude:: * ;
22
22
23
23
use any:: Any ;
24
- use cell:: Cell ;
25
24
use cell:: RefCell ;
26
25
use fmt;
27
26
use intrinsics;
@@ -39,8 +38,6 @@ thread_local! {
39
38
}
40
39
}
41
40
42
- thread_local ! { pub static PANIC_COUNT : Cell <usize > = Cell :: new( 0 ) }
43
-
44
41
// Binary interface to the panic runtime that the standard library depends on.
45
42
//
46
43
// The standard library is tagged with `#![needs_panic_runtime]` (introduced in
@@ -187,7 +184,7 @@ fn default_hook(info: &PanicInfo) {
187
184
// for this panic. Otherwise only print it if logging is enabled.
188
185
#[ cfg( any( not( cargobuild) , feature = "backtrace" ) ) ]
189
186
let log_backtrace = {
190
- let panics = PANIC_COUNT . with ( |c| c . get ( ) ) ;
187
+ let panics = update_panic_count ( 0 ) ;
191
188
192
189
panics >= 2 || backtrace:: log_enabled ( )
193
190
} ;
@@ -238,14 +235,31 @@ fn default_hook(info: &PanicInfo) {
238
235
}
239
236
}
240
237
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
+
241
256
/// Invoke a closure, capturing the cause of an unwinding panic if one occurs.
242
257
pub unsafe fn try < R , F : FnOnce ( ) -> R > ( f : F ) -> Result < R , Box < Any + Send > > {
243
258
let mut slot = None ;
244
259
let mut f = Some ( f) ;
245
- let ret = PANIC_COUNT . with ( |s| {
246
- let prev = s. get ( ) ;
247
- s. set ( 0 ) ;
260
+ let ret;
248
261
262
+ {
249
263
let mut to_run = || {
250
264
slot = Some ( f. take ( ) . unwrap ( ) ( ) ) ;
251
265
} ;
@@ -258,18 +272,18 @@ pub unsafe fn try<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<Any + Send>> {
258
272
dataptr,
259
273
& mut any_data,
260
274
& mut any_vtable) ;
261
- s. set ( prev) ;
262
-
263
275
if r == 0 {
264
- Ok ( ( ) )
276
+ ret = Ok ( ( ) ) ;
265
277
} else {
266
- Err ( mem:: transmute ( raw:: TraitObject {
278
+ update_panic_count ( -1 ) ;
279
+ ret = Err ( mem:: transmute ( raw:: TraitObject {
267
280
data : any_data as * mut _ ,
268
281
vtable : any_vtable as * mut _ ,
269
- } ) )
282
+ } ) ) ;
270
283
}
271
- } ) ;
284
+ }
272
285
286
+ debug_assert ! ( update_panic_count( 0 ) == 0 ) ;
273
287
return ret. map ( |( ) | {
274
288
slot. take ( ) . unwrap ( )
275
289
} ) ;
@@ -285,7 +299,7 @@ pub unsafe fn try<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<Any + Send>> {
285
299
286
300
/// Determines whether the current thread is unwinding because of panic.
287
301
pub fn panicking ( ) -> bool {
288
- PANIC_COUNT . with ( |c| c . get ( ) != 0 )
302
+ update_panic_count ( 0 ) != 0
289
303
}
290
304
291
305
/// Entry point of panic from the libcore crate.
@@ -350,18 +364,14 @@ fn rust_panic_with_hook(msg: Box<Any + Send>,
350
364
file_line : & ( & ' static str , u32 ) ) -> ! {
351
365
let ( file, line) = * file_line;
352
366
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 ) ;
358
368
359
369
// If this is the third nested call (e.g. panics == 2, this is 0-indexed),
360
370
// the panic hook probably triggered the last panic, otherwise the
361
371
// double-panic check would have aborted the process. In this case abort the
362
372
// process real quickly as we don't want to try calling it again as it'll
363
373
// probably just panic again.
364
- if panics > 1 {
374
+ if panics > 2 {
365
375
util:: dumb_print ( format_args ! ( "thread panicked while processing \
366
376
panic. aborting.\n ") ) ;
367
377
unsafe { intrinsics:: abort ( ) }
@@ -383,7 +393,7 @@ fn rust_panic_with_hook(msg: Box<Any + Send>,
383
393
HOOK_LOCK . read_unlock ( ) ;
384
394
}
385
395
386
- if panics > 0 {
396
+ if panics > 1 {
387
397
// If a thread panics while it's already unwinding then we
388
398
// have limited options. Currently our preference is to
389
399
// just abort. In the future we may consider resuming
@@ -396,6 +406,12 @@ fn rust_panic_with_hook(msg: Box<Any + Send>,
396
406
rust_panic ( msg)
397
407
}
398
408
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
+
399
415
/// A private no-mangle function on which to slap yer breakpoints.
400
416
#[ no_mangle]
401
417
#[ allow( private_no_mangle_fns) ] // yes we get it, but we like breakpoints
0 commit comments