我有一个体系结构,其中主进程可以产生子进程。
主进程通过管道向子进程发送计算请求。
下面是我当前的子进程代码:
while True:
try:
# not sufficient because conn.recv() is blocking
if self.close_event.is_set():
break
fun, args = self.conn.recv()
# some heavy computation
res = getattr(ds, fun)(*args)
self.conn.send(res)
except EOFError as err:
# should be raised by conn.recv() if connection is closed
# but it never happens
break
以及它在主进程中的初始化方式:
def init_worker(self):
close_event = DefaultCtxEvent()
conn_parent, conn_child = Pipe()
process = WorkerProcess(
i, self.nb_workers, conn_child, close_event, arguments=self.arguments)
process.daemon = True
process.start()
# close the side we don't use
conn_child.close()
# Remember the side we need
self.conn = conn_parent
我有一个干净的方法,应该关闭所有的子进程,就像这样从主进程:
def clean(self):
self.conn.close()
# waiting for the loop to break for a clean exit
self.child_process.join()
然而,对conn.recv()
的调用会阻塞,并且不会像我所期望的那样抛出错误。我可能在某种程度上混淆了“conn_parent”和“conn_children”的行为?
如何正确关闭儿童连接?
编辑:一个可能的解决方案是显式发送一条消息,内容类似于“_break”。循环通过conn.recv()
接收消息并中断。这是一个“正常”模式吗?作为奖励,有没有办法在不终止进程的情况下杀死一个可能长时间运行的方法?
1条答案
按热度按时间8i9zcol21#
显然有一个problem with linux Pipes,因为子节点派生了父节点的连接,它仍然是打开的,需要在子节点端显式关闭。
这只是一个如何实现虚拟示例。
第一个
这在Windows上是不需要的,或者当Linux使用“spawn”来创建worker时,因为子节点不会派生父节点连接,但是此代码将在具有任何worker创建策略的任何系统上工作。