]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-74389: gh-70560: subprocess.Popen.communicate() now ignores stdin.flush error...
authorGregory P. Smith <68491+gpshead@users.noreply.github.com>
Sat, 29 Nov 2025 05:03:06 +0000 (21:03 -0800)
committerGitHub <noreply@github.com>
Sat, 29 Nov 2025 05:03:06 +0000 (05:03 +0000)
gh-70560: gh-74389: subprocess.Popen.communicate() now ignores stdin.flush error when closed

with a unittest and news entry.

Lib/subprocess.py
Lib/test/test_subprocess.py
Misc/NEWS.d/next/Library/2025-11-29-04-20-44.gh-issue-74389.pW3URj.rst [new file with mode: 0644]

index 168703828fc50e7f5208cd2c5a369e075ca618d5..99e2d0755d7e4643c14c8cbb3e15b1e969278964 100644 (file)
@@ -2077,6 +2077,10 @@ class Popen:
                     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()
index 5e73810dcb725338557cdfec93292d5738baad05..2d717f985a3ac381e5c00ba61dbb9f61ea3fb986 100644 (file)
@@ -1104,6 +1104,19 @@ class ProcessTestCase(BaseTestCase):
         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 (file)
index 0000000..a9bf5f8
--- /dev/null
@@ -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.