[lldb-dev] Async mode and listeners

snare snare at ho.ax
Fri Jul 18 04:10:53 PDT 2014


Hi,

I have a question about listeners and async mode. I'm building a debugger UI on top of LLDB in Python, and basically what I want to do is instantiate an SBDebugger, get its SBCommandInterpreter, loop on readline and feed the commands to the command interpreter pretty much the same way that the regular LLDB driver does. I’ve had a look at the driver code, but there’s quite a bit I don’t understand about how the back end works. There is other stuff going on in my tool that I won't go into that necessitates running it this way, rather than as a script loaded into the regular LLDB driver (which is actually how the existing version works).

>From what I understand, the way to do this is to use async mode. I've had a look at the process_events.py example, which makes sense, but I'm not sure how to proceed with regard to listeners when letting SBCommandInterpreter do the heavy lifting rather than calling Launch* with the API.

I was hoping to be able to do something like this:

    import lldb
    import time

    debugger = lldb.SBDebugger.Create()
    debugger.SetAsync(True)
    ci = debugger.GetCommandInterpreter()
    res = lldb.SBCommandReturnObject()

    # "inferior" is a test program that when called with "loop" as the first param just does `while(1);`
    print("starting inferior")
    ci.HandleCommand("file tests/inferior", res)
    ci.HandleCommand("run loop", res)

    # let the target run a bit and then get its status
    print("sleeping 1 second")
    time.sleep(1)
    state = debugger.StateAsCString(debugger.GetTargetAtIndex(0).process.GetState())
    print("state (should be running): {}".format(state))

The state is always "stopped". After looking at `process_events.py` I figured I need to set up a listener and consume the events, so I tried something like this, with a listener running in a background thread (and a more realistic example with accepting user commands rather than the contrived example above):

    import lldb
    import os
    import threading

    debugger = lldb.SBDebugger.Create()
    debugger.SetAsync(True)
    ci = debugger.GetCommandInterpreter()

    done = threading.Event()

    def run_listener():
        event = lldb.SBEvent()
        listener = debugger.GetListener()
        while not done.is_set():
            if listener.WaitForEvent(1, event):
                print("Got a new LLDB event: {}".format(event))
            else:
                # print("Timed out waiting for LLDB event, trying again")
                pass

    t = threading.Thread(target=run_listener)
    t.start()

    try:
        while True:
            line = raw_input("> ")
            res = lldb.SBCommandReturnObject()
            ci.HandleCommand(line, res)
            if res.Succeeded():
                print(res.GetOutput().strip())
            else:
                print(res.GetError().strip())
    except:
        done.set()
        t.join()

But running the listener like that causes HandleCommand() to block. I'm assuming my listener consuming the events means that the debugger never receives them. I do not really require handling the events from my code, I'm happy for the debugger to handle that if it can do so and allow me to still perform other operations asynchronously like inspecting the state/read memory/etc.

Can anybody give me a clue as to how to proceed with this?

Thanks,
Loukas



More information about the lldb-dev mailing list