@@ -245,19 +245,24 @@ fn default_hook(info: &PanicInfo<'_>) {
245
245
246
246
// The current implementation always returns `Some`.
247
247
let location = info. location ( ) . unwrap ( ) ;
248
-
249
- let msg = match info. payload ( ) . downcast_ref :: < & ' static str > ( ) {
250
- Some ( s) => * s,
251
- None => match info. payload ( ) . downcast_ref :: < String > ( ) {
252
- Some ( s) => & s[ ..] ,
253
- None => "Box<dyn Any>" ,
254
- } ,
255
- } ;
256
248
let thread = thread_info:: current_thread ( ) ;
257
249
let name = thread. as_ref ( ) . and_then ( |t| t. name ( ) ) . unwrap_or ( "<unnamed>" ) ;
258
250
259
251
let write = |err : & mut dyn crate :: io:: Write | {
260
- let _ = writeln ! ( err, "thread '{name}' panicked at '{msg}', {location}" ) ;
252
+ // Use the panic message directly if available, otherwise take it from
253
+ // the payload.
254
+ if let Some ( msg) = info. message ( ) {
255
+ let _ = writeln ! ( err, "thread '{name}' panicked at '{msg}', {location}" ) ;
256
+ } else {
257
+ let msg = if let Some ( s) = info. payload ( ) . downcast_ref :: < & ' static str > ( ) {
258
+ * s
259
+ } else if let Some ( s) = info. payload ( ) . downcast_ref :: < String > ( ) {
260
+ & s[ ..]
261
+ } else {
262
+ "Box<dyn Any>"
263
+ } ;
264
+ let _ = writeln ! ( err, "thread '{name}' panicked at '{msg}', {location}" ) ;
265
+ }
261
266
262
267
static FIRST_PANIC : AtomicBool = AtomicBool :: new ( true ) ;
263
268
@@ -524,6 +529,8 @@ pub fn panicking() -> bool {
524
529
#[ cfg( not( test) ) ]
525
530
#[ panic_handler]
526
531
pub fn begin_panic_handler ( info : & PanicInfo < ' _ > ) -> ! {
532
+ use alloc:: alloc:: AllocErrorPanicPayload ;
533
+
527
534
struct PanicPayload < ' a > {
528
535
inner : & ' a fmt:: Arguments < ' a > ,
529
536
string : Option < String > ,
@@ -550,8 +557,7 @@ pub fn begin_panic_handler(info: &PanicInfo<'_>) -> ! {
550
557
unsafe impl < ' a > BoxMeUp for PanicPayload < ' a > {
551
558
fn take_box ( & mut self ) -> * mut ( dyn Any + Send ) {
552
559
// We do two allocations here, unfortunately. But (a) they're required with the current
553
- // scheme, and (b) we don't handle panic + OOM properly anyway (see comment in
554
- // begin_panic below).
560
+ // scheme, and (b) OOM uses its own separate payload type which doesn't allocate.
555
561
let contents = mem:: take ( self . fill ( ) ) ;
556
562
Box :: into_raw ( Box :: new ( contents) )
557
563
}
@@ -576,7 +582,14 @@ pub fn begin_panic_handler(info: &PanicInfo<'_>) -> ! {
576
582
let loc = info. location ( ) . unwrap ( ) ; // The current implementation always returns Some
577
583
let msg = info. message ( ) . unwrap ( ) ; // The current implementation always returns Some
578
584
crate :: sys_common:: backtrace:: __rust_end_short_backtrace ( move || {
579
- if let Some ( msg) = msg. as_str ( ) {
585
+ if let Some ( payload) = info. payload ( ) . downcast_ref :: < AllocErrorPanicPayload > ( ) {
586
+ rust_panic_with_hook (
587
+ & mut payload. internal_clone ( ) ,
588
+ info. message ( ) ,
589
+ loc,
590
+ info. can_unwind ( ) ,
591
+ ) ;
592
+ } else if let Some ( msg) = msg. as_str ( ) {
580
593
rust_panic_with_hook ( & mut StrPanicPayload ( msg) , info. message ( ) , loc, info. can_unwind ( ) ) ;
581
594
} else {
582
595
rust_panic_with_hook (
@@ -623,11 +636,7 @@ pub const fn begin_panic<M: Any + Send>(msg: M) -> ! {
623
636
624
637
unsafe impl < A : Send + ' static > BoxMeUp for PanicPayload < A > {
625
638
fn take_box ( & mut self ) -> * mut ( dyn Any + Send ) {
626
- // Note that this should be the only allocation performed in this code path. Currently
627
- // this means that panic!() on OOM will invoke this code path, but then again we're not
628
- // really ready for panic on OOM anyway. If we do start doing this, then we should
629
- // propagate this allocation to be performed in the parent of this thread instead of the
630
- // thread that's panicking.
639
+ // Note that this should be the only allocation performed in this code path.
631
640
let data = match self . inner . take ( ) {
632
641
Some ( a) => Box :: new ( a) as Box < dyn Any + Send > ,
633
642
None => process:: abort ( ) ,
0 commit comments