11use std:: {
2+ cell:: RefCell ,
23 future:: Future ,
34 pin:: Pin ,
45 task:: { Context , Poll } ,
@@ -42,33 +43,65 @@ pub mod PanicStrategy {
4243
4344#[ inline]
4445fn panic_hook_handler < S : PanicStrategy :: S , R > ( f : impl FnOnce ( ) -> R ) -> R {
45- let prev_hook = if S :: is_suppressed ( ) {
46- let prev = Some ( std:: panic:: take_hook ( ) ) ;
47- std:: panic:: set_hook ( Box :: new ( |_| { } ) ) ;
48- prev
49- } else {
50- None
51- } ;
46+ PANIC_HOOK . with ( |hook| {
47+ if !S :: is_suppressed ( ) {
48+ * hook. borrow_mut ( ) = Some ( std:: panic:: take_hook ( ) ) ;
49+ }
50+ } ) ;
51+ std:: panic:: set_hook ( Box :: new ( move |info| {
52+ PANIC_HOOK . with ( |hook| {
53+ if let Some ( hook) = & * hook. borrow ( ) {
54+ hook ( info) ;
55+ }
56+ } ) ;
57+ PANIC_INFO_AND_BACKTRACE . with ( |bt| {
58+ * bt. borrow_mut ( ) = Some ( (
59+ info. to_string ( ) ,
60+ std:: backtrace:: Backtrace :: force_capture ( ) . to_string ( ) ,
61+ ) ) ;
62+ } ) ;
63+ } ) ) ;
5264 let result = f ( ) ;
53- if let Some ( prev_hook) = prev_hook {
54- std:: panic:: set_hook ( prev_hook) ;
55- }
65+ PANIC_HOOK . with ( |hook| {
66+ if let Some ( hook) = hook. borrow_mut ( ) . take ( ) {
67+ std:: panic:: set_hook ( hook) ;
68+ }
69+ } ) ;
5670
5771 result
5872}
5973
74+ type PanicHook = Box < dyn Fn ( & std:: panic:: PanicInfo < ' _ > ) + ' static + Sync + Send > ;
75+
76+ thread_local ! {
77+ static PANIC_INFO_AND_BACKTRACE : RefCell <Option <( String , String ) >> = RefCell :: new( None ) ;
78+ static PANIC_HOOK : RefCell <Option <PanicHook >> = RefCell :: new( None ) ;
79+ }
80+
6081pub fn catch_unwind < S : PanicStrategy :: S , R > ( f : impl FnOnce ( ) -> R ) -> Result < R > {
6182 match panic_hook_handler :: < S , _ > ( move || {
6283 std:: panic:: catch_unwind ( std:: panic:: AssertUnwindSafe ( f) )
6384 } ) {
6485 Ok ( res) => Ok ( res) ,
65- Err ( cause) => match cause. downcast_ref :: < & ' static str > ( ) {
66- None => match cause. downcast_ref :: < String > ( ) {
67- None => Err ( internal_error ! ( "Unknown panic message" ) ) ,
68- Some ( message) => Err ( internal_error ! ( "{message}" ) ) ,
69- } ,
70- Some ( message) => Err ( internal_error ! ( "{message}" ) ) ,
71- } ,
86+ Err ( cause) => {
87+ let ( info, backtrace) = PANIC_INFO_AND_BACKTRACE
88+ . with ( |b| b. borrow_mut ( ) . take ( ) )
89+ . unwrap_or_default ( ) ;
90+
91+ match cause. downcast_ref :: < & ' static str > ( ) {
92+ None => match cause. downcast_ref :: < String > ( ) {
93+ None => Err ( internal_error ! (
94+ "Unknown fatal error.\n Raw: {info}\n {GENERIC_FATAL_MESSAGE}\n \n {backtrace}"
95+ ) ) ,
96+ Some ( message) => Err ( internal_error ! (
97+ "{message}.\n Raw: {info}\n {GENERIC_FATAL_MESSAGE}\n \n {backtrace}"
98+ ) ) ,
99+ } ,
100+ Some ( message) => Err ( internal_error ! (
101+ "{message}.\n Raw: {info}\n {GENERIC_FATAL_MESSAGE}\n \n {backtrace}"
102+ ) ) ,
103+ }
104+ }
72105 }
73106}
74107
@@ -95,3 +128,6 @@ impl<F: Future + Send + 'static> Future for CatchUnwindFuture<F> {
95128 }
96129 }
97130}
131+
132+ const GENERIC_FATAL_MESSAGE : & str =
133+ "This is not expected, please file an issue at https://github.com/web-infra-dev/rspack/issues." ;
0 commit comments