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:
Elizaveta Shashkova
2017-02-14 15:06:50 +03:00
parent 9c4ae0b297
commit 34045abb37
6 changed files with 471 additions and 336 deletions
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)
+5
View File
@@ -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
+7 -4
View File
@@ -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