Catching segfault with debugger in Python

余生颓废 提交于 2019-12-07 04:40:59

问题


I want to debug a Python program which is often stuck.

Basically, my program runs a spyne-server which accepts SOAP requests. My program is multi-threaded and sometimes, the client I use to reach it timeouts.

I've tryed severals debuggers such as PUDB, PDB, WINPDB, PYSTUCK but I wasn't able to catch any exception from them, in fact they happen to be stuck too (CTRL+C doesnt work...)

The best I've achieved was from GDB with the following command:

 gdb -ex r --args python myscript.py

GDB manages to catch the exception but doesn't display any usefull informations:

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

I've installed the package python2.7-dbg to enable the command "py-bt" but it is not more usefull:

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

I've read somewhere that it's because Python doesn't have the debug symbols then I've tryed the following

 gdb -ex r --args python-dbg myscript.py

But it's doesn't work either, I cant even run the program, I have several errors:

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

I'm running out of options....

Details about my program: Python: Python 2.7 OS: Ubuntu 12.04 Server-Side Framework : Spyne (ex SoapLib) I also use Pyro on my program which may be the cause of all this. I have disabled the Multithreading on Pyro though


回答1:


Have you tried the built-in gdb module? I mean python -m pdb myscript.py. On top of that you can import gdb and hardcode some breakpoints.




回答2:


I've managed to get a better backtrace by running

gdb -ex r --args python-dbg myscript.py

I've resolved the symbol issues (cf above) by recompiling the package lxml with python-dbg. I had some troubles doing that but it finally worked following the steps:

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

The following post helped a lot: http://hustoknow.blogspot.fr/2013/06/why-your-python-program-cant-start-when.html

Now I just have to understand the backtrace :-)




回答3:


I've tracked down hard to find fatal errors/segfaults using python's faulthandler from the standard library. It will create a traceback (recent call first) showing which line of code was being executed when python takes a dump.

ex:

import faulthandler


with open("fault_handler.log", "w") as fobj:
    faulthandler.enable(fobj)
    your_function_to_debug()

It's somewhat more limited than standard python tracebacks, but it's more than sufficient to at least point you in the right direction. From the docs:

  • 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.



来源:https://stackoverflow.com/questions/28108851/catching-segfault-with-debugger-in-python

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!