在线程中传播系统调用中断

Posted

技术标签:

【中文标题】在线程中传播系统调用中断【英文标题】:Propagate system call interruptions in threads 【发布时间】:2012-04-23 13:05:42 【问题描述】:

我正在运行两个 python 线程 (import threading)。他们俩都在open() 呼叫中被阻止;事实上,他们会尝试打开命名管道以便在其中写入,因此在有人尝试从命名管道读取之前阻塞是一种正常的行为。

简而言之,它看起来像:

import threading

def f():
    open('pipe2', 'r')

if __name__ == '__main__':
    t = threading.Thread(target=f)
    t.start()
    open('pipe1', 'r')

当我键入 ^C 时,主线程中的 open() 被中断(引发 IOError 且 errno == 4)。

我的问题是:t 线程仍在等待,我想传播中断行为,以使其也引发IOError

【问题讨论】:

如果在子线程启动前设置 daemon=True 会怎样? 仅此而已。而且,我的问题的目的不是杀死线程,我希望他在收到信号后做一些事情(清理)。 【参考方案1】:

我在 python 文档中找到了这个: " ...只有主线程可以设置新的信号处理程序,并且主线程将是唯一接收信号的线程(这是由 Python 信号模块强制执行的,即使底层线程实现支持向单个线程发送信号)。这意味着信号不能用作线程间通信的手段。改用锁。 " 也许您还应该查看这些文档:exceptions.KeyboardInterrupt

library/signal.html

另一个想法是使用 select 在线程中异步读取管道。这适用于 Linux,不确定 Windows(它不是​​最干净的,也不是最好的实现):

   #!/usr/bin/python

   import threading
   import os
   import select

   def f():
           f = os.fdopen(os.open('pipe2', os.O_RDONLY|os.O_NONBLOCK))
           finput = [ f ]
           foutput = []
           # here the pipe is scanned and whatever gets in will be printed out
           # ...as long as 'getout' is False
           while finput and not getout:
                   fread, fwrite, fexcep = select.select(finput, foutput, finput)
                   for q in fread:
                           if q in finput:
                                   s = q.read()
                                   if len(s) > 0:
                                           print s

   if __name__ == '__main__':
           getout = False
           t = threading.Thread(target=f)
           t.start()
           try:
                   open('pipe1', 'r')
           except:
                   getout = True

【讨论】:

以上是关于在线程中传播系统调用中断的主要内容,如果未能解决你的问题,请参考以下文章

抢占式内核中,线程在系统调用过程中被抢占,然后又被重新调度时,如何返回至被中断的系统调用的

在Windows或Linux等高级系统里,驱动程序是以线程的形式独立运行,还是做为过程被线程调用运行?

Linux 系统调用的内部结构

linux系统中,进程进行系统调用进入内核态时,是该进程本身进入内核态还是操作系统新开了一个内核线程?

线程切换时CPU在干嘛

Linux 系统调用流程序列