I am reading the the Python documentation on the Popen class in the subprocess module section and I came across the following code:
p1 = Popen(["dmesg"], stdout=PIPE)
p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE)
p1.stdout.close() # Allow p1 to receive a SIGPIPE if p2 exits.
output = p2.communicate()[0]
The documentation also states that
"The p1.stdout.close() call after starting the p2 is important in order for p1 to receive a SIGPIPE if p2 exits before p1.
Why must the p1.stdout be closed before we can receive a SIGPIPE and how does p1 knows that p2 exits before p1 if we already closed it?
SIGPIPE
is a signal that would be sent ifdmesg
tried to write to a closed pipe. Here,dmesg
ends up with two targets to write to, your Python process and thegrep
process.That's because
subprocess
clones file handles (using theos.dup2()
function). Configuringp2
to usep1.stdout
triggers aos.dup2()
call that asks the OS to duplicate the pipe filehandle; the duplicate is used to connectdmesg
togrep
.With two open file handles for
dmesg
stdout,dmesg
is never given aSIGPIPE
signal if only one of them closes early, sogrep
closing would never be detected.dmesg
would needlessly continue to produce output.So by closing
p1.stdout
immediately, you ensure that the only remaining filehandle reading fromdmesg
stdout is thegrep
process, and if that process were to exit,dmesg
receives aSIGPIPE
.