Little background
After spending a good amount of time, here's a summary:
The initial bug, being that the GIL does not get released when executing GDB command, was actually fixed in 2014. 1 2
That should have allowed to do something like
gdb.execute("continue")
# Do some processing in the main thread
gdb.execute("interrupt")
However, a few years later, a series of bugs due to a too early release of the GIL were undiscovered, and so other patches were added, which again removed the ability to do so. here's one of them
Also, a Threading module module was added, which can thus execute things in GDB's context, while the GIL is still locked.
In 2023, gdb.interrupt was added. You can find the docs in the Threading module also (not detected by intellisense on my machine, but it does work)
It helps in that it only interrupts if the target is actually running, and sends a Ctrl-C if needed. If you don't want your script to be interrupted by it, you have to catch the exception. I personnally handle it like that:
def halt(self):
try:
gdb.interrupt()
except KeyboardInterrupt:
pass
Current Situation
If you need to programmatically interrupt GDB, @Chris Moore's Answer remains the best one.
def run_and_stop():
gdb.post_event(lambda: gdb.interrupt())
gdb.execute("continue")
I personnally use it like that:
def main():
while True:
backtrace = gdb.execute("backtrace")
def do_async():
process_backtrace(backtrace)
halt()
gdb.post_event(do_async)
gdb.execute("resume")
A few more notes
I could not manage to manage to make gdb.execute("continue &") to work.
For some reason, executing interrupt when already halted, then continue immediately halted upon resume, like if it had been without the need to run interrupt again. In my case I wanted to make sure it ran for at least a few milliseconds between each run, so I could not use that.
Halting repeatedly like this is extremely innefficient, with pyOCD, I can get 2 fps, and with OpenOCD I can get 4.
You may be tempted to use monitor resume and monitor halt instead. Not that you'll then have to use maintenance clear register-cache, and that you'll often still end up with broken stacktraces. Why? Good question.
My Atmel-ICE crashes after a few minutes when I do that repeatedly. Not sure why. It seems to be less frequent when I stop with PyOCD instead of OpenOCD. Is it juste because of the speed?