FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

[3.14] gh-141473: Fix subprocess.Popen.communicate to send input to stdin upon a subsequent post-timeout call (GH-141477) by miss-islington · Pull Request #142059 · python/cpython · GitHub

Repository navigation

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension .py  (2) .rst  (2) All 2 file types selected
Viewed files
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Unified
Split
Hide whitespace
Diff view
Unified
Split
Hide whitespace
4 changes: 3 additions & 1 deletion Doc/library/subprocess.rst
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -831,7 +831,9 @@ Instances of the :class:`Popen` class have the following methods:

If the process does not terminate after *timeout* seconds, a
:exc:`TimeoutExpired` exception will be raised. Catching this exception and
retrying communication will not lose any output.
retrying communication will not lose any output. Supplying *input* to a
subsequent post-timeout :meth:`communicate` call is in undefined behavior
and may become an error in the future.

The child process is not killed if the timeout expires, so in order to
cleanup properly a well-behaved application should kill the child process and
Expand Down
2 changes: 1 addition & 1 deletion Lib/subprocess.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -2106,7 +2106,7 @@ def _communicate(self, input, endtime, orig_timeout):
input_view = memoryview(self._input)

with _PopenSelector() as selector:
if self.stdin and input:
if self.stdin and not self.stdin.closed and self._input:
selector.register(self.stdin, selectors.EVENT_WRITE)
if self.stdout and not self.stdout.closed:
selector.register(self.stdout, selectors.EVENT_READ)
Expand Down
34 changes: 34 additions & 0 deletions Lib/test/test_subprocess.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -1643,6 +1643,40 @@ def test_wait_negative_timeout(self):

self.assertEqual(proc.wait(), 0)

def test_post_timeout_communicate_sends_input(self):
"""GH-141473 regression test; the stdin pipe must close"""
with subprocess.Popen(
[sys.executable, "-uc", """\
import sys
while c := sys.stdin.read(512):
sys.stdout.write(c)
print()
"""],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
) as proc:
try:
data = f"spam{'#'*4096}beans"
proc.communicate(
input=data,
timeout=0,
)
except subprocess.TimeoutExpired as exc:
pass
# Prior to the bugfix, this would hang as the stdin
# pipe to the child had not been closed.
try:
stdout, stderr = proc.communicate(timeout=15)
except subprocess.TimeoutExpired as exc:
self.fail("communicate() hung waiting on child process that should have seen its stdin pipe close and exit")
self.assertEqual(
proc.returncode, 0,
msg=f"STDERR:\n{stderr}\nSTDOUT:\n{stdout}")
self.assertStartsWith(stdout, "spam")
self.assertIn("beans", stdout)


class RunFuncTestCase(BaseTestCase):
def run_python(self, code, **kwargs):
Expand Down
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
When :meth:`subprocess.Popen.communicate` was called with *input* and a
*timeout* and is called for a second time after a
:exc:`~subprocess.TimeoutExpired` exception before the process has died, it
should no longer hang.
Loading

Back | FazBrowse Home | New Git URL