Skip to content

Commit

Permalink
Listener thread broken out to a standalone class. Communication chann…
Browse files Browse the repository at this point in the history
…el added.
  • Loading branch information
gm281 committed Aug 1, 2014
1 parent 4ff5e84 commit 6fc790d
Showing 1 changed file with 81 additions and 44 deletions.
125 changes: 81 additions & 44 deletions trace.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,45 @@
import threading
import time

def trace(debugger, command, result, internal_dict):
target = debugger.GetSelectedTarget()
print >>result, target
process = target.GetProcess()
print >>result, process
thread = process.GetSelectedThread()
print >>result, thread
frame = thread.GetSelectedFrame()
print >>result, frame
class MyListeningThread(threading.Thread):
def __init__(self, wait_event, notify_event, listener, result):
super(MyListeningThread, self).__init__()
self.wait_event = wait_event
self.notify_event = notify_event
self.listener = listener
self.result = result
self.exiting = False

def isExiting(self):
return self.exiting

def exit(self):
self.exiting = True

def run(self):
while True:
self.wait_event.wait()
self.wait_event.clear()
if self.exiting:
print >>self.result, 'Listener thread was asked to exit, complying'
self.notify_event.set()
return
event = lldb.SBEvent()
print >>self.result, 'Listener thread waiting for an event'
wait_result = self.listener.WaitForEvent(10, event)

if not wait_result:
print >>self.result, 'Listener thread timed out waiting for notification'
self.exiting = True
self.notify_event.set()
return
print >>self.result, '=== YEY'
print >>self.result, 'Event data flavor:', event.GetDataFlavor()
print >>self.result, 'Event string:', lldb.SBEvent.GetCStringFromEvent(event)
print >>self.result, 'Listener thread got event, notifying'
self.notify_event.set()

def instrument_calls(target, thread, frame, result):
# TODO: symbols vs functions
print >>result, frame.GetFunction()
symbol = frame.GetSymbol()
Expand All @@ -37,45 +67,50 @@ def trace(debugger, command, result, internal_dict):
breakpoint.SetThreadID(thread.GetThreadID())
breakpoints[address] = breakpoint
print >>result, breakpoints
return breakpoints

event = lldb.SBEvent()
listener = lldb.SBListener("trace breakpoint listener")
def trace(debugger, command, result, internal_dict):
wait_event = threading.Event()
wait_event.clear()
notify_event = threading.Event()
notify_event.clear()

target = debugger.GetSelectedTarget()
print >>result, target
process = target.GetProcess()
print >>result, process
broadcaster = process.GetBroadcaster()
print >>result, broadcaster
listener = lldb.SBListener("trace breakpoint listener")
rc = broadcaster.AddListener(listener, lldb.SBProcess.eBroadcastBitStateChanged)
if not rc:
print >>result, 'Failed to add listener'
return

print >>result, '=== a'
class MyListeningThread(threading.Thread):
def run(self):
count = 0
# Let's only try at most 4 times to retrieve any kind of event.
# After that, the thread exits.
while not count > 3:
print >>result, 'Try wait for event...'
if listener.WaitForEventForBroadcasterWithType(1,
broadcaster,
lldb.SBProcess.eBroadcastBitStateChanged,
event):
print >>result, '=== YEY'
print >>result, 'Event data flavor:', event.GetDataFlavor()
print >>result, 'Event string:', lldb.SBEvent.GetCStringFromEvent(event)
return
else:
print >>result, 'timeout occurred waiting for event...'
count = count + 1
return
print >>result, '=== b'
my_thread = MyListeningThread()
print >>result, '=== c'
print >>self.result, 'Failed to add listener'

my_thread = MyListeningThread(wait_event, notify_event, listener, result)
my_thread.start()
print >>result, '=== d'
thread = process.GetSelectedThread()
print >>result, thread
frame = thread.GetSelectedFrame()


breakpoints = instrument_calls(target, thread, frame, result)
print >>result, 'Instrumented all calls, running process'
print >>result, process.GetState()
process.Continue()
print >>result, '=== e'
my_thread.join()
print >>result, '=== f'
wait_event.set()
print >>result, 'Process continued, waiting for notification'
notify_event.wait()
notify_event.clear()
while process.GetState() != lldb.eStateStopped:
wait_event.set()
notify_event.wait()
notify_event.clear()
print >>result, 'Got notification, sanity checks follow'
print >>result, process.GetState()
# Some sanity checking
if my_thread.isExiting():
print >>result, 'Listener thread exited unexpectedly'
return
if thread.GetStopReason() != lldb.eStopReasonBreakpoint:
print >>result, thread
print >>result, "Thread under trace didn't stop due to a breakpoint"
Expand All @@ -92,9 +127,11 @@ def run(self):
for breakpoint in breakpoints.itervalues():
print >>result, 'Deleting breakpoint %d' % breakpoint.GetID()
target.BreakpointDelete(breakpoint.GetID())



my_thread.exit()
wait_event.set()
my_thread.join()
broadcaster.RemoveListener(listener)
print >>result, 'Listener thread exited completing'

# And the initialization code to add your commands
def __lldb_init_module(debugger, internal_dict):
Expand Down

0 comments on commit 6fc790d

Please sign in to comment.