Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
fabioz committed Nov 10, 2023
1 parent 17b4237 commit 3aa51a0
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 30 deletions.
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
from _pydevd_bundle import pydevd_utils
from _pydevd_bundle.pydevd_additional_thread_info import set_additional_thread_info
from _pydevd_bundle.pydevd_comm_constants import CMD_STEP_INTO, CMD_THREAD_SUSPEND
from _pydevd_bundle.pydevd_constants import PYTHON_SUSPEND, STATE_SUSPEND, get_thread_id, STATE_RUN
from _pydevd_bundle.pydevd_constants import PYTHON_SUSPEND, STATE_SUSPEND, get_thread_id, STATE_RUN, \
USE_SYS_MONITORING
from _pydev_bundle._pydev_saved_modules import threading
from _pydev_bundle import pydev_log
import sys
from _pydevd_sys_monitoring import pydevd_sys_monitoring


def pydevd_find_thread_by_id(thread_id):
Expand Down Expand Up @@ -94,3 +97,7 @@ def suspend_all_threads(py_db, except_thread):
py_db.set_trace_for_frame_and_parents(frame)
finally:
frame = None

if USE_SYS_MONITORING:
# After suspending the frames we need the monitoring to be reset.
pydevd_sys_monitoring.restart_events()
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,10 @@ def enable_line_tracing(code):
monitor.set_local_events(DEBUGGER_ID, code, events | monitor.events.LINE)


def enable_code_tracing(code):
enable_line_tracing(code)


def _line_event(code, line):
print('line event', code, line)

Expand Down Expand Up @@ -456,3 +460,9 @@ def stop_monitoring(all_threads=False):
if thread_info is None:
return
thread_info.trace = False


def restart_events():
print('restart events')
sys.monitoring.restart_events()

38 changes: 28 additions & 10 deletions plugins/org.python.pydev.core/pysrc/pydevd.py
Original file line number Diff line number Diff line change
Expand Up @@ -1207,6 +1207,9 @@ def set_tracing_for_untraced_contexts(self):
threads = None
additional_info = None

if USE_SYS_MONITORING:
pydevd_sys_monitoring.restart_events()

@property
def multi_threads_single_notification(self):
return self._threads_suspended_single_notification.multi_threads_single_notification
Expand Down Expand Up @@ -1935,6 +1938,10 @@ def set_suspend(self, thread, stop_reason, suspend_other_threads=False, is_pause
# Suspend all except the current one (which we're currently suspending already).
suspend_all_threads(self, except_thread=thread)

if is_pause and not suspend_other_threads:
# When suspending other threads this is already called.
pydevd_sys_monitoring.restart_events()

def _send_breakpoint_condition_exception(self, thread, conditional_breakpoint_exception_tuple):
"""If conditional breakpoint raises an exception during evaluation
send exception details to java
Expand Down Expand Up @@ -2278,18 +2285,29 @@ def set_trace_for_frame_and_parents(self, frame, **kwargs):
while frame is not None:
# Don't change the tracing on debugger-related files
file_type = self.get_file_type(frame)
if USE_SYS_MONITORING:
if file_type is None:
if disable:
pydev_log.debug('Disable tracing of frame: %s - %s', frame.f_code.co_filename, frame.f_code.co_name)

if file_type is None:
if disable:
pydev_log.debug('Disable tracing of frame: %s - %s', frame.f_code.co_filename, frame.f_code.co_name)
if frame.f_trace is not None and frame.f_trace is not NO_FTRACE:
frame.f_trace = NO_FTRACE

elif frame.f_trace is not self.trace_dispatch:
pydev_log.debug('Set tracing of frame: %s - %s', frame.f_code.co_filename, frame.f_code.co_name)
frame.f_trace = self.trace_dispatch
else:
pydev_log.debug('Set tracing of frame: %s - %s', frame.f_code.co_filename, frame.f_code.co_name)
pydevd_sys_monitoring.enable_code_tracing(frame.f_code)
else:
pydev_log.debug('SKIP set tracing of frame: %s - %s', frame.f_code.co_filename, frame.f_code.co_name)
else:
pydev_log.debug('SKIP set tracing of frame: %s - %s', frame.f_code.co_filename, frame.f_code.co_name)
# Not using sys.monitoring.
if file_type is None:
if disable:
pydev_log.debug('Disable tracing of frame: %s - %s', frame.f_code.co_filename, frame.f_code.co_name)
if frame.f_trace is not None and frame.f_trace is not NO_FTRACE:
frame.f_trace = NO_FTRACE

elif frame.f_trace is not self.trace_dispatch:
pydev_log.debug('Set tracing of frame: %s - %s', frame.f_code.co_filename, frame.f_code.co_name)
frame.f_trace = self.trace_dispatch
else:
pydev_log.debug('SKIP set tracing of frame: %s - %s', frame.f_code.co_filename, frame.f_code.co_name)

frame = frame.f_back

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,71 @@
import sys
import pytest
import threading

DEBUGGER_ID = sys.monitoring.DEBUGGER_ID
monitor = sys.monitoring


def test_change_line_during_trace():
def _disable_monitoring():
if monitor.get_tool(DEBUGGER_ID) == 'pydevd':
sys.monitoring.set_events(sys.monitoring.DEBUGGER_ID, 0)
monitor.register_callback(DEBUGGER_ID, monitor.events.PY_START , None)
monitor.register_callback(DEBUGGER_ID, monitor.events.PY_RESUME, None)
monitor.register_callback(DEBUGGER_ID, monitor.events.LINE, None)
sys.monitoring.free_tool_id(DEBUGGER_ID)


@pytest.fixture
def with_monitoring():
monitor.use_tool_id(DEBUGGER_ID, 'pydevd')
yield
_disable_monitoring()


def test_disabling_code(with_monitoring):

executed = []

def _start_method(code, offset):
if code.co_name == 'method':
executed.append(('start', code.co_name, offset))
monitor.set_local_events(DEBUGGER_ID, code, monitor.events.LINE)
return monitor.DISABLE

def _on_line(code, offset):
if code.co_name == 'method':
executed.append(('line', code.co_name, offset))
return monitor.DISABLE

monitor.set_events(DEBUGGER_ID, monitor.events.PY_START | monitor.events.PY_RESUME)

monitor.register_callback(DEBUGGER_ID, monitor.events.PY_START , _start_method)
monitor.register_callback(DEBUGGER_ID, monitor.events.PY_RESUME, _start_method)
monitor.register_callback(DEBUGGER_ID, monitor.events.LINE, _on_line)

def method():
a = 1

method()
method()
assert executed == [('start', 'method', 0), ('line', 'method', method.__code__.co_firstlineno + 1)]

del executed[:]
t = threading.Thread(target=method)
t.start()
t.join()

# If disable once, even on a new thread we won't get notifications
assert not executed

monitor.restart_events()
t = threading.Thread(target=method)
t.start()
t.join()
assert executed == [('start', 'method', 0), ('line', 'method', method.__code__.co_firstlineno + 1)]


def test_change_line_during_trace(with_monitoring):
code_to_break_at_line = {}
do_change_line = [0]
lines_traced = []
Expand All @@ -23,25 +84,30 @@ def _on_line(code, line):
print(frame.f_lineno)
frame.f_lineno = line - 2

monitor.use_tool_id(DEBUGGER_ID, 'pydevd')
try:
monitor.set_events(DEBUGGER_ID, monitor.events.PY_START | monitor.events.PY_RESUME)
monitor.set_events(DEBUGGER_ID, monitor.events.PY_START | monitor.events.PY_RESUME)

monitor.register_callback(DEBUGGER_ID, monitor.events.PY_START , _start_method)
monitor.register_callback(DEBUGGER_ID, monitor.events.PY_RESUME, _start_method)
monitor.register_callback(DEBUGGER_ID, monitor.events.LINE, _on_line)
monitor.register_callback(DEBUGGER_ID, monitor.events.PY_START , _start_method)
monitor.register_callback(DEBUGGER_ID, monitor.events.PY_RESUME, _start_method)
monitor.register_callback(DEBUGGER_ID, monitor.events.LINE, _on_line)

def method1(): # code.co_firstlineno
a = 1 # code.co_firstlineno + 1
lines_traced.append('before a=2') # code.co_firstlineno + 2
a = 2 # code.co_firstlineno + 3
lines_traced.append('before a=3') # code.co_firstlineno + 4
# a = 3 # code.co_firstlineno + 5
def method1(): # code.co_firstlineno
a = 1 # code.co_firstlineno + 1
lines_traced.append('before a=2') # code.co_firstlineno + 2
a = 2 # code.co_firstlineno + 3
lines_traced.append('before a=3') # code.co_firstlineno + 4
# a = 3 # code.co_firstlineno + 5

for _i in range(3):
method1()
for _i in range(3):
method1()

assert lines_traced == []
sys.monitoring.set_events(sys.monitoring.DEBUGGER_ID, 0)
finally:
sys.monitoring.free_tool_id(DEBUGGER_ID)
assert lines_traced == [
'before a=2',
'before a=3',

'before a=2',
'before a=2',

'before a=3',
'before a=2',
'before a=3',
]

0 comments on commit 3aa51a0

Please sign in to comment.