https://github.com/python/cpython/commit/99b70fe4ebf70c4d4fec4752058e6175e6802b74
commit: 99b70fe4ebf70c4d4fec4752058e6175e6802b74
branch: 3.13
author: Miss Islington (bot) <[email protected]>
committer: gpshead <[email protected]>
date: 2025-11-28T23:33:47-08:00
summary:

[3.13] gh-74389: gh-70560: subprocess.Popen.communicate() now ignores 
stdin.flush error when closed (GH-142061) (#142065)

gh-74389: gh-70560: subprocess.Popen.communicate() now ignores stdin.flush 
error when closed (GH-142061)

gh-70560: gh-74389: subprocess.Popen.communicate() now ignores stdin.flush 
error when closed

with a unittest and news entry.
(cherry picked from commit 923056b2d41c4c28ad9163901053cd3824d775c5)

Co-authored-by: Gregory P. Smith <[email protected]>

files:
A Misc/NEWS.d/next/Library/2025-11-29-04-20-44.gh-issue-74389.pW3URj.rst
M Lib/subprocess.py
M Lib/test/test_subprocess.py

diff --git a/Lib/subprocess.py b/Lib/subprocess.py
index 8702545eaf7b19..885f0092b53113 100644
--- a/Lib/subprocess.py
+++ b/Lib/subprocess.py
@@ -2099,6 +2099,10 @@ def _communicate(self, input, endtime, orig_timeout):
                     self.stdin.flush()
                 except BrokenPipeError:
                     pass  # communicate() must ignore BrokenPipeError.
+                except ValueError:
+                    # ignore ValueError: I/O operation on closed file.
+                    if not self.stdin.closed:
+                        raise
                 if not input:
                     try:
                         self.stdin.close()
diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py
index 2f96344164d211..a9f0ce2524e6ec 100644
--- a/Lib/test/test_subprocess.py
+++ b/Lib/test/test_subprocess.py
@@ -1159,6 +1159,19 @@ def test_writes_before_communicate(self):
         self.assertEqual(stdout, b"bananasplit")
         self.assertEqual(stderr, b"")
 
+    def test_communicate_stdin_closed_before_call(self):
+        # gh-70560, gh-74389: stdin.close() before communicate()
+        # should not raise ValueError from stdin.flush()
+        with subprocess.Popen([sys.executable, "-c",
+                               'import sys; sys.exit(0)'],
+                              stdin=subprocess.PIPE,
+                              stdout=subprocess.PIPE,
+                              stderr=subprocess.PIPE) as p:
+            p.stdin.close()  # Close stdin before communicate
+            # This should not raise ValueError
+            (stdout, stderr) = p.communicate()
+            self.assertEqual(p.returncode, 0)
+
     def test_universal_newlines_and_text(self):
         args = [
             sys.executable, "-c",
diff --git 
a/Misc/NEWS.d/next/Library/2025-11-29-04-20-44.gh-issue-74389.pW3URj.rst 
b/Misc/NEWS.d/next/Library/2025-11-29-04-20-44.gh-issue-74389.pW3URj.rst
new file mode 100644
index 00000000000000..a9bf5f80d80c9f
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2025-11-29-04-20-44.gh-issue-74389.pW3URj.rst
@@ -0,0 +1,3 @@
+When the stdin being used by a :class:`subprocess.Popen` instance is closed,
+this is now ignored in :meth:`subprocess.Popen.communicate` instead of
+leaving the class in an inconsistent state.

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to