【发布时间】:2012-06-02 09:43:39
【问题描述】:
我得到了如下简单的程序:
import threading
import time
import signal
WITH_DEADLOCK = 0
lock = threading.Lock()
def interruptHandler(signo, frame):
print str(frame), 'received', signo
lock.acquire()
try:
time.sleep(3)
finally:
if WITH_DEADLOCK:
print str(frame), 'release'
lock.release()
signal.signal(signal.SIGINT, interruptHandler)
for x in xrange(60):
print time.strftime("%H:%M:%S"), 'main thread is working'
time.sleep(1)
因此,如果您启动该程序,并且在 3 秒内按两次 Ctrl+C,则不会出现死锁。每次按 Ctrl + C 时,都会显示正确的行。 如果您更改 WITH_DEADLOCK=1 并按 Ctrl+C 两次(3 秒内),则程序将挂起。
有人可以解释为什么打印操作会产生如此大的差异吗?
(我的python版本是2.6.5)
【问题讨论】:
-
我的猜测是打印操作会改变以处理新信号(没有释放锁)......
-
至少缺少
global lock -
查看被中断的帧,我注意到当它挂起时,信号正在中断另一个帧。此外,将锁更改为递归可以阻止挂起的发生。这些告诉我它正在挂起,因为第二个处理程序正在中断第一个处理程序,然后等待第一个处理程序持有的锁。死锁是因为第一个在等待第二个返回,第二个在等待第一个释放锁。当它不挂起时,被中断的帧总是一样的。至于为什么会这样,我还是不确定。
-
我知道它挂在哪里,但我无法解释为什么它没有打印操作。将 Lock 更改为 RLock 将破坏评论部分的安全性(因为它是信号处理程序)
-
令人惊讶的是,在 Python2 上没有
print并且确实没有it deadlocks even withoutprinton Python3,它不会死锁。信号处理程序必须是可重入的(它甚至比线程安全更具限制性)。当执行第二个处理程序时,第一个处理程序被中断,因此它永远不会释放锁,第二个处理程序无法获得它 -> 死锁。
标签: python linux signals deadlock