1- use crate :: {
2- dev_aid:: ariadne_interface:: { pretty_print_span, pretty_print_spans_in_reverse_order} ,
3- prelude:: * ,
4- } ;
1+ use crate :: { dev_aid:: ariadne_interface:: pretty_print_many_spans, linker:: LinkerFiles , prelude:: * } ;
52
63use std:: {
74 cell:: { Cell , RefCell } ,
8- ops:: Range ,
95 path:: PathBuf ,
10- sync:: {
11- Arc , LazyLock , Mutex ,
12- atomic:: { AtomicBool , AtomicPtr } ,
13- } ,
6+ sync:: { Arc , LazyLock , Mutex , atomic:: AtomicBool } ,
147 thread,
158 time:: { Duration , Instant } ,
169} ;
@@ -19,10 +12,8 @@ use circular_buffer::CircularBuffer;
1912use colored:: Colorize ;
2013
2114use crate :: {
22- codegen:: sanitize_filename,
23- config:: config,
24- linker:: { FileData , Linker } ,
25- prelude:: Span ,
15+ codegen:: sanitize_filename, config:: config, dev_aid:: ariadne_interface:: pretty_print_span,
16+ linker:: Linker ,
2617} ;
2718
2819/// Many duplicates will be produced, and filtering them out in the code itself is inefficient. Therefore just keep a big buffer and deduplicate as needed
@@ -41,12 +32,11 @@ struct SpanDebuggerStackElement {
4132 global_obj_name : String ,
4233 debugging_enabled : bool ,
4334 span_history : CircularBuffer < SPAN_TOUCH_HISTORY_SIZE , Span > ,
44- file_data : * const FileData ,
4535}
4636
4737thread_local ! {
4838 static DEBUG_STACK : RefCell <PerThreadDebugInfo > = const { RefCell :: new( PerThreadDebugInfo { debug_stack: Vec :: new( ) , recent_debug_options: CircularBuffer :: new( ) } ) } ;
49- static MOST_RECENT_FILE_DATA : std :: sync :: atomic :: AtomicPtr < FileData > = const { AtomicPtr :: new( std:: ptr:: null_mut( ) ) }
39+ static STORED_LINKER : Cell < * mut Linker > = const { Cell :: new( std:: ptr:: null_mut( ) ) } ;
5040}
5141
5242/// Register a [crate::file_position::Span] for printing by [SpanDebugger] on panic.
@@ -61,37 +51,42 @@ pub fn add_debug_span(sp: Span) {
6151 } ) ;
6252}
6353
64- fn print_most_recent_spans ( file_data : & FileData , history : & SpanDebuggerStackElement ) {
65- let mut spans_to_print: Vec < Range < usize > > = Vec :: with_capacity ( NUM_SPANS_TO_PRINT ) ;
54+ fn print_most_recent_spans ( linker_files : & LinkerFiles , history : & SpanDebuggerStackElement ) {
55+ let mut spans_to_print: Vec < Span > = Vec :: with_capacity ( NUM_SPANS_TO_PRINT ) ;
6656
6757 for sp in history. span_history . iter ( ) . rev ( ) {
68- let as_range = sp. as_range ( ) ;
69- if !spans_to_print. contains ( & as_range) {
70- spans_to_print. push ( as_range) ;
58+ if !spans_to_print. contains ( sp) {
59+ spans_to_print. push ( * sp) ;
7160 }
7261 if spans_to_print. len ( ) >= NUM_SPANS_TO_PRINT {
7362 break ;
7463 }
7564 }
7665
7766 info ! (
78- "Panic unwinding. Printing the last {} spans. BEWARE: These spans may not correspond to this file, thus incorrect spans are possible! " ,
67+ "Panic unwinding. Printing the last {} spans." ,
7968 spans_to_print. len( )
8069 ) ;
81- pretty_print_spans_in_reverse_order ( file_data, spans_to_print) ;
70+ pretty_print_many_spans (
71+ linker_files,
72+ spans_to_print. iter ( ) . rev ( ) . enumerate ( ) . map ( |( idx, span) | {
73+ let sp = span. as_range ( ) ;
74+ ( * span, format ! ( "-{idx}: Span({}, {})" , sp. start, sp. end) )
75+ } ) ,
76+ ) ;
8277}
8378
8479#[ allow( unused) ]
8580pub fn debug_print_span ( span : Span , label : String ) {
86- MOST_RECENT_FILE_DATA . with ( |ptr| {
87- let ptr = ptr . load ( std :: sync :: atomic :: Ordering :: SeqCst ) ;
88- if ptr . is_null ( ) {
89- error ! ( "No FileData registered for Span Debugging!" ) ;
90- } else {
91- let fd : & FileData = unsafe { & * ptr } ;
92- pretty_print_span ( fd , span , label ) ;
93- }
94- } )
81+ let linker_ptr = STORED_LINKER . get ( ) ;
82+ if linker_ptr . is_null ( ) {
83+ error ! ( "DEBUG: No Linker registered for Span Debugging!" ) ;
84+ } else {
85+ // SAFETY: Well actually this is totally not safe, since this could be called while a &mut Linker is held, and returned.
86+ // But since this is exclusively for debugging (and therefore should never be part of a release), it doesn't matter.
87+ let linker : & Linker = unsafe { & * linker_ptr } ;
88+ pretty_print_span ( & linker . files , span , label ) ;
89+ }
9590}
9691
9792fn print_stack_top ( enter_exit : & str ) {
@@ -117,19 +112,7 @@ fn print_stack_top(enter_exit: &str) {
117112 } )
118113}
119114
120- pub fn debug_context < R > (
121- stage : & ' static str ,
122- global_obj_name : String ,
123- file_data : & FileData ,
124- f : impl FnOnce ( ) -> R ,
125- ) -> R {
126- MOST_RECENT_FILE_DATA . with ( |ptr| {
127- let file_data = file_data as * const FileData ;
128- ptr. store (
129- file_data as * mut FileData ,
130- std:: sync:: atomic:: Ordering :: SeqCst ,
131- )
132- } ) ;
115+ pub fn debug_context < R > ( stage : & ' static str , global_obj_name : String , f : impl FnOnce ( ) -> R ) -> R {
133116 let config = config ( ) ;
134117
135118 let oot_killer_str = format ! ( "{stage} {global_obj_name}" ) ;
@@ -147,7 +130,6 @@ pub fn debug_context<R>(
147130 global_obj_name,
148131 debugging_enabled,
149132 span_history : CircularBuffer :: new ( ) ,
150- file_data,
151133 } ) ;
152134 } ) ;
153135 print_stack_top ( "Enter " ) ;
@@ -200,9 +182,6 @@ pub fn debugging_enabled() -> bool {
200182 } )
201183}
202184
203- thread_local ! {
204- static STORED_LINKER : Cell <* mut Linker > = const { Cell :: new( std:: ptr:: null_mut( ) ) } ;
205- }
206185/// Set up the hook to print spans. Uses [std::panic::set_hook] instead of [std::panic::catch_unwind] because this runs before my debugger "on panic" breakpoint.
207186/// Use together with [create_dump_on_panic].
208187pub fn setup_panic_handler ( ) {
@@ -223,9 +202,9 @@ pub fn setup_panic_handler() {
223202 )
224203 . red( )
225204 ) ;
226- let file_data = unsafe { & * last_stack_elem . file_data } ;
205+ let linker = unsafe { & * STORED_LINKER . get ( ) } ;
227206 //pretty_print_span(file_data, span, label);
228- print_most_recent_spans ( file_data , last_stack_elem) ;
207+ print_most_recent_spans ( & linker . files , last_stack_elem) ;
229208 } else {
230209 eprintln ! ( "{}" , "No Span-guarding context" . red( ) ) ;
231210 }
@@ -372,7 +351,7 @@ fn spawn_watchdog_thread() {
372351 timers. retain ( |entry| {
373352 let deadline = entry. started_at + duration;
374353 if deadline <= now && entry. alive . load ( std:: sync:: atomic:: Ordering :: SeqCst ) {
375- fatal_exit ! ( "⏰⏰⏰⏰⏰⏰⏰⏰⏰\n ⏰ OutOfTimeKiller triggered in {} after it took more than {:.2} seconds to execute ⏰\n Process will now be terminated." ,
354+ fatal_exit ! ( "⏰⏰⏰⏰⏰⏰⏰⏰⏰\n ⏰ OutOfTimeKiller triggered in {} after it took more than {:.2} seconds to execute ⏰\n Process will now be terminated." ,
376355 entry. info,
377356 ( now - entry. started_at) . as_secs_f64( ) ) ; // To show in stdout when this happens too
378357 } else {
@@ -468,9 +447,8 @@ mod tests {
468447 "non_extistent file text" . to_string ( ) ,
469448 & mut ( ) ,
470449 ) ;
471- let fd = & linker. files [ fd_id] ;
472450
473- debug_context ( "test_context" , "test_obj" . to_string ( ) , fd , || {
451+ debug_context ( "test_context" , "test_obj" . to_string ( ) , || {
474452 let my_span = Span :: from_range ( 3 ..10 , fd_id) ;
475453 my_span. debug ( ) ;
476454 if !linker. files . is_empty ( ) {
0 commit comments