Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 20fe983

Browse files
committed
Merge with 3.5
2 parents cc96d5e + 0a7b2ae commit 20fe983

1 file changed

Lines changed: 53 additions & 7 deletions

File tree

Lib/idlelib/Debugger.py

Lines changed: 53 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@ def user_line(self, frame):
1717
self.set_step()
1818
return
1919
message = self.__frame2message(frame)
20-
self.gui.interaction(message, frame)
20+
try:
21+
self.gui.interaction(message, frame)
22+
except (TclError, RuntimeError):
23+
pass
2124

2225
def user_exception(self, frame, info):
2326
if self.in_rpc_code(frame):
@@ -59,8 +62,42 @@ def __init__(self, pyshell, idb=None):
5962
self.frame = None
6063
self.make_gui()
6164
self.interacting = 0
65+
self.nesting_level = 0
6266

6367
def run(self, *args):
68+
# Deal with the scenario where we've already got a program running
69+
# in the debugger and we want to start another. If that is the case,
70+
# our second 'run' was invoked from an event dispatched not from
71+
# the main event loop, but from the nested event loop in 'interaction'
72+
# below. So our stack looks something like this:
73+
# outer main event loop
74+
# run()
75+
# <running program with traces>
76+
# callback to debugger's interaction()
77+
# nested event loop
78+
# run() for second command
79+
#
80+
# This kind of nesting of event loops causes all kinds of problems
81+
# (see e.g. issue #24455) especially when dealing with running as a
82+
# subprocess, where there's all kinds of extra stuff happening in
83+
# there - insert a traceback.print_stack() to check it out.
84+
#
85+
# By this point, we've already called restart_subprocess() in
86+
# ScriptBinding. However, we also need to unwind the stack back to
87+
# that outer event loop. To accomplish this, we:
88+
# - return immediately from the nested run()
89+
# - abort_loop ensures the nested event loop will terminate
90+
# - the debugger's interaction routine completes normally
91+
# - the restart_subprocess() will have taken care of stopping
92+
# the running program, which will also let the outer run complete
93+
#
94+
# That leaves us back at the outer main event loop, at which point our
95+
# after event can fire, and we'll come back to this routine with a
96+
# clean stack.
97+
if self.nesting_level > 0:
98+
self.abort_loop()
99+
self.root.after(100, lambda: self.run(*args))
100+
return
64101
try:
65102
self.interacting = 1
66103
return self.idb.run(*args)
@@ -71,6 +108,7 @@ def close(self, event=None):
71108
if self.interacting:
72109
self.top.bell()
73110
return
111+
self.abort_loop()
74112
if self.stackviewer:
75113
self.stackviewer.close(); self.stackviewer = None
76114
# Clean up pyshell if user clicked debugger control close widget.
@@ -191,7 +229,12 @@ def interaction(self, message, frame, info=None):
191229
b.configure(state="normal")
192230
#
193231
self.top.wakeup()
194-
self.root.mainloop()
232+
# Nested main loop: Tkinter's main loop is not reentrant, so use
233+
# Tcl's vwait facility, which reenters the event loop until an
234+
# event handler sets the variable we're waiting on
235+
self.nesting_level += 1
236+
self.root.tk.call('vwait', '::idledebugwait')
237+
self.nesting_level -= 1
195238
#
196239
for b in self.buttons:
197240
b.configure(state="disabled")
@@ -215,23 +258,26 @@ def __frame2fileline(self, frame):
215258

216259
def cont(self):
217260
self.idb.set_continue()
218-
self.root.quit()
261+
self.abort_loop()
219262

220263
def step(self):
221264
self.idb.set_step()
222-
self.root.quit()
265+
self.abort_loop()
223266

224267
def next(self):
225268
self.idb.set_next(self.frame)
226-
self.root.quit()
269+
self.abort_loop()
227270

228271
def ret(self):
229272
self.idb.set_return(self.frame)
230-
self.root.quit()
273+
self.abort_loop()
231274

232275
def quit(self):
233276
self.idb.set_quit()
234-
self.root.quit()
277+
self.abort_loop()
278+
279+
def abort_loop(self):
280+
self.root.tk.call('set', '::idledebugwait', '1')
235281

236282
stackviewer = None
237283

0 commit comments

Comments
 (0)