Debugged applications may crash randomly after calling Debug.stop()
chschmitt opened this issue · 3 comments
The title pretty much describes the problem. I am debugging various 32 bit applications using the Debug
class. Before calling Debug.next()
I check a threading.Event
in my debugging loop to see if the debugger should detach. If the event is set, Debug.stop()
is called. The debugger quits nicely, but often the debugged application crashes (showing the windows dialog "<foo.exe> has stopped working").
The exception codes I saw were either 0x80000003 or 0x80000004.
Is that a general issue when debugging windows applications or is it possibly a bug?
Sounds like a bug indeed. 0x80000003 is EXCEPTION_BREAKPOINT, the exception raised when a breakpoint instruction is executed. This would mean WinAppDbg is not correctly removing all breakpoints before detaching.
Question, are you trying to call Debug.stop() in response to a breakpoint event?
As a workaround, I suppose you could remove all breakpoints in your script before calling stop(), but I get the feeling the problem is not quite there, but more on the lines of the breakpoint event not being ignored when continuing execution...
The event is set from another thread. Effectively, stop()
is called immediately before my version of next()
in the debugger's main loop, not from an event handler, i.e. dispatch()
has already returned. I found that get_debugee_count()
is still 1 when stop()
returns.
def next(self):
# exceptions are caught in main loop
self.debug.wait()
try:
self.debug.dispatch()
finally:
self.debug.cont()
I tried some things and I suspect that the removal of a breakpoint while it is hit leaves the debugged process messed up (i.e. with the break instruction still in memory). The following seems to work:
- Disable all breakpoints when stop event is set
- Continue main loop
- Break main loop and call
stop()
when a timeout was hit
def mainloop(self):
while True:
if self.shared.stop_event.is_set():
self.debug.disable_all_breakpoints()
try:
if not self.next() and self.shared.stop_event.is_set():
print('stop is set & got wait timeout: breaking main loop')
break
except Exception:
print('error in tracer loop, calling stop_debug() unconditionally')
self.debug.stop()
raise
if not self.debug:
print('all debugees gone')
break
self.debug.stop()
print('debug event loop has been left normally')
def next(self):
try:
self.debug.wait(5000)
except WindowsError as e:
if e.winerror == 121:
return False
raise
try:
self.debug.dispatch()
finally:
self.debug.cont()
return True
BTW: Thanks for your excellent library