【问题标题】:Catching segfault with debugger in Python在 Python 中使用调试器捕获段错误
【发布时间】:2015-01-23 11:23:23
【问题描述】:

我想调试一个经常卡住的Python程序。

基本上,我的程序运行一个接受 SOAP 请求的 spyne-server。我的程序是多线程的,有时,我用来访问它的客户端会超时。

我已经尝试了几个调试器,例如 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 2.7 操作系统:Ubuntu 12.04 服务器端框架:Spyne(前 SoapLib) 我也在我的程序中使用了 Pyro,这可能是这一切的原因。虽然我已经禁用了 Pyro 上的多线程

【问题讨论】:

    标签: python debugging segmentation-fault gdb


    【解决方案1】:

    您是否尝试过内置的 gdb 模块?我的意思是python -m pdb myscript.py。除此之外,您还可以导入 gdb 并硬编码一些断点。

    【讨论】:

    • 我不确定它应该以这种方式工作。当我运行 python -m gdb myscript.py 时,我在 'gdb.function' 中得到文件“/usr/share/gdb/python/gdb/__init__.py”,第 23 行:os.path.join( gdb.PYTHONDIR, 'gdb', 'function'), NameError: name 'os' 未定义。是的,我会放置一些断点并减少代码,但它很大,这就是我首先使用 degugger 的原因 :)
    • 不应该是python -m pdb myscript.py吗?
    • python -m pdb myscript.py 运行良好,但无法捕获 seqfault ......它只是在一段时间后卡住了,需要 kill -9 才能停止
    【解决方案2】:

    我已经设法通过运行获得更好的回溯

    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
    

    以下帖子帮助很大: http://hustoknow.blogspot.fr/2013/06/why-your-python-program-cant-start-when.html

    现在我只需要了解回溯 :-)

    【讨论】:

      【解决方案3】:

      我使用标准库中的 python 的faulthandler 很难找到致命错误/段错误。它将创建一个回溯(首先是最近调用),显示当 python 进行转储时正在执行哪一行代码。

      例如:

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

      它比标准的 python 回溯更受限制,但至少足以为您指明正确的方向。来自文档:

      • 仅支持 ASCII。反斜杠替换错误处理程序用于编码。

      • 每个字符串限制为 500 个字符。

      • 仅显示文件名、函数名和行号。 (无源代码)

      • 限制为 100 帧和 100 个线程。

      • 顺序颠倒:最近的通话最先显示。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-10-05
        • 1970-01-01
        • 1970-01-01
        • 2010-10-07
        • 1970-01-01
        • 2015-07-10
        • 2012-07-06
        相关资源
        最近更新 更多