Dyl*_*ali 7 python debugging gdb python-3.x gdb-python
我正在运行 python 3.6.6-debug(通过 pyenv 安装)并且我已经将关联的 libpython.py 从cpython/Tools/gdb/libpython.pyto复制了~/.config/gdb(签出 v3.6.6 标签)。
在我的 .gdbinit 我有:
source ~/.config/gdb/libpython.py
Run Code Online (Sandbox Code Playgroud)
对于简单的过程,我可以毫无问题地使用py-list,py-bt等,但是我目前正在 py.test 下测试的程序为我提供了任何 python gdb helper 命令的错误:
(gdb) py-list
Python Exception <class 'RuntimeError'> Type does not have a target.:
Error occurred in Python command: Type does not have a target.
Run Code Online (Sandbox Code Playgroud)
这个错误是什么意思,我该如何解决?
我深入研究 libpython.py 以确切了解如何py-list/py-bt做他们的事情,然后从 gdb 中手动运行相关的 gdb python 命令以重现问题并准确隔离 libpython.py 中出现问题的位置。在进行下面的调试后,我能够在 gdb 中获得更详细的回溯:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "~/git/cpython/Tools/gdb/libpython.py", line 916, in filename
File "~/git/cpython/Tools/gdb/libpython.py", line 1158, in proxyval
RuntimeError: Type does not have a target.
Run Code Online (Sandbox Code Playgroud)
问题在 libpython.py 行1158处触发,即
fields = gdb.lookup_type('PyUnicodeObject').target().fields()
Run Code Online (Sandbox Code Playgroud)
这澄清了一些事情:libpython.py 获取 PyUnicodeObject 的 Type 对象,然后尝试调用其target上的方法,但 PyUnicodeObject 的 Type 对象没有 target。根据gdb 文档:
— 功能:Type.target()
返回一个新的 gdb.Type 对象,表示该类型的目标类型。
对于指针类型,目标类型是指向对象的类型。对于数组类型(即类 C 数组),目标类型是数组元素的类型。对于函数或方法类型,目标类型是返回值的类型。对于复杂类型,目标类型是元素的类型。对于 typedef,目标类型是别名类型。
如果类型没有目标,则此方法将引发异常。
这绝对看起来像一个错误,尽管我在网上、python 问题跟踪器或 python 提交历史记录中找不到任何提到这个问题的地方。我将在 python 跟踪器上打开一个问题,看看维护者怎么说(除非有人之前遇到过这个问题并提交了答案)。
配置ptrace为允许在没有 sudo 的情况下进行调试
$ sudo sh -c 'echo 0 > /proc/sys/kernel/yama/ptrace_scope
Run Code Online (Sandbox Code Playgroud)
确定挂起(多处理)程序的父python进程
$ pstree -p -s 22391
systemd(1)???tmux(31719)???bash(5161)???py.test(22391)???py.test(22478)
??py.test(24577)
??py.test(24578)
??python3.6(25427)
??python3.6(25545)
??python3.6(25546)
??python3.6(25547)
??python3.6(27376)???{python3.6}(27393)
??python3.6(30563)???{python3.6}(30580)
??{py.test}(27368)
??{py.test}(30562)
??{py.test}(629)
??{py.test}(630)
Run Code Online (Sandbox Code Playgroud)
(我只是在上面猜对了,对我的程序使用任何正在运行的 python 进程的 pid 都可以)
附加到父进程
$ gdb -p 22391
Run Code Online (Sandbox Code Playgroud)
确定最近的python执行帧并切换到它
(gdb) bt 10
#0 0x00007fec7309a5d3 in select () at ../sysdeps/unix/syscall-template.S:84
#1 0x00007fec738692aa in pysleep (secs=50000000) at ./Modules/timemodule.c:1417
#2 0x00007fec738671a3 in time_sleep (self=0x7fec71a00458, obj=0x7fec6cf728b0) at ./Modules/timemodule.c:235
#3 0x00007fec7368513e in _PyCFunction_FastCallDict (func_obj=0x7fec719ff5f8, args=0x7fec406fac08, nargs=1, kwargs=0x0) at Objects/methodobject.c:209
#4 0x00007fec73685535 in _PyCFunction_FastCallKeywords (func=0x7fec719ff5f8, stack=0x7fec406fac08, nargs=1, kwnames=0x0) at Objects/methodobject.c:294
#5 0x00007fec7379ab0d in call_function (pp_stack=0x7ffc37032440, oparg=1, kwnames=0x0) at Python/ceval.c:4830
#6 0x00007fec737927ca in _PyEval_EvalFrameDefault (f=0x7fec406faa58, throwflag=0) at Python/ceval.c:3328
===> #7 0x00007fec7377eb3b in PyEval_EvalFrameEx (f=0x7fec406faa58, throwflag=0) at Python/ceval.c:754
#8 0x00007fec7363a208 in gen_send_ex (gen=0x7fec3d0b88d8, arg=0x0, exc=0, closing=0) at Objects/genobject.c:189
#9 0x00007fec7363bca6 in gen_iternext (gen=0x7fec3d0b88d8) at Objects/genobject.c:563
(More stack frames follow...)
(gdb) frame 7
#7 0x00007fec7377eb3b in PyEval_EvalFrameEx (f=0x7fec406faa58, throwflag=0) at Python/ceval.c:754
754 Python/ceval.c: No such file or directory.
Run Code Online (Sandbox Code Playgroud)
添加 python 源目录并用于tui enable获取一些上下文
(gdb) dir ~/git/cpython
Source directories searched: /home/calid/git/cpython:$cdir:$cwd
(gdb) tui enable
Run Code Online (Sandbox Code Playgroud)
启动gdb的交互式python解释器,手动输入libpython行,获取当前python脚本/行号
(gdb) pi
>>> gdbframe = gdb.selected_frame()
>>> f = gdbframe.read_var('f')
>>> pyframe = PyFrameObjectPtr.from_pyobject_ptr(f)
>>> pyframe.filename()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "~/git/cpython/Tools/gdb/libpython.py", line 916, in filename
File "~/git/cpython/Tools/gdb/libpython.py", line 1158, in proxyval
RuntimeError: Type does not have a target.
Run Code Online (Sandbox Code Playgroud)
这重现了我用py-listand看到的异常py-bt,但这次我也得到了一个非常有用的回溯。
默认情况下打开 gdb python 堆栈跟踪
set python print-stack full
毕竟,我偶然发现了上述选项的文档。设置默认情况下打开堆栈跟踪打印,并避免需要进行所有手动调试......所以事后看来我做了很多我不需要做的额外工作:)(虽然我确实学到了很多正在进行中)。
我现在已经将它添加到我的 gdbinit 以备将来使用。
小智 11
我遇到了同样的问题,尝试并简单地改变了线路
fields = gdb.lookup_type('PyUnicodeObject').target().fields()
到
fields = gdb.lookup_type('PyUnicodeObject').fields()
然后它起作用了。
| 归档时间: |
|
| 查看次数: |
2068 次 |
| 最近记录: |