为什么超时会避免龙卷风挂起?

时间:2015-11-10 16:34:55

标签: python tornado

等待Tornado协程中的concurrent.futures.Future的{​​{1}}有时会对我不利:

ThreadPoolExecutor

当我添加超时时,它可能会在超时期间挂起,但在此之后似乎实际上会返回正确的结果。

def slowinc(x):
    time.sleep(0.1)
    return x + 1
yield tp_executor.submit(slowinc, 1)  # sometimes hangs

这只发生在一个更大的测试套件的环境中,其中发生了许多不愉快的事情(子进程在中间步长终止)。这个错误几乎肯定与这种不愉快的背景有关,而不是严格意义上的龙卷风。但是,我相信我已经尽可能地隔离了这些令人不快的事情。

所以我为微妙的错误道歉,缺乏一个简单的可重复的例子。我希望失败的超时实际上导致成功的奇怪行为有助于隔离我的问题。

临时解决方案

到目前为止,我的解决方案如下:

yield gen.with_timeout(timedelta(seconds=5), 
                       executor.submit(...))  # hangs for 5sec, then works

这解决了我的直接问题,除了偶尔的一秒延迟之外,它是完全可用的。我仍然对这种行为感到困惑,我很好奇我正在做些什么来触发这个。

更新

上面的超时解决方案适用于Tornado 4.2和4.3下的Python 3.4,但@ ben-darnell的回答中提到的while not future.done(): try: yield gen.with_timeout(timedelta(seconds=1), future) except gen.TimeoutError: pass result = future.result() 解决方案和timeout解决方案都没有解决Python 2.7下的这个问题龙卷风4.2或4.3。

1 个答案:

答案 0 :(得分:1)

我没有完整的解决方案,但我认为我可以提供更简单的解决方法:启动一个在短时间内无效的后台PeriodicCallbackPeriodicCallback(lambda: None, 500).start()。这将确保IOLoop定期唤醒而不会侵入您的所有yield executor.submit()来电。

症状表明问题出在" waker" add_callback的行为:https://github.com/tornadoweb/tornado/blob/d9c5bc8fb6530a03ebbb6da667e26685b8eee0ea/tornado/ioloop.py#L929-L944

此代码在Tornado 4.3(https://github.com/tornadoweb/tornado/pull/1511/files)中已更改。如果您在4.3上,请查看问题是否仍然存在于4.2中。在你的"令人不快的"环境导致thread.get_ident()的行为与龙卷风期望的不同?

据报道,waker" pipe"在Windows上:https://github.com/tornadoweb/tornado/pull/1364