Skip to content

Commit 86ba765

Browse files
Issue #21619: Popen objects no longer leave a zombie after exit in the with
statement if the pipe was broken. Patch by Martin Panter.
2 parents 7e8c795 + ab900c2 commit 86ba765

3 files changed

Lines changed: 24 additions & 4 deletions

File tree

Lib/subprocess.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -892,10 +892,12 @@ def __exit__(self, type, value, traceback):
892892
self.stdout.close()
893893
if self.stderr:
894894
self.stderr.close()
895-
if self.stdin:
896-
self.stdin.close()
897-
# Wait for the process to terminate, to avoid zombies.
898-
self.wait()
895+
try: # Flushing a BufferedWriter may raise an error
896+
if self.stdin:
897+
self.stdin.close()
898+
finally:
899+
# Wait for the process to terminate, to avoid zombies.
900+
self.wait()
899901

900902
def __del__(self, _maxsize=sys.maxsize):
901903
if not self._child_created:

Lib/test/test_subprocess.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2502,6 +2502,21 @@ def test_invalid_args(self):
25022502
stderr=subprocess.PIPE) as proc:
25032503
pass
25042504

2505+
def test_broken_pipe_cleanup(self):
2506+
"""Broken pipe error should not prevent wait() (Issue 21619)"""
2507+
proc = subprocess.Popen([sys.executable, "-c",
2508+
"import sys;"
2509+
"sys.stdin.close();"
2510+
"sys.stdout.close();" # Signals that input pipe is closed
2511+
], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
2512+
proc.stdout.read() # Make sure subprocess has closed its input
2513+
proc.stdin.write(b"buffered data")
2514+
self.assertIsNone(proc.returncode)
2515+
self.assertRaises(BrokenPipeError, proc.__exit__, None, None, None)
2516+
self.assertEqual(0, proc.returncode)
2517+
self.assertTrue(proc.stdin.closed)
2518+
self.assertTrue(proc.stdout.closed)
2519+
25052520

25062521
def test_main():
25072522
unit_tests = (ProcessTestCase,

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ Core and Builtins
1313
Library
1414
-------
1515

16+
- Issue #21619: Popen objects no longer leave a zombie after exit in the with
17+
statement if the pipe was broken. Patch by Martin Panter.
18+
1619
- Issue #15955: Add an option to limit the output size in bz2.decompress().
1720
Patch by Nikolaus Rath.
1821

0 commit comments

Comments
 (0)