Чтение нескольких вопросов по этой теме. Теперь я понимаю, что дочерний процесс наследует дескрипторы файла из родительского процесса. Это затруднит получение ребенком EOFError, когда родитель закрывает соединение.MultiProcessing Pipe recv блокирует, даже когда дочерний процесс не работает
Но моя ситуация наоборот, и я не понимаю, с чем сталкиваюсь.
У меня есть родительский процесс, который запускает дочерний процесс и дает ему доступ к одному из концов подключенного соединения. Теперь, когда дочерний процесс завершен, сбои или что-то еще, все остановлено и соединение закрыто. В этот момент дочерний процесс показывает, что он не функционирует.
Затем я ожидаю, что соединение родительского процесса вызовет EOFError на вызов блокировки recv. Но вместо этого он просто сидит и ждет.
Что мне здесь не хватает?
EDIT
Я думаю, что этот пример представляет собой проблему:
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, как только дочерний процесс завершит соединение. Но это не так. Может ли кто-нибудь уточнить?
Не могли бы вы предоставить минимальный пример кода, демонстрирующий проблему? – jfs
@ J.F.Sebastian, я привел пример. Чтобы показать, что recv сохраняет блокировку. Я также предоставил второй вариант, который показывает, что он может легко закрыть, если это станет возможным. –
добавить 'child_conn.close()' после 'self.child.start()'. [Идиоматично работать с трубами, чтобы закрыть неиспользуемые концы] (https://gist.github.com/zed/7540510). Также (необязательно) укажите параметр 'duplex = False'. Если '.close()' работает для вас; пожалуйста, [разместите его как свой собственный ответ] (http://stackoverflow.com/help/self-answer) для других. – jfs