Author martin.panter
Recipients martin.panter
Date 2014-05-31.12:57:02
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1401541025.39.0.6743321007.issue21619@psf.upfronthosting.co.za>
In-reply-to
Content
The documentation for the “subprocess” module says that a “with” statement will “wait for” the process, implying that it does not leave a zombie. However this is not the case if there is buffered input data:

$ python3 -Wall -bt -q
>>> import subprocess
>>> with subprocess.Popen(("true",), stdin=subprocess.PIPE, bufsize=-1) as p:
...     from time import sleep; sleep(1)  # Wait for pipe to be broken
...     p.stdin.write(b"buffered data")
... 
13
Traceback (most recent call last):
  File "<stdin>", line 3, in <module>
  File "/usr/lib/python3.4/subprocess.py", line 899, in __exit__
    self.stdin.close()
BrokenPipeError: [Errno 32] Broken pipe
>>> # (Hit Ctrl-Z here)
[1]+  Stopped                 python3 -Wall -bt -q
[Exit 148]
$ ps
  PID TTY          TIME CMD
15867 pts/5    00:00:00 python3
15869 pts/5    00:00:00 true <defunct>
15873 pts/5    00:00:00 ps
32227 pts/5    00:00:10 bash

Similarly, calling Popen.communicate() does not clean the process up either if there is buffered input data and the process has already exited. The documentation does not spell out how a broken pipe is handled in communicate(), but after reading Issue 10963 I see that in many other cases it is meant to be ignored.

The best way to clean up a subprocess that I have come up with to close the pipe(s) and call wait() in two separate steps, such as:

try:
    proc.stdin.close()
except BrokenPipeError:
    pass
proc.wait()
History
Date User Action Args
2014-05-31 12:57:05martin.pantersetrecipients: + martin.panter
2014-05-31 12:57:05martin.pantersetmessageid: <1401541025.39.0.6743321007.issue21619@psf.upfronthosting.co.za>
2014-05-31 12:57:05martin.panterlinkissue21619 messages
2014-05-31 12:57:02martin.pantercreate