Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

gdb.execute blocks all the threads in python scripts

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?

like image 388
Antoine C. Avatar asked Aug 30 '18 13:08

Antoine C.


People also ask

How do I see all threads in GDB?

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.

How do I check bt of all threads?

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.

How do I import GDB into Python?

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 ) ...


1 Answers

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.

like image 93
Tom Tromey Avatar answered Oct 17 '22 15:10

Tom Tromey