【发布时间】:2020-10-09 14:41:21
【问题描述】:
在这个问题上我一直在扯头发
有问题的代码是此处开源项目的一部分:aiosmtpd(我的实际 FOSS 项目的分支,here)
有问题的文件是这个:main.py
出现问题的代码在line 139 of main.py
这是一个sn-p:
...
from aiosmtpd.smtp import DATA_SIZE_DEFAULT, SMTP, __version__
...
...
# args is the result of ArgumentParser.parse_args
factory = partial(
SMTP, args.handler,
data_size_limit=args.size, enable_SMTPUTF8=args.smtputf8)
...
server = loop.run_until_complete(
loop.create_server(factory, host=args.host, port=args.port))
...
有时——也就是说,并非总是——代码在那个时候失败,RuntimeError: Event loop stopped before Future completed.
我的问题:
-
此间歇性失败的原因可能是什么?
在测试过程中有 10% 的时间失败了(使用 tox + nosetest2),但 90% 的时间顺利进行。
-
我应该如何检测和/或检查和/或断言以防止这种情况发生?
-
“恢复”错误并重做操作的最佳策略是什么?
我将第 n 次强调 错误是间歇性发生的。很少,但经常足够让我觉得有必要追查根本原因。在出现错误后,如果我再次重新运行代码——立即或延迟后——几乎总是不会发生相同的错误。
【问题讨论】:
-
在代码库的某处寻找对
loop.stop()的调用。您可能想要删除它们,因为它们与run_until_complete以及更现代的asyncio.run根本不兼容。 -
@user4815162342 不,在这两条有问题的行中没有
loop.stop()。factory是一个简单的partial环绕另一个类,在该类中没有任何地方loop.stop()。记得我反复强调“间歇”;代码中存在loop.stop()将导致“始终”而不是“间歇”。 -
我知道
loop.stop()没有出现在这些行中,但它很可能出现在代码库的其他地方,甚至可能出现在一个库中,它会在出现以下情况时停止循环无法处理的事件。除非 asyncio 中出现错误,否则消息发生的唯一方法是有人调用loop.stop(),所以这就是我首先要寻找的。如果这没有显示任何内容,下一步将是注释 asyncio 以了解消息是如何到达而不事先调用loop.stop()- 但您更有可能找到@ 987654338@上一步。 -
@user4815162342 正如我之前评论的那样(我可能不够清楚,我的错)我已经从第 139 行追踪到。无处在从第 139 行调用的调用堆栈中,我是否找到了
loop.stop()的任何实例。此外——我真的强调了这一点——错误只是间歇性地发生。含义:有时(实际上很少)会发生错误。大多数时候,代码运行没有任何问题。loop.stop()在调用堆栈中任何位置的存在都会导致不断的错误而不是间歇性的。 -
没问题,很高兴问题得到解决!