与多个 children 通信时出现死锁
Deadlock on communicating with multiple children
这是 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)))
当我创建单个 child 时,它工作正常:
$ python parent.py 100 1
100 100 0
然而,多个children死锁:
$ 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
为什么 children 在我关闭他们 stdin
后仍继续 read()
?
PS。关闭 all children 的标准输入 before 的简单更改 solves问题:
$ python parent.py 10000 4
2486 2486 0
2493 2493 0
2531 2531 0
2490 2490 0
为什么?!
您已将 children 编程为读取所有标准输入 (for line in sys.stdin:
),也就是说,继续读取直到到达 EOF。如果他们的 stdin
是一个管道,当管道的另一端关闭时他们将得到 EOF。
这原来是 Python 2.6
中的错误
Python 2.7 不会死锁。
这是 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)))
当我创建单个 child 时,它工作正常:
$ python parent.py 100 1
100 100 0
然而,多个children死锁:
$ 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
为什么 children 在我关闭他们 stdin
后仍继续 read()
?
PS。关闭 all children 的标准输入 before 的简单更改 solves问题:
$ python parent.py 10000 4
2486 2486 0
2493 2493 0
2531 2531 0
2490 2490 0
为什么?!
您已将 children 编程为读取所有标准输入 (for line in sys.stdin:
),也就是说,继续读取直到到达 EOF。如果他们的 stdin
是一个管道,当管道的另一端关闭时他们将得到 EOF。
这原来是 Python 2.6
中的错误Python 2.7 不会死锁。