PyErr_CheckSignals没有拾取信号

时间:2014-09-16 17:18:22

标签: python c signals python-c-api python-c-extension

我有一个实现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

有什么东西可以覆盖信号吗?如果是这样,我该如何解决这个问题?

1 个答案:

答案 0 :(得分:0)

原来这里没有真正的谜,但这有点棘手。

除了调用PyErr_CheckSignals()之外,只要控制通过调用PyObject_Hash,PyDict_Get / Set / DelItem传递给它,解释器就可以捕获信号。如果解释器在其中一个函数中捕获到信号,则由于回调函数将触发异常(并且信号将在处理后消失)。但是,我没有检查所有函数的返回值(即我知道我的参数是可以清除的,所以我没有检查PyDict_SetItem的返回值) 因此,该例外被忽略,程序继续执行,好像信号没有发生一样。

特别感谢Ondrej通过此讨论。