2015-08-03 2 views
3

Это Followup к previous question:Тупик на общение с несколькими детьми

У меня есть parent.py:

from sys import argv 
from random import randrange 
from subprocess import Popen, PIPE 
lines = int(argv[1]) 
procs = int(argv[2]) 
cmd = ["python", "child.py"] 
children = list() 
for p in range(procs): 
    children.append([0,Popen(cmd, stdin=PIPE, stdout=PIPE)]) 
for i in range(lines): 
    child = children[randrange(procs)] 
    child[0] += 1 
    child[1].stdin.write("hello\n") 
for n,p in children: 
    p.stdin.close() 
    out = p.stdout.read() 
    p.stdout.close() 
    exitcode = p.wait() 
    print n,out,exitcode 
    assert n == int(out) 
assert lines == sum(n for n,_ in children) 

и child.py:

import sys 
l = list() 
for line in sys.stdin: 
    l.append(line) 
sys.stdout.write(str(len(l))) 

При создании одного ребенка , он отлично работает:

$ python parent.py 100 1 
100 100 0 

Однако несколько детей тупиковой:

$ python parent.py 100 2 & 
[1] 59492 
$ strace -p 59492 
Process 59492 attached - interrupt to quit 
read(5, ^C <unfinished ...> 
Process 59492 detached 
$ pstree -p 59492 
python(59492)-+-python(59494) 
       `-python(59495) 
$ strace -p 59494 
Process 59494 attached - interrupt to quit 
read(0, ^C <unfinished ...> 
Process 59494 detached 
$ strace -p 59495 
Process 59495 attached - interrupt to quit 
read(0, ^C <unfinished ...> 
Process 59495 detached 

Почему дети продолжают read() даже после того, как я закрываю их stdin?

PS. Простое изменение закрытия всех детских stdins до того чтения с любого из них решает проблему:

$ python parent.py 10000 4 
2486 2486 0 
2493 2493 0 
2531 2531 0 
2490 2490 0 

ПОЧЕМУ ?!

+0

'python parent.py 100 2' работает для меня каждый раз. – Celada

+0

@Celada: вы используете python 2.7, правильно? – sds

+0

Да, я использую, 2.7.3. – Celada

ответ

1

Это оказалось ошибкой в ​​Python 2.6

Python 2,7 делает не тупиковый.

+0

Интересно! Вы знаете, если это [эта ошибка] (http://bugs.python.org/issue4112)? – Celada

+0

@ Celada: похоже, но ошибка говорит о том, что она не должна фиксироваться в 2.7 - и моя проблема не проявляется в 2.7, поэтому я не уверен. – sds

+0

О, да, я неправильно понял, что * будет * backport до 2.7 вместо * не будет * backport до 2.7. Так и должно быть, это еще одна ошибка. – Celada

0

Вы запрограммировали своих детей на чтение ВСЕХ stdin (for line in sys.stdin:), то есть для чтения, пока они не достигнут EOF. Если их stdin - это труба, они получат EOF, когда другой конец трубы закроется.

+1

Да, но родитель * * * закрывает другой конец трубы: у вас есть 'для n, p у детей: p.stdin.close()'. Что такое OP, и я не хватает? – Celada

+0

@Celada Я предполагаю, что он не закрывал трубу изначально, и она зашла в тупик. Теперь он исправил это, и он спрашивает, почему закрытие трубы разрешает тупик. – PSkocik

+1

Нет, ваша интерпретация моего вопроса полностью не указана, – sds

Смежные вопросы