I had an issue with close_fds
in Python27 so after doing some research I found this example:
from subprocess import Popen, PIPE, STDOUT
p1 = Popen(['cat'], stdin=PIPE, stdout=PIPE)
p2 = Popen(['grep', 'a'], stdin=p1.stdout, stdout=PIPE)
p1.stdin.write("aaaaaaaaaaaaaaaa\n")
p1.stdin.close()
p2.stdout.read()
My problem is that I can't understand why p1.stdin
remains open. p1
is not a child of p2
so p2
shouldn't inherit any p1
resource except p1.stdout
which is explicitly passed. Furthermore why setting close_fds=True
in p2
resolves the issue? Here is written this:
If close_fds is true, all file descriptors except 0, 1 and 2 will be closed before the child process is executed.
So even if I will be able to understand the inheritance between p1
and p2
still p1.stdin
shouldn't be closed by close_fds=True
because it is the standard input (1).
Since p1
and p2
are siblings, there is no inheritance going on between their corresponding processes directly.
However, consider the file descriptor that the parent sees as p1.stdin
, inherited by p1
and redirected to its stdin
. This file descriptor exists in the parent process (with a number other than 0, 1, or 2 - you can verify this by printing p1.stdin.fileno()
), and it has to exist, because we intend to write to it from the parent. It is this file descriptor that is unintentionally inherited and kept open by p2
.
When an open file is referenced by multiple file descriptors, as is the case with p1.stdin
, it is only closed when all the descriptors are closed. This is why it is necessary to both close p1.stdin
and pass close_fds
to p2
. (If you implemented the spawning code manually, you would simply close the file descriptor after the second fork()
.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With