17
17
//! * Executing a panic up to doing the actual implementation
18
18
//! * Shims around "try"
19
19
20
+ use core:: panic:: BoxMeUp ;
21
+
20
22
use io:: prelude:: * ;
21
23
22
24
use any:: Any ;
@@ -27,7 +29,7 @@ use intrinsics;
27
29
use mem;
28
30
use ptr;
29
31
use raw;
30
- use sys:: stdio:: Stderr ;
32
+ use sys:: stdio:: { Stderr , stderr_prints_nothing } ;
31
33
use sys_common:: rwlock:: RWLock ;
32
34
use sys_common:: thread_info;
33
35
use sys_common:: util;
@@ -56,7 +58,7 @@ extern {
56
58
data_ptr : * mut usize ,
57
59
vtable_ptr : * mut usize ) -> u32 ;
58
60
#[ unwind( allowed) ]
59
- fn __rust_start_panic ( data : usize , vtable : usize ) -> u32 ;
61
+ fn __rust_start_panic ( payload : usize ) -> u32 ;
60
62
}
61
63
62
64
#[ derive( Copy , Clone ) ]
@@ -163,6 +165,12 @@ fn default_hook(info: &PanicInfo) {
163
165
#[ cfg( feature = "backtrace" ) ]
164
166
use sys_common:: backtrace;
165
167
168
+ // Some platforms know that printing to stderr won't ever actually print
169
+ // anything, and if that's the case we can skip everything below.
170
+ if stderr_prints_nothing ( ) {
171
+ return
172
+ }
173
+
166
174
// If this is a double panic, make sure that we print a backtrace
167
175
// for this panic. Otherwise only print it if logging is enabled.
168
176
#[ cfg( feature = "backtrace" ) ]
@@ -212,15 +220,15 @@ fn default_hook(info: &PanicInfo) {
212
220
213
221
let prev = LOCAL_STDERR . with ( |s| s. borrow_mut ( ) . take ( ) ) ;
214
222
match ( prev, err. as_mut ( ) ) {
215
- ( Some ( mut stderr) , _) => {
216
- write ( & mut * stderr) ;
217
- let mut s = Some ( stderr) ;
218
- LOCAL_STDERR . with ( |slot| {
219
- * slot. borrow_mut ( ) = s. take ( ) ;
220
- } ) ;
221
- }
222
- ( None , Some ( ref mut err) ) => { write ( err) }
223
- _ => { }
223
+ ( Some ( mut stderr) , _) => {
224
+ write ( & mut * stderr) ;
225
+ let mut s = Some ( stderr) ;
226
+ LOCAL_STDERR . with ( |slot| {
227
+ * slot. borrow_mut ( ) = s. take ( ) ;
228
+ } ) ;
229
+ }
230
+ ( None , Some ( ref mut err) ) => { write ( err) }
231
+ _ => { }
224
232
}
225
233
}
226
234
@@ -344,7 +352,7 @@ pub fn begin_panic_fmt(msg: &fmt::Arguments,
344
352
345
353
let mut s = String :: new ( ) ;
346
354
let _ = s. write_fmt ( * msg) ;
347
- rust_panic_with_hook ( Box :: new ( s) , Some ( msg) , file_line_col)
355
+ rust_panic_with_hook ( & mut PanicPayload :: new ( s) , Some ( msg) , file_line_col)
348
356
}
349
357
350
358
/// This is the entry point of panicking for panic!() and assert!().
@@ -360,7 +368,34 @@ pub fn begin_panic<M: Any + Send>(msg: M, file_line_col: &(&'static str, u32, u3
360
368
// be performed in the parent of this thread instead of the thread that's
361
369
// panicking.
362
370
363
- rust_panic_with_hook ( Box :: new ( msg) , None , file_line_col)
371
+ rust_panic_with_hook ( & mut PanicPayload :: new ( msg) , None , file_line_col)
372
+ }
373
+
374
+ struct PanicPayload < A > {
375
+ inner : Option < A > ,
376
+ }
377
+
378
+ impl < A : Send + ' static > PanicPayload < A > {
379
+ fn new ( inner : A ) -> PanicPayload < A > {
380
+ PanicPayload { inner : Some ( inner) }
381
+ }
382
+ }
383
+
384
+ unsafe impl < A : Send + ' static > BoxMeUp for PanicPayload < A > {
385
+ fn box_me_up ( & mut self ) -> * mut ( Any + Send ) {
386
+ let data = match self . inner . take ( ) {
387
+ Some ( a) => Box :: new ( a) as Box < Any + Send > ,
388
+ None => Box :: new ( ( ) ) ,
389
+ } ;
390
+ Box :: into_raw ( data)
391
+ }
392
+
393
+ fn get ( & self ) -> & ( Any + Send ) {
394
+ match self . inner {
395
+ Some ( ref a) => a,
396
+ None => & ( ) ,
397
+ }
398
+ }
364
399
}
365
400
366
401
/// Executes the primary logic for a panic, including checking for recursive
@@ -369,9 +404,7 @@ pub fn begin_panic<M: Any + Send>(msg: M, file_line_col: &(&'static str, u32, u3
369
404
/// This is the entry point or panics from libcore, formatted panics, and
370
405
/// `Box<Any>` panics. Here we'll verify that we're not panicking recursively,
371
406
/// run panic hooks, and then delegate to the actual implementation of panics.
372
- #[ inline( never) ]
373
- #[ cold]
374
- fn rust_panic_with_hook ( payload : Box < Any + Send > ,
407
+ fn rust_panic_with_hook ( payload : & mut BoxMeUp ,
375
408
message : Option < & fmt:: Arguments > ,
376
409
file_line_col : & ( & ' static str , u32 , u32 ) ) -> ! {
377
410
let ( file, line, col) = * file_line_col;
@@ -391,7 +424,7 @@ fn rust_panic_with_hook(payload: Box<Any + Send>,
391
424
392
425
unsafe {
393
426
let info = PanicInfo :: internal_constructor (
394
- & * payload,
427
+ payload. get ( ) ,
395
428
message,
396
429
Location :: internal_constructor ( file, line, col) ,
397
430
) ;
@@ -419,16 +452,29 @@ fn rust_panic_with_hook(payload: Box<Any + Send>,
419
452
/// Shim around rust_panic. Called by resume_unwind.
420
453
pub fn update_count_then_panic ( msg : Box < Any + Send > ) -> ! {
421
454
update_panic_count ( 1 ) ;
422
- rust_panic ( msg)
455
+
456
+ struct RewrapBox ( Box < Any + Send > ) ;
457
+
458
+ unsafe impl BoxMeUp for RewrapBox {
459
+ fn box_me_up ( & mut self ) -> * mut ( Any + Send ) {
460
+ Box :: into_raw ( mem:: replace ( & mut self . 0 , Box :: new ( ( ) ) ) )
461
+ }
462
+
463
+ fn get ( & self ) -> & ( Any + Send ) {
464
+ & * self . 0
465
+ }
466
+ }
467
+
468
+ rust_panic ( & mut RewrapBox ( msg) )
423
469
}
424
470
425
471
/// A private no-mangle function on which to slap yer breakpoints.
426
472
#[ no_mangle]
427
473
#[ allow( private_no_mangle_fns) ] // yes we get it, but we like breakpoints
428
- pub fn rust_panic ( msg : Box < Any + Send > ) -> ! {
474
+ pub fn rust_panic ( mut msg : & mut BoxMeUp ) -> ! {
429
475
let code = unsafe {
430
- let obj = mem :: transmute :: < _ , raw :: TraitObject > ( msg) ;
431
- __rust_start_panic ( obj. data as usize , obj . vtable as usize )
476
+ let obj = & mut msg as * mut & mut BoxMeUp ;
477
+ __rust_start_panic ( obj as usize )
432
478
} ;
433
479
rtabort ! ( "failed to initiate panic, error {}" , code)
434
480
}
0 commit comments