@@ -33,12 +33,16 @@ class _MonitoringTracer:
3333 E .INSTRUCTION : 'opcode' ,
3434 }
3535
36+ GLOBAL_EVENTS = E .PY_START | E .PY_RESUME | E .PY_THROW | E .PY_UNWIND | E .RAISE
37+ LOCAL_EVENTS = E .LINE | E .JUMP | E .PY_RETURN | E .PY_YIELD | E .STOP_ITERATION
38+
3639 def __init__ (self ):
3740 self ._tool_id = sys .monitoring .DEBUGGER_ID
3841 self ._name = 'bdbtracer'
3942 self ._tracefunc = None
4043 self ._disable_current_event = False
4144 self ._tracing_thread = None
45+ self ._enabled = False
4246
4347 def start_trace (self , tracefunc ):
4448 self ._tracefunc = tracefunc
@@ -47,7 +51,7 @@ def start_trace(self, tracefunc):
4751 if curr_tool is None :
4852 sys .monitoring .use_tool_id (self ._tool_id , self ._name )
4953 elif curr_tool == self ._name :
50- sys .monitoring .set_events (self ._tool_id , 0 )
54+ sys .monitoring .clear_tool_id (self ._tool_id )
5155 else :
5256 raise ValueError ('Another debugger is using the monitoring tool' )
5357 E = sys .monitoring .events
@@ -57,17 +61,18 @@ def start_trace(self, tracefunc):
5761 sys .monitoring .register_callback (self ._tool_id , event , callback )
5862 if event != E .INSTRUCTION :
5963 all_events |= event
64+ self .check_trace_func ()
6065 self .check_trace_opcodes ()
61- sys .monitoring .set_events (self ._tool_id , all_events )
66+ sys .monitoring .set_events (self ._tool_id , self .GLOBAL_EVENTS )
67+ self ._enabled = True
6268
6369 def stop_trace (self ):
70+ self ._enabled = False
6471 self ._tracing_thread = None
6572 curr_tool = sys .monitoring .get_tool (self ._tool_id )
6673 if curr_tool != self ._name :
6774 return
68- for event in self .EVENT_CALLBACK_MAP .keys ():
69- sys .monitoring .register_callback (self ._tool_id , event , None )
70- sys .monitoring .set_events (self ._tool_id , 0 )
75+ sys .monitoring .clear_tool_id (self ._tool_id )
7176 self .check_trace_opcodes ()
7277 sys .monitoring .free_tool_id (self ._tool_id )
7378
@@ -88,6 +93,8 @@ def wrapper(self, *args):
8893 try :
8994 frame = sys ._getframe ().f_back
9095 ret = func (self , frame , * args )
96+ if self ._enabled and frame .f_trace :
97+ self .check_trace_func ()
9198 if self ._disable_current_event :
9299 return sys .monitoring .DISABLE
93100 else :
@@ -105,6 +112,8 @@ def call_callback(self, frame, code, *args):
105112 local_tracefunc = self ._tracefunc (frame , 'call' , None )
106113 if local_tracefunc is not None :
107114 frame .f_trace = local_tracefunc
115+ if self ._enabled :
116+ sys .monitoring .set_local_events (self ._tool_id , code , self .LOCAL_EVENTS )
108117
109118 @callback_wrapper
110119 def return_callback (self , frame , code , offset , retval ):
@@ -163,6 +172,14 @@ def set_trace_opcodes(self, frame, trace_opcodes):
163172 else :
164173 sys .monitoring .set_local_events (self ._tool_id , frame .f_code , 0 )
165174
175+ def check_trace_func (self , frame = None ):
176+ if frame is None :
177+ frame = sys ._getframe ().f_back
178+ while frame is not None :
179+ if frame .f_trace is not None :
180+ sys .monitoring .set_local_events (self ._tool_id , frame .f_code , self .LOCAL_EVENTS )
181+ frame = frame .f_back
182+
166183 def _get_lineno (self , code , offset ):
167184 import dis
168185 last_lineno = None
0 commit comments