数据库的路上

借助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()

代码解释

  1. find_threads_by_name 函数

    • 首先执行 gdb.execute("info thread", to_string=True) 命令获取所有线程信息,将其按行分割。
    • 使用 found_ids 集合来记录已经找到的线程 ID,避免重复输出。
    • 遍历每一行,若包含指定的线程名称,则提取线程 ID,去除可能存在的 * 符号(表示当前激活的线程),并检查是否为有效的数字且未在 found_ids 集合中,若满足条件则输出该线程 ID 并将其添加到集合中。
  2. FindThreadsByName

    • 继承自 gdb.Command,定义了 find-threads-by-name 命令。
    • invoke 方法中,解析命令行参数,若参数数量不为 1,则输出使用说明;若参数数量正确,调用 find_threads_by_name 函数进行线程查找。

使用方法

  1. 将上述代码保存为一个新的 Python 文件,例如 find_threads_optimized.py
  2. 在 GDB 中加载该脚本:
(gdb) source find_threads_optimized.py
  1. 使用自定义命令查找线程:
(gdb) find-threads-by-name <target_name>