似乎多线程程序中的异步信号没有被Python正确处理。但是,我想我会在这里检查是否有人能够发现我违反某个原则的地方,或者误解了某些概念。异步键盘中断和多线程
也有类似的线程,我在这里找到了SO,但没有一个看起来完全一样。
该场景是:我有两个线程,读者线程和写入器线程(主线程)。写入器线程写入读取器线程轮询的管道。这两个线程使用基元(我假设使用pthread_cond_wait
执行)进行协调。主线程在Event
上等待,而读取器线程最终设置它。
但是,如果我想在主线程正在等待Event
时中断我的程序,则不会异步处理KeyboardInterrupt。
这里是一个小程序来说明我的观点:
#!/usr/bin/python
import os
import sys
import select
import time
import threading
pfd_r = -1
pfd_w = -1
reader_ready = threading.Event()
class Reader(threading.Thread):
"""Read data from pipe and echo to stdout."""
def run(self):
global pfd_r
while True:
if select.select([pfd_r], [], [], 1)[0] == [pfd_r]:
output = os.read(pfd_r, 1000)
sys.stdout.write("R> '%s'\n" % output)
sys.stdout.flush()
# Suppose there is some long-running processing happening:
time.sleep(10)
reader_ready.set()
# Set up pipe.
(pfd_r, pfd_w) = os.pipe()
rt = Reader()
rt.daemon = True
rt.start()
while True:
reader_ready.clear()
user_input = raw_input("> ").strip()
written = os.write(pfd_w, user_input)
assert written == len(user_input)
# Wait for reply -- Try to ^C here and it won't work immediately.
reader_ready.wait()
开始与“./bug.py”程序,在提示符下输入一些。一旦看到阅读器以前缀'R>'回复,请尝试使用^C
中断。
我所看到的(Ubuntu Linux 10.10,Python 2.6.6)是^C
直到阻塞reader_ready.wait()
返回后才被处理。我期望看到的是^C
异步引发,导致程序终止(因为我没有捕获KeyboardInterrupt)。
这可能看起来像一个人为的例子,但我在真实世界的程序中遇到了这个问题,time.sleep(10)
被实际计算所取代。
我在做什么明显错误,就像误解预期的结果会是什么?
编辑:我也刚刚用Python 3.1.1进行了测试,存在同样的问题。
太好了,谢谢你的解释。我可能会说这个特殊的“功能”实际上是一个错误....我想我必须找出另一种方法来同步我的线程。这似乎很愚蠢,我不能使用内置的同步原语来做到这一点。 –
好吧,你可以去做一个漂亮的hackish:'while 1:'(Line break)'如果reader_ready.wait(1):break' –
我可以这样做,或者使用'reader_ready.wait(99999)'作为超时时间。它似乎偶然会做一个“睡眠”,所以键盘中断可以被处理。尽管如此,一个黑客。 –