Ошибка python-gdb: python exception <class 'runtimeerror'> тип не имеет цели

Я запускаю python 3.6.6-debug (установлен через pyenv), и я скопировал связанный libpython.py с cpython/Tools/gdb/libpython.py на ~/.config/gdb (с отмеченным тегом v3.6.6).

В моем .gdbinit у меня есть:

source ~/.config/gdb/libpython.py

Для простых процессов я могу использовать py-list, py-bt и т. д. Без проблем, но программа, которую я сейчас тестирую под py.test, дает мне эту ошибку для любой вспомогательной команды python gdb:

(gdb) py-list
Python Exception <class 'RuntimeError'> Type does not have a target.:
Error occurred in Python command: Type does not have a target.

Что означает эта ошибка и как ее исправить?

Обновлять

Я покопался в libpython.py, чтобы точно увидеть, как py-list / py-bt делают свое дело, а затем вручную запустил связанные команды gdb python изнутри gdb, чтобы воспроизвести проблему и точно определить, где именно в 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.

Проблема возникает в строке libpython.py 1158, которая

fields = gdb.lookup_type('PyUnicodeObject').target().fields()

Это проясняет ситуацию: libpython.py получает объект Type для PyUnicodeObject, а затем пытается вызвать для него метод target, но объект Type для PyUnicodeObject не имеет цели. Согласно документация gdb:

— Function: Type.target ()

Return a new gdb.Type object which represents the target type of this type.

For a pointer type, the target type is the type of the pointed-to object. For an array type (meaning C-like arrays), the target type is the type of the elements of the array. For a function or method type, the target type is the type of the return value. For a complex type, the target type is the type of the elements. For a typedef, the target type is the aliased type.

If the type does not have a target, this method will throw an exception.

Это определенно похоже на ошибку, хотя я не могу найти упоминания об этой проблеме где-либо еще в Интернете, в системе отслеживания проблем Python или в истории фиксации Python. Я собираюсь открыть проблему в трекере Python и посмотреть, что говорят разработчики (если только кто-то не сталкивался с этим раньше и не отправил ответ).

Как я отлаживал

Настройте ptrace, чтобы разрешить отладку без sudo

$ sudo sh -c 'echo 0 > /proc/sys/kernel/yama/ptrace_scope

Определите родительский процесс 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)

(Я просто догадался, что использование pid любого из запущенных процессов python для моей программы сработало бы)

Присоединиться к родительскому процессу

$ gdb -p 22391

Определите самый последний кадр выполнения 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.

Добавьте исходные каталоги Python и используйте tui enable, чтобы получить некоторый контекст

(gdb) dir ~/git/cpython
Source directories searched: /home/calid/git/cpython:$cdir:$cwd
(gdb) tui enable

gdb tui screenshot

Запустите интерактивный интерпретатор python gdb и вручную введите строки 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.

Это воспроизвело исключение, которое я наблюдал с py-list и py-bt, но на этот раз я также получил очень полезную обратную связь с ним.

Включите трассировку стека gdb python по умолчанию

set python print-stack full

После всего этого я наткнулся на документация для варианта выше. Настройка, которая включает печать трассировки стека по умолчанию и позволила бы избежать необходимости выполнять всю эту ручную отладку ... Итак, оглядываясь назад, я проделал много дополнительной работы, которую мне не нужно было делать :) (хотя я действительно многому научился в процессе).

Я добавил это в свой gdbinit на будущее.

Ресурсы

7
0
2 165
1

Ответы 1

Я столкнулся с той же проблемой, попробовал и просто изменил строку

fields = gdb.lookup_type('PyUnicodeObject').target().fields()

к

fields = gdb.lookup_type('PyUnicodeObject').fields()

Тогда это работает.

Работает на GDB 8.2.1 / Ubuntu 16.04. Python3.6, /usr/share/gdb/auto-load/usr/bin/python3.6-gdb.py

skytree 26.03.2019 16:29

Другие вопросы по теме