bpo-35721: Close socket pair if Popen in _UnixSubprocessTransport fails (GH-11553)
This slightly expands an existing test case `test_popen_error` to trigger a `ResourceWarning` and fixes it. https://bugs.python.org/issue35721
This commit is contained in:
parent
6d1c46746e
commit
9932fd91e8
|
@ -757,12 +757,18 @@ class _UnixSubprocessTransport(base_subprocess.BaseSubprocessTransport):
|
||||||
# other end). Notably this is needed on AIX, and works
|
# other end). Notably this is needed on AIX, and works
|
||||||
# just fine on other platforms.
|
# just fine on other platforms.
|
||||||
stdin, stdin_w = socket.socketpair()
|
stdin, stdin_w = socket.socketpair()
|
||||||
self._proc = subprocess.Popen(
|
try:
|
||||||
args, shell=shell, stdin=stdin, stdout=stdout, stderr=stderr,
|
self._proc = subprocess.Popen(
|
||||||
universal_newlines=False, bufsize=bufsize, **kwargs)
|
args, shell=shell, stdin=stdin, stdout=stdout, stderr=stderr,
|
||||||
if stdin_w is not None:
|
universal_newlines=False, bufsize=bufsize, **kwargs)
|
||||||
stdin.close()
|
if stdin_w is not None:
|
||||||
self._proc.stdin = open(stdin_w.detach(), 'wb', buffering=bufsize)
|
stdin.close()
|
||||||
|
self._proc.stdin = open(stdin_w.detach(), 'wb', buffering=bufsize)
|
||||||
|
stdin_w = None
|
||||||
|
finally:
|
||||||
|
if stdin_w is not None:
|
||||||
|
stdin.close()
|
||||||
|
stdin_w.close()
|
||||||
|
|
||||||
|
|
||||||
class AbstractChildWatcher:
|
class AbstractChildWatcher:
|
||||||
|
|
|
@ -468,9 +468,7 @@ class SubprocessMixin:
|
||||||
isinstance(self, SubprocessFastWatcherTests)):
|
isinstance(self, SubprocessFastWatcherTests)):
|
||||||
asyncio.get_child_watcher()._callbacks.clear()
|
asyncio.get_child_watcher()._callbacks.clear()
|
||||||
|
|
||||||
def test_popen_error(self):
|
def _test_popen_error(self, stdin):
|
||||||
# Issue #24763: check that the subprocess transport is closed
|
|
||||||
# when BaseSubprocessTransport fails
|
|
||||||
if sys.platform == 'win32':
|
if sys.platform == 'win32':
|
||||||
target = 'asyncio.windows_utils.Popen'
|
target = 'asyncio.windows_utils.Popen'
|
||||||
else:
|
else:
|
||||||
|
@ -480,12 +478,23 @@ class SubprocessMixin:
|
||||||
popen.side_effect = exc
|
popen.side_effect = exc
|
||||||
|
|
||||||
create = asyncio.create_subprocess_exec(sys.executable, '-c',
|
create = asyncio.create_subprocess_exec(sys.executable, '-c',
|
||||||
'pass', loop=self.loop)
|
'pass', stdin=stdin,
|
||||||
|
loop=self.loop)
|
||||||
with warnings.catch_warnings(record=True) as warns:
|
with warnings.catch_warnings(record=True) as warns:
|
||||||
with self.assertRaises(exc):
|
with self.assertRaises(exc):
|
||||||
self.loop.run_until_complete(create)
|
self.loop.run_until_complete(create)
|
||||||
self.assertEqual(warns, [])
|
self.assertEqual(warns, [])
|
||||||
|
|
||||||
|
def test_popen_error(self):
|
||||||
|
# Issue #24763: check that the subprocess transport is closed
|
||||||
|
# when BaseSubprocessTransport fails
|
||||||
|
self._test_popen_error(stdin=None)
|
||||||
|
|
||||||
|
def test_popen_error_with_stdin_pipe(self):
|
||||||
|
# Issue #35721: check that newly created socket pair is closed when
|
||||||
|
# Popen fails
|
||||||
|
self._test_popen_error(stdin=subprocess.PIPE)
|
||||||
|
|
||||||
def test_read_stdout_after_process_exit(self):
|
def test_read_stdout_after_process_exit(self):
|
||||||
|
|
||||||
async def execute():
|
async def execute():
|
||||||
|
|
|
@ -486,6 +486,7 @@ Florian Festi
|
||||||
John Feuerstein
|
John Feuerstein
|
||||||
Carl Feynman
|
Carl Feynman
|
||||||
Vincent Fiack
|
Vincent Fiack
|
||||||
|
Niklas Fiekas
|
||||||
Anastasia Filatova
|
Anastasia Filatova
|
||||||
Tomer Filiba
|
Tomer Filiba
|
||||||
Segev Finer
|
Segev Finer
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
Fix :meth:`asyncio.SelectorEventLoop.subprocess_exec()` leaks file descriptors
|
||||||
|
if ``Popen`` fails and called with ``stdin=subprocess.PIPE``.
|
||||||
|
Patch by Niklas Fiekas.
|
Loading…
Reference in New Issue