11//! Tracer trait and sys.monitoring callback plumbing.
22
33use std:: any:: Any ;
4+ use std:: panic:: { catch_unwind, AssertUnwindSafe } ;
45use std:: sync:: Mutex ;
56
67use crate :: code_object:: { CodeObjectRegistry , CodeObjectWrapper } ;
@@ -264,6 +265,32 @@ struct Global {
264265
265266static GLOBAL : Mutex < Option < Global > > = Mutex :: new ( None ) ;
266267
268+ fn catch_callback < F > ( label : & ' static str , callback : F ) -> CallbackResult
269+ where
270+ F : FnOnce ( ) -> CallbackResult ,
271+ {
272+ match catch_unwind ( AssertUnwindSafe ( callback) ) {
273+ Ok ( result) => result,
274+ Err ( payload) => Err ( ffi:: panic_to_pyerr ( label, payload) ) ,
275+ }
276+ }
277+
278+ fn call_tracer_with_code < ' py , F > (
279+ py : Python < ' py > ,
280+ guard : & mut Option < Global > ,
281+ code : & Bound < ' py , PyCode > ,
282+ label : & ' static str ,
283+ callback : F ,
284+ ) -> CallbackResult
285+ where
286+ F : FnOnce ( & mut dyn Tracer , & CodeObjectWrapper ) -> CallbackResult ,
287+ {
288+ let global = guard. as_mut ( ) . expect ( "tracer installed" ) ;
289+ let wrapper = global. registry . get_or_insert ( py, code) ;
290+ let tracer = global. tracer . as_mut ( ) ;
291+ catch_callback ( label, || callback ( tracer, & wrapper) )
292+ }
293+
267294fn handle_callback_result (
268295 py : Python < ' _ > ,
269296 guard : & mut Option < Global > ,
@@ -519,13 +546,10 @@ fn callback_call(
519546 if guard. is_none ( ) {
520547 return Ok ( py. None ( ) ) ;
521548 }
522- let result = {
523- let global = guard. as_mut ( ) . expect ( "tracer installed" ) ;
524- let wrapper = global. registry . get_or_insert ( py, & code) ;
525- global
526- . tracer
527- . on_call ( py, & wrapper, offset, & callable, arg0. as_ref ( ) )
528- } ;
549+ let result =
550+ call_tracer_with_code ( py, & mut guard, & code, "callback_call" , |tracer, wrapper| {
551+ tracer. on_call ( py, wrapper, offset, & callable, arg0. as_ref ( ) )
552+ } ) ;
529553 handle_callback_result ( py, & mut guard, result)
530554 } )
531555}
@@ -537,11 +561,10 @@ fn callback_line(py: Python<'_>, code: Bound<'_, PyCode>, lineno: u32) -> PyResu
537561 if guard. is_none ( ) {
538562 return Ok ( py. None ( ) ) ;
539563 }
540- let result = {
541- let global = guard. as_mut ( ) . expect ( "tracer installed" ) ;
542- let wrapper = global. registry . get_or_insert ( py, & code) ;
543- global. tracer . on_line ( py, & wrapper, lineno)
544- } ;
564+ let result =
565+ call_tracer_with_code ( py, & mut guard, & code, "callback_line" , |tracer, wrapper| {
566+ tracer. on_line ( py, wrapper, lineno)
567+ } ) ;
545568 handle_callback_result ( py, & mut guard, result)
546569 } )
547570}
@@ -557,13 +580,13 @@ fn callback_instruction(
557580 if guard. is_none ( ) {
558581 return Ok ( py. None ( ) ) ;
559582 }
560- let result = {
561- let global = guard . as_mut ( ) . expect ( "tracer installed" ) ;
562- let wrapper = global . registry . get_or_insert ( py , & code ) ;
563- global
564- . tracer
565- . on_instruction ( py, & wrapper, instruction_offset)
566- } ;
583+ let result = call_tracer_with_code (
584+ py ,
585+ & mut guard ,
586+ & code ,
587+ "callback_instruction" ,
588+ |tracer , wrapper| tracer . on_instruction ( py, wrapper, instruction_offset) ,
589+ ) ;
567590 handle_callback_result ( py, & mut guard, result)
568591 } )
569592}
@@ -580,13 +603,10 @@ fn callback_jump(
580603 if guard. is_none ( ) {
581604 return Ok ( py. None ( ) ) ;
582605 }
583- let result = {
584- let global = guard. as_mut ( ) . expect ( "tracer installed" ) ;
585- let wrapper = global. registry . get_or_insert ( py, & code) ;
586- global
587- . tracer
588- . on_jump ( py, & wrapper, instruction_offset, destination_offset)
589- } ;
606+ let result =
607+ call_tracer_with_code ( py, & mut guard, & code, "callback_jump" , |tracer, wrapper| {
608+ tracer. on_jump ( py, wrapper, instruction_offset, destination_offset)
609+ } ) ;
590610 handle_callback_result ( py, & mut guard, result)
591611 } )
592612}
@@ -603,13 +623,13 @@ fn callback_branch(
603623 if guard. is_none ( ) {
604624 return Ok ( py. None ( ) ) ;
605625 }
606- let result = {
607- let global = guard . as_mut ( ) . expect ( "tracer installed" ) ;
608- let wrapper = global . registry . get_or_insert ( py , & code ) ;
609- global
610- . tracer
611- . on_branch ( py, & wrapper, instruction_offset, destination_offset)
612- } ;
626+ let result = call_tracer_with_code (
627+ py ,
628+ & mut guard ,
629+ & code ,
630+ "callback_branch" ,
631+ |tracer , wrapper| tracer . on_branch ( py, wrapper, instruction_offset, destination_offset) ,
632+ ) ;
613633 handle_callback_result ( py, & mut guard, result)
614634 } )
615635}
@@ -625,11 +645,13 @@ fn callback_py_start(
625645 if guard. is_none ( ) {
626646 return Ok ( py. None ( ) ) ;
627647 }
628- let result = {
629- let global = guard. as_mut ( ) . expect ( "tracer installed" ) ;
630- let wrapper = global. registry . get_or_insert ( py, & code) ;
631- global. tracer . on_py_start ( py, & wrapper, instruction_offset)
632- } ;
648+ let result = call_tracer_with_code (
649+ py,
650+ & mut guard,
651+ & code,
652+ "callback_py_start" ,
653+ |tracer, wrapper| tracer. on_py_start ( py, wrapper, instruction_offset) ,
654+ ) ;
633655 handle_callback_result ( py, & mut guard, result)
634656 } )
635657}
@@ -645,11 +667,13 @@ fn callback_py_resume(
645667 if guard. is_none ( ) {
646668 return Ok ( py. None ( ) ) ;
647669 }
648- let result = {
649- let global = guard. as_mut ( ) . expect ( "tracer installed" ) ;
650- let wrapper = global. registry . get_or_insert ( py, & code) ;
651- global. tracer . on_py_resume ( py, & wrapper, instruction_offset)
652- } ;
670+ let result = call_tracer_with_code (
671+ py,
672+ & mut guard,
673+ & code,
674+ "callback_py_resume" ,
675+ |tracer, wrapper| tracer. on_py_resume ( py, wrapper, instruction_offset) ,
676+ ) ;
653677 handle_callback_result ( py, & mut guard, result)
654678 } )
655679}
@@ -666,13 +690,13 @@ fn callback_py_return(
666690 if guard. is_none ( ) {
667691 return Ok ( py. None ( ) ) ;
668692 }
669- let result = {
670- let global = guard . as_mut ( ) . expect ( "tracer installed" ) ;
671- let wrapper = global . registry . get_or_insert ( py , & code ) ;
672- global
673- . tracer
674- . on_py_return ( py, & wrapper, instruction_offset, & retval)
675- } ;
693+ let result = call_tracer_with_code (
694+ py ,
695+ & mut guard ,
696+ & code ,
697+ "callback_py_return" ,
698+ |tracer , wrapper| tracer . on_py_return ( py, wrapper, instruction_offset, & retval) ,
699+ ) ;
676700 handle_callback_result ( py, & mut guard, result)
677701 } )
678702}
@@ -689,13 +713,13 @@ fn callback_py_yield(
689713 if guard. is_none ( ) {
690714 return Ok ( py. None ( ) ) ;
691715 }
692- let result = {
693- let global = guard . as_mut ( ) . expect ( "tracer installed" ) ;
694- let wrapper = global . registry . get_or_insert ( py , & code ) ;
695- global
696- . tracer
697- . on_py_yield ( py, & wrapper, instruction_offset, & retval)
698- } ;
716+ let result = call_tracer_with_code (
717+ py ,
718+ & mut guard ,
719+ & code ,
720+ "callback_py_yield" ,
721+ |tracer , wrapper| tracer . on_py_yield ( py, wrapper, instruction_offset, & retval) ,
722+ ) ;
699723 handle_callback_result ( py, & mut guard, result)
700724 } )
701725}
@@ -712,13 +736,13 @@ fn callback_py_throw(
712736 if guard. is_none ( ) {
713737 return Ok ( py. None ( ) ) ;
714738 }
715- let result = {
716- let global = guard . as_mut ( ) . expect ( "tracer installed" ) ;
717- let wrapper = global . registry . get_or_insert ( py , & code ) ;
718- global
719- . tracer
720- . on_py_throw ( py, & wrapper, instruction_offset, & exception)
721- } ;
739+ let result = call_tracer_with_code (
740+ py ,
741+ & mut guard ,
742+ & code ,
743+ "callback_py_throw" ,
744+ |tracer , wrapper| tracer . on_py_throw ( py, wrapper, instruction_offset, & exception) ,
745+ ) ;
722746 handle_callback_result ( py, & mut guard, result)
723747 } )
724748}
@@ -735,13 +759,13 @@ fn callback_py_unwind(
735759 if guard. is_none ( ) {
736760 return Ok ( py. None ( ) ) ;
737761 }
738- let result = {
739- let global = guard . as_mut ( ) . expect ( "tracer installed" ) ;
740- let wrapper = global . registry . get_or_insert ( py , & code ) ;
741- global
742- . tracer
743- . on_py_unwind ( py, & wrapper, instruction_offset, & exception)
744- } ;
762+ let result = call_tracer_with_code (
763+ py ,
764+ & mut guard ,
765+ & code ,
766+ "callback_py_unwind" ,
767+ |tracer , wrapper| tracer . on_py_unwind ( py, wrapper, instruction_offset, & exception) ,
768+ ) ;
745769 handle_callback_result ( py, & mut guard, result)
746770 } )
747771}
@@ -758,13 +782,13 @@ fn callback_raise(
758782 if guard. is_none ( ) {
759783 return Ok ( py. None ( ) ) ;
760784 }
761- let result = {
762- let global = guard . as_mut ( ) . expect ( "tracer installed" ) ;
763- let wrapper = global . registry . get_or_insert ( py , & code ) ;
764- global
765- . tracer
766- . on_raise ( py, & wrapper, instruction_offset, & exception)
767- } ;
785+ let result = call_tracer_with_code (
786+ py ,
787+ & mut guard ,
788+ & code ,
789+ "callback_raise" ,
790+ |tracer , wrapper| tracer . on_raise ( py, wrapper, instruction_offset, & exception) ,
791+ ) ;
768792 handle_callback_result ( py, & mut guard, result)
769793 } )
770794}
@@ -781,13 +805,13 @@ fn callback_reraise(
781805 if guard. is_none ( ) {
782806 return Ok ( py. None ( ) ) ;
783807 }
784- let result = {
785- let global = guard . as_mut ( ) . expect ( "tracer installed" ) ;
786- let wrapper = global . registry . get_or_insert ( py , & code ) ;
787- global
788- . tracer
789- . on_reraise ( py, & wrapper, instruction_offset, & exception)
790- } ;
808+ let result = call_tracer_with_code (
809+ py ,
810+ & mut guard ,
811+ & code ,
812+ "callback_reraise" ,
813+ |tracer , wrapper| tracer . on_reraise ( py, wrapper, instruction_offset, & exception) ,
814+ ) ;
791815 handle_callback_result ( py, & mut guard, result)
792816 } )
793817}
@@ -804,13 +828,15 @@ fn callback_exception_handled(
804828 if guard. is_none ( ) {
805829 return Ok ( py. None ( ) ) ;
806830 }
807- let result = {
808- let global = guard. as_mut ( ) . expect ( "tracer installed" ) ;
809- let wrapper = global. registry . get_or_insert ( py, & code) ;
810- global
811- . tracer
812- . on_exception_handled ( py, & wrapper, instruction_offset, & exception)
813- } ;
831+ let result = call_tracer_with_code (
832+ py,
833+ & mut guard,
834+ & code,
835+ "callback_exception_handled" ,
836+ |tracer, wrapper| {
837+ tracer. on_exception_handled ( py, wrapper, instruction_offset, & exception)
838+ } ,
839+ ) ;
814840 handle_callback_result ( py, & mut guard, result)
815841 } )
816842}
@@ -844,13 +870,13 @@ fn callback_c_return(
844870 if guard. is_none ( ) {
845871 return Ok ( py. None ( ) ) ;
846872 }
847- let result = {
848- let global = guard . as_mut ( ) . expect ( "tracer installed" ) ;
849- let wrapper = global . registry . get_or_insert ( py , & code ) ;
850- global
851- . tracer
852- . on_c_return ( py, & wrapper, offset, & callable, arg0. as_ref ( ) )
853- } ;
873+ let result = call_tracer_with_code (
874+ py ,
875+ & mut guard ,
876+ & code ,
877+ "callback_c_return" ,
878+ |tracer , wrapper| tracer . on_c_return ( py, wrapper, offset, & callable, arg0. as_ref ( ) ) ,
879+ ) ;
854880 handle_callback_result ( py, & mut guard, result)
855881 } )
856882}
@@ -868,13 +894,13 @@ fn callback_c_raise(
868894 if guard. is_none ( ) {
869895 return Ok ( py. None ( ) ) ;
870896 }
871- let result = {
872- let global = guard . as_mut ( ) . expect ( "tracer installed" ) ;
873- let wrapper = global . registry . get_or_insert ( py , & code ) ;
874- global
875- . tracer
876- . on_c_raise ( py, & wrapper, offset, & callable, arg0. as_ref ( ) )
877- } ;
897+ let result = call_tracer_with_code (
898+ py ,
899+ & mut guard ,
900+ & code ,
901+ "callback_c_raise" ,
902+ |tracer , wrapper| tracer . on_c_raise ( py, wrapper, offset, & callable, arg0. as_ref ( ) ) ,
903+ ) ;
878904 handle_callback_result ( py, & mut guard, result)
879905 } )
880906}
0 commit comments