转储所有活动线程的堆栈跟踪

发布于 2024-07-24 16:27:47 字数 356 浏览 2 评论 0原文

我正在尝试转储所有活动线程的列表,包括每个线程的当前堆栈。 我可以使用 threading.enumerate() 获取所有线程的列表,但我无法找到从那里访问堆栈的方法。

背景:Zope/Plone 应用程序有时会崩溃,消耗 100% 的 cpu,需要重新启动。 我有一种感觉,这是一个无法正确终止的循环,但我无法在测试环境中重现它以进行验证。 我设法注册了一个可以从外部触发的信号处理程序,这样我就可以在这种情况再次发生时触发一些代码。 如果我可以转储所有活动线程的堆栈跟踪,那就可以告诉我出了什么问题。 这个洞在 python 2.4 上运行...

任何有关如何追踪此类情况的想法都值得赞赏:)

干杯, 克里斯

I'm trying to dump a list of all active threads including the current stack of each. I can get a list of all threads using threading.enumerate(), but i can't figure out a way to get to the stack from there.

Background: A Zope/Plone app freaks out from time to time, consuming 100% of cpu and needs to be restarted. I have a feeling it's a loop which doesn't terminate properly, but i cannot reproduce it in the test-environemt for verification. I managed to register a signal handler which can be triggered from the outside, so i can trigger some code as soon as the situation occurs again. If I could dump the stacktrace for all active threads, that would give me a clue what goes wrong. The hole thing runs on python 2.4...

Any ideas on how to trace down situations like these are appreciated :)

Cheers,
Chriss

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

还给你自由 2024-07-31 16:27:47

正如 jitter 在之前的回答中指出的那样,sys._current_frames() 为您提供了 v2.5+ 所需的内容。 对于懒惰的人来说,以下代码片段对我有用,可能会对您有所帮助:

print >> sys.stderr, "\n*** STACKTRACE - START ***\n"
code = []
for threadId, stack in sys._current_frames().items():
    code.append("\n# ThreadID: %s" % threadId)
    for filename, lineno, name, line in traceback.extract_stack(stack):
        code.append('File: "%s", line %d, in %s' % (filename,
                                                    lineno, name))
        if line:
            code.append("  %s" % (line.strip()))

for line in code:
    print >> sys.stderr, line
print >> sys.stderr, "\n*** STACKTRACE - END ***\n"

As jitter points out in an earlier answer sys._current_frames() gives you what you need for v2.5+. For the lazy the following code snippet worked for me and may help you:

print >> sys.stderr, "\n*** STACKTRACE - START ***\n"
code = []
for threadId, stack in sys._current_frames().items():
    code.append("\n# ThreadID: %s" % threadId)
    for filename, lineno, name, line in traceback.extract_stack(stack):
        code.append('File: "%s", line %d, in %s' % (filename,
                                                    lineno, name))
        if line:
            code.append("  %s" % (line.strip()))

for line in code:
    print >> sys.stderr, line
print >> sys.stderr, "\n*** STACKTRACE - END ***\n"
内心荒芜 2024-07-31 16:27:47

对于 Python 3.3 及更高版本,有 faulthandler.dump_traceback( )

下面的代码产生类似的输出,但包含线程名称,并且可以增强以打印更多信息。

for th in threading.enumerate():
    print(th)
    traceback.print_stack(sys._current_frames()[th.ident])
    print()

For Python 3.3 and later, there is faulthandler.dump_traceback().

The code below produces similar output, but includes the thread name and could be enhanced to print more information.

for th in threading.enumerate():
    print(th)
    traceback.print_stack(sys._current_frames()[th.ident])
    print()
紫罗兰の梦幻 2024-07-31 16:27:47

使用 Zope 时,您需要安装 Products.signalstackmr.freeze; 这些就是为了这个目的而设计的!

向您的 Zope 服务器发送 USR1 信号,它会立即将所有线程的堆栈跟踪转储到控制台。 即使所有 Zope 线程都被锁定,它也会这样做。

在底层,这些包间接使用 threadframes; 对于 Python 2.5 及更高版本,当使用 Zope 时,您可以使用 sys._current_frames() 函数来访问每个线程的堆栈帧。

Zope 2.12.5 开始,此功能已集成到 Zope 本身中,并且没有需要再安装额外的软件包了。

When using Zope, you want to install Products.signalstack or mr.freeze; these were designed for just this purpose!

Send a USR1 signal to your Zope server and it'll immediately dump stack traces for all threads to the console. It'll do this even if all Zope threads are locked up.

Under the hood these packages indirectly use threadframes; for Python versions 2.5 and up, when not using Zope, you can build the same functionality using the sys._current_frames() function to access per-thread stack frames.

As of Zope 2.12.5 this functionality is integrated into Zope itself, and there is no need to install additional packages anymore.

故乡的云 2024-07-31 16:27:47

2.4. 太糟糕了。 从 Python 2.5 开始,有 sys._current_frames()

但你可以尝试threadframe。 如果 makefile 给您带来麻烦,您可以尝试这个 setup.py对于 threadframe

使用 threadframe 时的示例输出

2.4. Too bad. From Python 2.5 on there is sys._current_frames().

But you could try threadframe. And if the makefile gives you trouble you could try this setup.py for threadframe

Sample output when using threadframe

浅忆流年 2024-07-31 16:27:47

只是为了完整起见, Products.LongRequestLogger 对于识别瓶颈非常有帮助,并这样做它以特定的时间间隔转储堆栈跟踪。

Just for completeness sake, Products.LongRequestLogger is super helpful to identify bottlenecks, and to do so it dumps stacktraces at specific intervals.

帅气称霸 2024-07-31 16:27:47

ASPN 上有一个适用的食谱。 您可以使用threading.enumerate()来获取所有tids,然后只需调用_async_raise()并使用一些合适的异常来强制进行堆栈跟踪。

There is an applicable recipe on ASPN. You can use threading.enumerate() to get all the tids, then just call _async_raise() with some suitable exception to force a stack trace.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文