在 Python 中使用调试器捕获段错误
Catching segfault with debugger in Python
我想调试一个经常卡死的Python程序
基本上,我的程序 运行 是一个接受 SOAP 请求的 spyne 服务器。我的程序是多线程的,有时我用来访问它的客户端会超时。
我已经尝试了几个调试器,如 PUDB、PDB、WINPDB、PYSTUCK,但我无法从它们中捕获任何异常,事实上它们也恰好被卡住了(CTRL+C 不起作用... )
我取得的最好成绩是使用以下命令从 GDB 获得的:
gdb -ex r --args python myscript.py
GDB 设法捕获了异常,但没有显示任何有用的信息:
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7fffd7fff700 (LWP 22573)]
0x000000000057656d in PyEval_EvalCodeEx ()
(gdb) info threads
Id Target Id Frame
* 15 Thread 0x7fffd7fff700 (LWP 22573) "python" 0x000000000057656d in PyEval_EvalCodeEx ()
7 Thread 0x7fffecc2c700 (LWP 22277) "python" 0x00007ffff6998653 in select () at ../sysdeps/unix/syscall-template.S:82
6 Thread 0x7fffed42d700 (LWP 22276) "python" 0x00007ffff6998653 in select () at ../sysdeps/unix/syscall-template.S:82
5 Thread 0x7fffedc2e700 (LWP 22271) "python" sem_wait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S:86
4 Thread 0x7fffee42f700 (LWP 22270) "python" sem_wait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S:86
3 Thread 0x7fffef9e8700 (LWP 22261) "python" 0x00007ffff6993933 in __GI___poll (fds=<optimized out>, nfds=<optimized out>,
timeout=<optimized out>) at ../sysdeps/unix/sysv/linux/poll.c:87
2 Thread 0x7ffff613f700 (LWP 21988) "python" 0x00007ffff7bcc04d in accept () at ../sysdeps/unix/syscall-template.S:82
1 Thread 0x7ffff7fd6700 (LWP 20970) "python" 0x00007ffff6998653 in select () at ../sysdeps/unix/syscall-template.S:82
(gdb) bt
#0 0x000000000057656d in PyEval_EvalCodeEx ()
#1 0x0000000000577ab0 in function_call.15039 ()
#2 0x00000000004d91b6 in PyObject_Call ()
#3 0x000000000054d8a5 in PyEval_EvalFrameEx ()
#4 0x000000000054c272 in PyEval_EvalFrameEx ()
#5 0x000000000054c272 in PyEval_EvalFrameEx ()
#6 0x000000000054c272 in PyEval_EvalFrameEx ()
#7 0x000000000054c272 in PyEval_EvalFrameEx ()
#8 0x000000000054c272 in PyEval_EvalFrameEx ()
我已经安装了软件包 python2.7-dbg 来启用命令 "py-bt" 但它不是更有用:
(gdb) py-bt
#7 (unable to read python frame information)
#8 (unable to read python frame information)
#16 (unable to read python frame information)
#17 (unable to read python frame information)
#18 (unable to read python frame information)
#27 (unable to read python frame information)
#28 (unable to read python frame information)
#32 (unable to read python frame information)
#33 (unable to read python frame information)
#34 (unable to read python frame information)
我在某处读到这是因为 Python 没有调试符号然后我尝试了以下
gdb -ex r --args python-dbg myscript.py
但它也不起作用,我什至无法 运行 程序,我有几个错误:
ImportError: /usr/lib/python2.7/dist-packages/lxml/etree.so: undefined symbol: Py_InitModule4_64
ImportError: /usr/lib/python2.7/dist-packages/apt_pkg.so: undefined symbol: Py_InitModule4_64
我运行别无选择....
关于我的程序的详细信息:
Python: Python 2.7
OS: Ubuntu 12.04
服务器端框架:Spyne(前 SoapLib)
我还在我的程序中使用了 Pyro,这可能是造成这一切的原因。不过我已经在 Pyro 上禁用了多线程
你试过内置的gdb模块吗?我的意思是 python -m pdb myscript.py
。最重要的是,您可以导入 gdb 并对一些断点进行硬编码。
我已经通过 运行
获得了更好的回溯
gdb -ex r --args python-dbg myscript.py
我已经通过使用 python-dbg 重新编译包 lxml 解决了符号问题(参见上文)。我在这样做时遇到了一些麻烦,但它最终按照以下步骤工作:
pip install lxml --download-cache myDir
# for newer pip, use : pip install lxml --download myDir --no-use-wheel
cd myDir
tar -xvf lxml-4.2.1.tar.gz
cd lxml-4.2.1
sudo apt-get install libxslt-dev
sudo apt-get install gcc
sudo apt-get install python-dev
sudo apt-get install python-dbg
sudo python-dbg setup.py install
以下post帮助很大:
http://hustoknow.blogspot.fr/2013/06/why-your-python-program-cant-start-when.html
现在我只需要了解回溯:-)
我使用标准库中的 python 的 faulthandler 很难找到致命的 errors/segfaults。它将创建一个回溯(最近调用优先)显示当 python 进行转储时正在执行的代码行。
例如:
import faulthandler
with open("fault_handler.log", "w") as fobj:
faulthandler.enable(fobj)
your_function_to_debug()
它比标准的 python 回溯更受限制,但至少可以为您指明正确的方向。来自文档:
Only ASCII is supported. The backslashreplace error handler is used on encoding.
Each string is limited to 500 characters.
Only the filename, the function name and the line number are displayed. (no source code)
It is limited to 100 frames and 100 threads.
The order is reversed: the most recent call is shown first.
我想调试一个经常卡死的Python程序
基本上,我的程序 运行 是一个接受 SOAP 请求的 spyne 服务器。我的程序是多线程的,有时我用来访问它的客户端会超时。
我已经尝试了几个调试器,如 PUDB、PDB、WINPDB、PYSTUCK,但我无法从它们中捕获任何异常,事实上它们也恰好被卡住了(CTRL+C 不起作用... )
我取得的最好成绩是使用以下命令从 GDB 获得的:
gdb -ex r --args python myscript.py
GDB 设法捕获了异常,但没有显示任何有用的信息:
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7fffd7fff700 (LWP 22573)]
0x000000000057656d in PyEval_EvalCodeEx ()
(gdb) info threads
Id Target Id Frame
* 15 Thread 0x7fffd7fff700 (LWP 22573) "python" 0x000000000057656d in PyEval_EvalCodeEx ()
7 Thread 0x7fffecc2c700 (LWP 22277) "python" 0x00007ffff6998653 in select () at ../sysdeps/unix/syscall-template.S:82
6 Thread 0x7fffed42d700 (LWP 22276) "python" 0x00007ffff6998653 in select () at ../sysdeps/unix/syscall-template.S:82
5 Thread 0x7fffedc2e700 (LWP 22271) "python" sem_wait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S:86
4 Thread 0x7fffee42f700 (LWP 22270) "python" sem_wait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S:86
3 Thread 0x7fffef9e8700 (LWP 22261) "python" 0x00007ffff6993933 in __GI___poll (fds=<optimized out>, nfds=<optimized out>,
timeout=<optimized out>) at ../sysdeps/unix/sysv/linux/poll.c:87
2 Thread 0x7ffff613f700 (LWP 21988) "python" 0x00007ffff7bcc04d in accept () at ../sysdeps/unix/syscall-template.S:82
1 Thread 0x7ffff7fd6700 (LWP 20970) "python" 0x00007ffff6998653 in select () at ../sysdeps/unix/syscall-template.S:82
(gdb) bt
#0 0x000000000057656d in PyEval_EvalCodeEx ()
#1 0x0000000000577ab0 in function_call.15039 ()
#2 0x00000000004d91b6 in PyObject_Call ()
#3 0x000000000054d8a5 in PyEval_EvalFrameEx ()
#4 0x000000000054c272 in PyEval_EvalFrameEx ()
#5 0x000000000054c272 in PyEval_EvalFrameEx ()
#6 0x000000000054c272 in PyEval_EvalFrameEx ()
#7 0x000000000054c272 in PyEval_EvalFrameEx ()
#8 0x000000000054c272 in PyEval_EvalFrameEx ()
我已经安装了软件包 python2.7-dbg 来启用命令 "py-bt" 但它不是更有用:
(gdb) py-bt
#7 (unable to read python frame information)
#8 (unable to read python frame information)
#16 (unable to read python frame information)
#17 (unable to read python frame information)
#18 (unable to read python frame information)
#27 (unable to read python frame information)
#28 (unable to read python frame information)
#32 (unable to read python frame information)
#33 (unable to read python frame information)
#34 (unable to read python frame information)
我在某处读到这是因为 Python 没有调试符号然后我尝试了以下
gdb -ex r --args python-dbg myscript.py
但它也不起作用,我什至无法 运行 程序,我有几个错误:
ImportError: /usr/lib/python2.7/dist-packages/lxml/etree.so: undefined symbol: Py_InitModule4_64
ImportError: /usr/lib/python2.7/dist-packages/apt_pkg.so: undefined symbol: Py_InitModule4_64
我运行别无选择....
关于我的程序的详细信息: Python: Python 2.7 OS: Ubuntu 12.04 服务器端框架:Spyne(前 SoapLib) 我还在我的程序中使用了 Pyro,这可能是造成这一切的原因。不过我已经在 Pyro 上禁用了多线程
你试过内置的gdb模块吗?我的意思是 python -m pdb myscript.py
。最重要的是,您可以导入 gdb 并对一些断点进行硬编码。
我已经通过 运行
获得了更好的回溯gdb -ex r --args python-dbg myscript.py
我已经通过使用 python-dbg 重新编译包 lxml 解决了符号问题(参见上文)。我在这样做时遇到了一些麻烦,但它最终按照以下步骤工作:
pip install lxml --download-cache myDir
# for newer pip, use : pip install lxml --download myDir --no-use-wheel
cd myDir
tar -xvf lxml-4.2.1.tar.gz
cd lxml-4.2.1
sudo apt-get install libxslt-dev
sudo apt-get install gcc
sudo apt-get install python-dev
sudo apt-get install python-dbg
sudo python-dbg setup.py install
以下post帮助很大: http://hustoknow.blogspot.fr/2013/06/why-your-python-program-cant-start-when.html
现在我只需要了解回溯:-)
我使用标准库中的 python 的 faulthandler 很难找到致命的 errors/segfaults。它将创建一个回溯(最近调用优先)显示当 python 进行转储时正在执行的代码行。
例如:
import faulthandler
with open("fault_handler.log", "w") as fobj:
faulthandler.enable(fobj)
your_function_to_debug()
它比标准的 python 回溯更受限制,但至少可以为您指明正确的方向。来自文档:
Only ASCII is supported. The backslashreplace error handler is used on encoding.
Each string is limited to 500 characters.
Only the filename, the function name and the line number are displayed. (no source code)
It is limited to 100 frames and 100 threads.
The order is reversed: the most recent call is shown first.