如何解除阻塞在已删除的命名管道上的线程阻塞?

How to unblock a thread blocking on a deleted named pipe?

我有一个 Python 程序,该程序将命名管道用于各种目的。 每个管道都由不同的线程管理,因此不会阻塞主线程。

假设我有一个线程正在阻塞对 open('in', 'rb') 的调用,其中 in 是命名管道的相对路径。 如果我想关闭我的程序,我会使用类似这样的方法来解除我的线程与另一个线程的阻塞:

with suppress(OSError):
    fd = os.open('in', O_WRONLY | O_NONBLOCK)
    os.close(fd)

这只是在写入模式下打开管道,以便 open 上阻塞的线程可以继续前进,然后关闭它。我使用 O_NONBLOCK 来避免阻塞,以防其他线程已经终止(并忽略潜在的 OSError)。

在我的线程在 open 上阻塞时有人决定删除命名管道 in 之前,这工作正常。 在这种情况下,我不能使用我的 "try to open the pipe in non blocking mode and close it" 方法,因为管道在文件系统上不再可见(并且非阻塞打开只会创建一个全新的管道)。

除了杀死线程之外,这个问题的正确解决方案是什么? 请注意,我无法阻止其他进程删除管道,权限也无济于事(删除进程可以 运行 作为 root)。

我已经使用 os.open('in', O_RDONLY | O_NONBLOCK) 解决了我的问题,即使管道的另一端没有编写器,它也会生成一个文件描述符。

一旦我有了一个有效的文件描述符用于读取,我就能够将其提供给 select() 系统调用以阻塞,直到有东西可以读取。

为了处理 "what if someone deletes the pipe from the file system while I'm blocking" 问题,我使用了 pipe() 系统调用来获取一个未命名的管道(Python 版本只为 2 个生成了 2 个文件描述符管道的末端)。

我也将这个未命名管道的读取描述符提供给 select() 调用,所以任何时候我想停止我的程序我只是通过写入管道的写入描述符来取消阻塞 select()无名管道,不管有名管道是怎么回事。