检测命名管道的关闭

Posted

技术标签:

【中文标题】检测命名管道的关闭【英文标题】:Detect close of named pipe 【发布时间】:2015-04-02 03:13:15 【问题描述】:

我有一个将数据写入命名管道的 C 程序和一个从命名管道读取数据的 Python 程序,如下所示:

p = open('/path/to/named/pipe', 'r')
...
data = p.read(size)

当 C 程序退出时,它会关闭管道。

如何从 Python 端检测到这一点?我尝试为 SIGPIPE 安装处理程序,但似乎 SIGPIPE 仅在尝试写入封闭管道时发生,而不是从中读取。我还预计 p.read(size) 可能会因为另一端的 EOF 而返回长度为零的字符串,但实际上它只是挂起等待数据。

我该如何检测并处理这种情况?

【问题讨论】:

如果 Python 处于闲置状态,这几乎肯定意味着某个进程(可能它本身)仍然有管道打开以供写入。如果所有的作者都关闭了管道,那么所有的读者(通常,'all' 只是一个读者)将在他们下一次尝试阅读时获得 EOF。请注意,如果 Python 打开管道进行读取和写入,它是一个写入器,永远不会得到 EOF。 您可以为该文件描述符放置nonblock 我认为这里的问题是使用open(...,'r') 没有做正确的事情;必须使用os.open(..., os.O_RDONLY) 【参考方案1】:

您可以使用the select module 来监控管道的状态。在 Linux 上(select.poll() 可用,以下代码将检测是否存在封闭管道:

import select

# ...

poller = select.poll()
# Register the "hangup" event on p
poller.register(p, select.POLLHUP)

# Call poller.poll with 0s as timeout
for descriptor, mask in poller.poll(0):
    # Can contain at most one element, but still:
    if descriptor == p.fileno() and mask & select.POLLHUP:
        print('The pipe is closed on the other end.')
        p.close()

其他操作系统也有类似的方法可以检测到这种情况。

调用read时挂起,是因为IO阻塞。您可以使用os.set_blocking 将其变为非阻塞(并让read 返回一个空字符串),但这仍然无法让您检测到另一端的管道何时关闭。

【讨论】:

以上是关于检测命名管道的关闭的主要内容,如果未能解决你的问题,请参考以下文章

检测阅读器何时关闭命名管道(FIFO)

命名管道 232 管道正在关闭

检测命名管道与 I/O 完成断开连接

C#命名管道,如何检测客户端断开连接

如何使用重叠 I/O 检测到命名管道服务器的客户端连接?

c中的命名管道