问题
While I browsed posts, I ran into this example below on here, It is saying proc1.stdout.close()
is needed to be called for appropriate exit of proc1
, generating SIGPIPE
.
import subprocess
proc1 = subprocess.Popen(['ps', 'cax'], stdout=subprocess.PIPE)
proc2 = subprocess.Popen(['grep', 'python'], stdin=proc1.stdout,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
proc1.stdout.close() # Allow proc1 to receive a SIGPIPE if proc2 exits.
out, err = proc2.communicate()
print('out: {0}'.format(out))
print('err: {0}'.format(err))
However, I am not clear on that. Please fix my understanding.
SIGPIPE
occurs when aPIPE
tries to write to closedPIPE
.- Writer
PIPE
isproc1
'sstdout
and readerPIPE
isproc2
'sstdin
. proc1
will exit whenproc2
exit andproc1
tries to write data toproc2
'sstdin PIPE
. becauseproc2
'sstdin PIPE
is closed whenproc2
exitSIGPIPE
happen atproc1
becauseproc1
tries to write to closedproc2
'sstdin PIPE
.
From my understanding, SIGPIPE
would happen and proc1
would exit, regardless of closing proc1
's stdout
.
What do I miss?
Edit
After reading the post from @unutbu's comment......
I think the copied file descriptor(proc1.stdout
) is writer PIPE, not reader PIPE. thus, there are two writer PIPE and one reader PIPE connected one another.
Therefore, SIGPIPE
will be generated when proc2
exit because proc2
is only one process which has reader PIPE(will be closed when proc2
exit).
However, the above post seems to say that there are two reader PIPEs by copying proc1.stdout
so SIGPIPE
won't be generated even after proc2
exit because there still is another reader PIPE open. the below is the part of post.
So by closing p1.stdout immediately, you ensure that the only remaining filehandle reading from dmesg stdout is the grep process, and if that process were to exit, dmesg receives a SIGPIPE.
I am not saying that the post is wrong but I just want to fix my understanding. Thank you in advance.
回答1:
proc1 = subprocess.Popen(['ps', 'cax'], stdout=subprocess.PIPE)
creates this a pipe between the parent process and proc1
:
| | | |
| parent |-<-----<-| proc1 |
| | ^ | |
|
p1.stdout
p1.stdout
is what the parent would read to obtain (stdout) output from proc1
.
proc2 = subprocess.Popen(['grep', 'python'], stdin=proc1.stdout,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
connects a copy of the pipe from proc1 to proc2:
| | | | | |
| parent |-<-----<-| proc1 |->----->-| proc2 |
| | | | | |
By calling p1.stdout.close()
, we close the parent processes's side of the pipe:
| | | | | |
| parent | <-| proc1 |->----->-| proc2 |
| | | | | |
Now when proc2
terminates, its side of the pipe is also closed:
| | | | | |
| parent | <-| proc1 |-> | proc2 |
| | | | | |
The next time proc1
tries to write to the pipe, a SIGPIPE signal is generated,
which allows proc1
to terminate since it knows no one is listening on the other end of its pipes.
来源:https://stackoverflow.com/questions/48001819/python-subprocess-popen-pipe-and-sigpipe