关于调试:从卡住的python进程中获取堆栈跟踪

Get stacktrace from stuck python process

我必须运行一个传统的Zope2网站,并对它有一些不满。最大的问题是,有时它只是锁定,以100%的CPU负载运行,不再响应请求。虽然这个问题在常规的基础上是不可复制的,但是一个包含3个动态图的页面有时会触发它,所以我怀疑某种竞争条件会导致一个无止境的循环或一个卡住的busywait。

问题是,我还没有找到调试这个东西的方法。Zope日志中没有任何内容,系统日志中也没有任何内容。我尝试了这个问题的建议来获取stacktrace,但是唯一有影响的信号是SIGKILL

是否还有另一种可能性可以确定当流程被卡住时它到底在哪里?


您可以使用pyrasite打印出一个很好的堆栈跟踪。

首先,您需要安装gdb。

1
2
3
4
5
# Redhat, CentOS, etc
$ yum install gdb

# Ubuntu, Debian, etc
$ apt-get update && apt-get install gdb

然后,安装Pyrasite。

1
$ pip install pyrasite

使用ps或其他方法查找被卡住的python进程的进程ID,并用它运行pyrasite-shell

1
2
# Assuming process ID is 12345
$ pyrasite-shell 12345

现在应该看到一个python repl。在repl中运行以下命令,查看所有线程的堆栈跟踪。

1
2
3
4
5
import sys, traceback
for thread_id, frame in sys._current_frames().items():
    print 'Stack for thread {}'.format(thread_id)
    traceback.print_stack(frame)
    print ''

请看我对这个问题的回答,使用products.signalStack。它注册与您在产品注册时找到的答案相同的处理程序。也许它对你更好。

如果没有,您可能手头上有一个操作系统级的I/O问题,您唯一的希望就是将gdb附加到流程中。搜索GDB答案的堆栈溢出;这里有丰富的信息!


您可以尝试将调试程序附加到正在运行的进程。另请参见此问题。


在互联网上转了一圈之后,我终于在这里结束了:http://podoliaka.org/2016/04/10/debugging-cpython-gdb/-详细描述了所有部件是如何组合在一起的。我的货币报价是'gdb/usr/bin/python-p$pid'-需要可执行文件的名称,以便gdb找到正确的调试信息文件。


如果进程被卡在其他信号无法通过的方式中,您可能需要考虑从调试器运行它,而不是在运行时尝试附加到它。

此外,它可能对其他调试策略很有用,例如关闭代码的某些部分,以找出它仍然可以复制的最小情况,以查看是什么使它更好。