I am scripting GDB with Python 2.7.
I am simply stepping instructions with gdb.execute("stepi")
. If the debugged program is idling and waiting for user interaction, gdb.execute("stepi")
doesn't return. If there is such a situation, I want to stop the debugging session without terminating gdb.
To do so, I create a thread that will kill the debugged process if the current instruction ran for more than x seconds:
from ctypes import c_ulonglong, c_bool
from os import kill
from threading import Thread
from time import sleep
import signal
# We need mutable primitives in order to update them in the thread
it = c_ulonglong(0) # Instructions counter
program_exited = c_bool(False)
t = Thread(target=check_for_idle, args=(pid,it,program_exited))
t.start()
while not program_exited.value:
gdb.execute("si") # Step instruction
it.value += 1
# Threaded function that will kill the loaded program if it's idling
def check_for_idle(pid, it, program_exited):
delta_max = 0.1 # Max delay between 2 instructions, seconds
while not program_exited.value:
it_prev = c_ulonglong(it.value) # Previous value of instructions counter
sleep(delta_max)
# If previous instruction lasted for more than 'delta_max', kill debugged process
if (it_prev.value == it.value):
# Process pid has been retrieved before
kill(pid, signal.SIGTERM)
program_exited.value = True
print("idle_process_end")
However, gdb.execute
is pausing my thread... Is there another way to kill the debugged process if it is idling?
Use the "info threads" command to see the IDs of currently known threads. The GDB thread debugging facility allows you to observe all threads while your program runs--but whenever GDB takes control, one thread in particular is always the focus of debugging. This thread is called the current thread.
To display the backtrace for several or all of the threads, use the command thread apply (see thread apply). For example, if you type thread apply all backtrace , gdb will display the backtrace for all the threads; this is handy when you debug a core dump of a multi-threaded program.
Explanation. GDB embeds the Python interpreter so it can use Python as an extension language. You can't just import gdb from /usr/bin/python like it's an ordinary Python library because GDB isn't structured as a library. What you can do is source MY-SCRIPT.py from within gdb (equivalent to running gdb -x MY-SCRIPT.py ) ...
However, gdb.execute is pausing my thread
What is happening here is that gdb.execute
does not release Python's global lock when calling into gdb. So, while the gdb command executes, other Python threads are stuck.
This is just an oversight in gdb. I've filed a bug for it.
Is there another way to kill the debugged process if it is idling?
There is one other technique you can try -- I am not certain it will work. Unfortunately this part of gdb is not fully fleshed out (at the present moment); so also feel free to file bug reports.
The main idea is to run gdb commands on the main thread -- but not from Python. So, try writing your stepping loop using the gdb CLI, maybe like:
(gdb) while 1
> stepi
> end
Then your thread should be able to kill
the inferior. Another approach might be for your thread to inject a gdb command into the main loop using gdb.post_event
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With