借助GDB python 模块调试 OpenGauss
OpenGauss是一个单进程多线程的架构,空闲情况下线程已经有几十个了,如何通过线程名快速找到线程id 对线程的调试很有比较。gdb 可以通过python 扩展实现这个功能
环境信息
操作系统centos7.6
安装依赖
sudo yum groupinstall "Development Tools"
sudo yum install python3-devel flex bison ncurses-devel
编译gdb
./configure --prefix /usr/local/gdb13 --with-python=$(which python3)
make &&make install
准备python 代码
import gdb
def find_threads_by_name(name):
# 只执行一次 info thread 命令获取所有线程信息
thread_info = gdb.execute("info thread", to_string=True)
lines = thread_info.split('\n')
found_ids = set()
for line in lines:
if name in line:
parts = line.strip().split()
thread_id = parts[0].replace('*', '').strip() # 去除可能的 * 符号
if thread_id.isdigit() and thread_id not in found_ids:
print(f"Found thread ID: {thread_id} with name: {name}")
found_ids.add(thread_id)
# 定义一个 GDB 命令
class FindThreadsByName(gdb.Command):
def __init__(self):
super(FindThreadsByName, self).__init__("find-threads-by-name", gdb.COMMAND_USER)
def invoke(self, arg, from_tty):
argv = gdb.string_to_argv(arg)
if len(argv) != 1:
print("Usage: find-threads-by-name <thread_name>")
return
find_threads_by_name(argv[0])
# 注册命令
FindThreadsByName()
代码解释
-
find_threads_by_name
函数:- 首先执行
gdb.execute("info thread", to_string=True)
命令获取所有线程信息,将其按行分割。 - 使用
found_ids
集合来记录已经找到的线程 ID,避免重复输出。 - 遍历每一行,若包含指定的线程名称,则提取线程 ID,去除可能存在的
*
符号(表示当前激活的线程),并检查是否为有效的数字且未在found_ids
集合中,若满足条件则输出该线程 ID 并将其添加到集合中。
- 首先执行
-
FindThreadsByName
类:- 继承自
gdb.Command
,定义了find-threads-by-name
命令。 - 在
invoke
方法中,解析命令行参数,若参数数量不为 1,则输出使用说明;若参数数量正确,调用find_threads_by_name
函数进行线程查找。
- 继承自
使用方法
- 将上述代码保存为一个新的 Python 文件,例如
find_threads_optimized.py
。 - 在 GDB 中加载该脚本:
(gdb) source find_threads_optimized.py
- 使用自定义命令查找线程:
(gdb) find-threads-by-name <target_name>