【发布时间】:2019-04-05 01:37:02
【问题描述】:
此示例代码无限期挂起:
import asyncio
async def main():
async def f():
await g_task
async def g():
await f_task
f_task = asyncio.create_task(f())
g_task = asyncio.create_task(g())
await f_task
asyncio.run(main())
我正在寻找一种自动检测和处理死锁的方法,就像 GoLang 所做的那样。
到目前为止,我想出了asyncio.wait_for() 的变体:
[编辑] 大修设计
https://gist.github.com/gimperiale/549cbad04c24d870145d3f38fbb8e6f0
原代码1行改动:
await wait_check_deadlock(f_task)
它有效,但有两个主要问题:
- 它依赖于
asyncio.Task._fut_waiter,这是 CPython 的一个实现细节 - 死锁的任务将永远保留在 RAM 中。
aw.cancel()似乎什么都不做。如果我捕获了我的辅助函数引发的 RecursionError,asyncio.run() 在尝试取消所有任务时会引发另一个 RecursionError。
这个问题有更强大的解决方案吗?
【问题讨论】:
-
golang 的旁注——go 程序很可能死锁。我已经做过很多次了,尤其是在单元测试中,它试图覆盖大量使用通道的代码的极端情况。
-
有一个问题,如果这实际上是一个正式的死锁,因为 Python
asyncio和async/await通常支持取消 - 只要引用f_task或g_task可用"外部”,即对于其他一些协同程序,其他代码可以调用f_task.cancel()????。除了目前已损坏:bugs.python.org/issue36456 ???? -
顺便说一句,我想你可以在mail.python.org/mailman/listinfo/async-sig 上发布你的问题
标签: python-asyncio