mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Fix working with threads in frame evaluation debugger (PY-22450, PY-22454)
We need to use old tracing function for suspending threads without breakpoint. Also sys.settrace() should be called inside a thread, that's why we pass this command as internal thread command.
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,8 @@
|
||||
import dis
|
||||
from _pydev_imps._pydev_saved_modules import threading
|
||||
from _pydevd_bundle.pydevd_additional_thread_info import PyDBAdditionalThreadInfo
|
||||
from _pydevd_bundle.pydevd_comm import get_global_debugger
|
||||
from _pydevd_bundle.pydevd_comm import get_global_debugger, CMD_THREAD_SUSPEND
|
||||
from _pydevd_bundle.pydevd_constants import STATE_SUSPEND
|
||||
from _pydevd_bundle.pydevd_dont_trace_files import DONT_TRACE
|
||||
from _pydevd_frame_eval.pydevd_frame_tracing import pydev_trace_code_wrapper, update_globals_dict
|
||||
from _pydevd_frame_eval.pydevd_modify_bytecode import insert_code
|
||||
@@ -56,6 +57,9 @@ cdef PyObject* get_bytecode_while_frame_eval(PyFrameObject *frame_obj, int exc):
|
||||
return _PyEval_EvalFrameDefault(frame_obj, exc)
|
||||
|
||||
main_debugger = get_global_debugger()
|
||||
if additional_info.pydev_state == STATE_SUSPEND and t.stop_reason == CMD_THREAD_SUSPEND:
|
||||
main_debugger.process_internal_commands()
|
||||
|
||||
breakpoints = main_debugger.breakpoints.get(abs_path_real_path_and_base[1])
|
||||
if breakpoints:
|
||||
was_break = False
|
||||
|
||||
@@ -12,10 +12,11 @@ def update_globals_dict(globals_dict):
|
||||
globals_dict.update(new_globals)
|
||||
|
||||
|
||||
def handle_breakpoint(frame, info, global_debugger, breakpoint):
|
||||
def handle_breakpoint(frame, thread, global_debugger, breakpoint):
|
||||
# ok, hit breakpoint, now, we have to discover if it is a conditional breakpoint
|
||||
new_frame = frame
|
||||
condition = breakpoint.condition
|
||||
info = thread.additional_info
|
||||
if condition is not None:
|
||||
try:
|
||||
val = eval(condition, new_frame.f_globals, new_frame.f_locals)
|
||||
@@ -58,6 +59,10 @@ def handle_breakpoint(frame, info, global_debugger, breakpoint):
|
||||
finally:
|
||||
if val is not None:
|
||||
info.pydev_message = str(val)
|
||||
|
||||
if breakpoint.suspend_policy == "ALL":
|
||||
global_debugger.suspend_all_other_threads(thread)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
@@ -94,7 +99,7 @@ def _pydev_stop_at_break():
|
||||
except KeyError:
|
||||
pydev_log.debug("Couldn't find breakpoint in the file {} on line {}".format(frame.f_code.co_filename, line))
|
||||
return
|
||||
if breakpoint and handle_breakpoint(frame, t.additional_info, debugger, breakpoint):
|
||||
if breakpoint and handle_breakpoint(frame, t, debugger, breakpoint):
|
||||
pydev_log.debug("Suspending at breakpoint in file: {} on line {}".format(frame.f_code.co_filename, line))
|
||||
debugger.set_suspend(t, CMD_SET_BREAK)
|
||||
debugger.do_wait_suspend(t, frame, 'line', None)
|
||||
|
||||
@@ -670,6 +670,11 @@ class PyDB:
|
||||
if stop_reason == CMD_SET_BREAK and self.suspend_on_breakpoint_exception:
|
||||
self._send_breakpoint_condition_exception(thread)
|
||||
|
||||
if self.frame_eval_func is not None and stop_reason == CMD_THREAD_SUSPEND:
|
||||
thread_id = get_thread_id(thread)
|
||||
int_cmd = InternalSetTracingThread(thread_id)
|
||||
self.post_internal_command(int_cmd, thread_id)
|
||||
|
||||
|
||||
def _send_breakpoint_condition_exception(self, thread):
|
||||
"""If conditional breakpoint raises an exception during evaluation
|
||||
|
||||
@@ -2,17 +2,20 @@ from threading import Thread
|
||||
from time import sleep
|
||||
|
||||
|
||||
def print_with_pause(text, pause):
|
||||
sleep(pause)
|
||||
print(text)
|
||||
|
||||
|
||||
def fun1(n):
|
||||
while True:
|
||||
sleep(0.01)
|
||||
print("finished fun1()", n)
|
||||
print_with_pause("Thread1", 0.1)
|
||||
|
||||
|
||||
def fun2(m):
|
||||
sleep(2)
|
||||
while True:
|
||||
sleep(0.01) #breakpoint
|
||||
print("finished fun2()", m)
|
||||
print_with_pause("Thread2", 0.1) # breakpoint
|
||||
|
||||
|
||||
threads = [Thread(target=fun1, args=(24,), name="Thread1"),
|
||||
|
||||
@@ -1002,8 +1002,8 @@ public class PythonDebuggerTest extends PyEnvTestCase {
|
||||
|
||||
@Override
|
||||
public void before() throws Exception {
|
||||
toggleBreakpoint(getFilePath(getScriptName()), 12);
|
||||
setBreakpointSuspendPolicy(getProject(), 12, SuspendPolicy.ALL);
|
||||
toggleBreakpoint(getFilePath(getScriptName()), 17);
|
||||
setBreakpointSuspendPolicy(getProject(), 17, SuspendPolicy.ALL);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1056,8 +1056,8 @@ public class PythonDebuggerTest extends PyEnvTestCase {
|
||||
runPythonTest(new PyDebuggerTask("/debug", "test_two_threads.py") {
|
||||
@Override
|
||||
public void before() throws Exception {
|
||||
toggleBreakpoint(getFilePath(getScriptName()), 12);
|
||||
setBreakpointSuspendPolicy(getProject(), 12, SuspendPolicy.THREAD);
|
||||
toggleBreakpoint(getFilePath(getScriptName()), 17);
|
||||
setBreakpointSuspendPolicy(getProject(), 17, SuspendPolicy.THREAD);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user