我有一个实现LRU缓存https://github.com/pbrady/fastcache的C扩展。我最近注意到,在一个使用缓存的应用程序(SymPy)中,超时信号丢失,应用程序继续运行。这只发生在使用我的C-extension而不是纯Python LRU缓存(即functools.lru_cache)https://github.com/pbrady/fastcache/issues/26时。
我通过调用PyErr_CheckSignals()来填充我的例程,并且信号丢失的次数减少了,但它仍然在发生。请注意,在调用期间,缓存将调用PyObject_Hash,PyDict_Get / Set / DelItem和PyObject_Call(如果未命中)。
这是SymPy代码的相关片段(超时是一个整数):
def _timeout(self, function, timeout):
def callback(x, y):
signal.alarm(0)
raise Skipped("Timeout")
signal.signal(signal.SIGALRM, callback)
signal.alarm(timeout) # Set an alarm with a given timeout
function()
signal.alarm(0) # Disable the alarm enter code here
有什么东西可以覆盖信号吗?如果是这样,我该如何解决这个问题?
答案 0 :(得分:0)
原来这里没有真正的谜,但这有点棘手。
除了调用PyErr_CheckSignals()之外,只要控制通过调用PyObject_Hash,PyDict_Get / Set / DelItem传递给它,解释器就可以捕获信号。如果解释器在其中一个函数中捕获到信号,则由于回调函数将触发异常(并且信号将在处理后消失)。但是,我没有检查所有函数的返回值(即我知道我的参数是可以清除的,所以我没有检查PyDict_SetItem的返回值) 因此,该例外被忽略,程序继续执行,好像信号没有发生一样。
特别感谢Ondrej通过此讨论。