即使子进程已取消,MultiProcessing Pipe recv块仍会阻塞 [英] MultiProcessing Pipe recv blocks even when child process is defunct

查看:312
本文介绍了即使子进程已取消,MultiProcessing Pipe recv块仍会阻塞的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

阅读有关此主题的几个问题,我现在知道子进程从父进程继承了文件描述符.当父母关闭连接时,这会使孩子更难收到EOFError.

Reading several questions on this topic I understand now that the child process inherits the file descriptors from the parent process. Which will make it more difficult for a child to receive an EOFError when a parent closes the connection.

但是我的情况恰恰相反,我不明白我面临的问题.

But my situation is the other way around, and I do not understand the problem I am facing.

我有一个父进程,该进程启动一个子进程,并使其能够访问我创建的Pipe连接的一端.现在,当子进程完成,发生故障或其他任何情况时,所有操作都将停止并且连接将关闭.此时,子进程显示为已消失.

I have a parent process that starts a child process, and gives it access to one end of the Pipe connection I created. Now when the child process is done, malfunctions or whatever, everything is stopped and the connection is closed. At this point the child process shows to be defunct.

然后,我希望父进程的连接在阻塞的recv调用上抛出EOFError.但是相反,它只是坐在那里等待.

Then I expect the parent process' connection to throw an EOFError on the blocking recv call. But instead it just sits there and waits.

我在这里想念什么?

编辑

我认为这个例子代表了问题:

I think this example represents the problem:

from multiprocessing import Process, Pipe
from threading import Thread
import time

class Parent(object):

    def __init__(self):
        self.parent_conn, child_conn = Pipe()
        self.child = Process(target=Child, args=(child_conn,))
        self.child.start()        

        def recv():
            try:
                self.parent_conn.recv()
            except EOFError:
                print "EOF"
            except:
                print "something else"

        # Does not work
        recv()

        # Works fine
        t = Thread(target=recv)
        t.setDaemon(True)
        t.start()

    def close(self):
        self.parent_conn.close()
        self.child.join()

class Child(object):

    def __init__(self, conn):
        conn.close()

if __name__ == "__main__":
    p = Parent()
    time.sleep(1)
    p.close()

如果我确实使用单独的线程,则允许父级关闭其自己的连接,并且一切正常. (请注意,您仍然需要知道完成该工作的方式),相反,如果我直接调用recv,它将明显阻塞,但是我怀疑一旦子进程关闭其连接,它将引发EOFError.但事实并非如此.有人可以澄清吗?

If I do use the separate thread, the parent is allowed to close its own connection and everything works fine. (Note that you still need to know somehow that the child is done for, to do this) Instead if I call recv directly it will block obviously, but I would suspect it to raise an EOFError as soon as the child process closes its connection. But it does not. Can anyone clarify?

推荐答案

self.child.start()之后添加child_conn.close().它是使用管道封闭未使用端的惯用法.另外(可选)提供duplex=False参数.

Add child_conn.close() after self.child.start(). It is idiomatic for working with pipes to close unused ends. Also (optionally) provide duplex=False parameter.

问题是,我事先不知道它是否会立即关闭.通常,孩子应该能够发送和接收.此外,我仍然不明白为什么这种方法无法正常工作.

The things is, I don't know beforehand whether it is going to close right away.. Normally the child should be able to send and receive. Furthermore I still do not get why this won't work, as is.

    父级中的
  1. child_conn.close()并不意味着 child 应该立即关闭其结尾
  2. parent_conn.recv直到有人可能会child_conn.send()才返回.如果打开child_conn(在孩子或父母中),则有 个机会
  1. child_conn.close() in the parent doesn't mean that child should close its end immediately
  2. parent_conn.recv doesn't return until there is a chance that somebody will child_conn.send(). If child_conn is opened (in child or parent) then there is a chance

如果我确实使用单独的线程,则允许父级关闭其自己的连接,并且一切正常.请注意,您仍然需要知道孩子的工作方式,

If I do use the separate thread, the parent is allowed to close its own connection and everything works fine. Note that you still need to know somehow that the child is done for, to do this

您不需要知道它.您可以在子级中打开连接后立即关闭.不管孩子做什么,在self.child.start()之后在父级中调用child_conn.close()都是可以的.

You don't need to know it. You can close as soon as the connection is opened in the child. Calling child_conn.close() in the parent after self.child.start() is fine whatever child does.

您能再解释一下双工选项吗?

Could you explain the duplex option a little bit more also?

duplex = False 表示管道是单向的,即您只能调用parent_conn.recv()child_conn.send().否则,它是双向的,并且两个连接都支持send/recv.

duplex=False means that the pipe is unidirectional i.e., you can only call parent_conn.recv() and child_conn.send(). Otherwise it is bidirectional and both connections support send/recv.

这篇关于即使子进程已取消,MultiProcessing Pipe recv块仍会阻塞的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆