Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d602141

Browse files
cptpcrdgpshead
andcommitted
Refactor to use context manager
Simplifies the logic and should help avoid mistakes in the future. Co-authored-by: Gregory P. Smith <[email protected]>
1 parent e299737 commit d602141

1 file changed

Lines changed: 31 additions & 49 deletions

File tree

Lib/subprocess.py

Lines changed: 31 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1306,6 +1306,26 @@ def _close_pipe_fds(self,
13061306
# Prevent a double close of these handles/fds from __init__ on error.
13071307
self._closed_child_pipe_fds = True
13081308

1309+
@contextlib.contextmanager
1310+
def _on_error_fd_closer(self):
1311+
"""Helper to ensure file descriptors opened in _get_handles are closed"""
1312+
to_close = []
1313+
try:
1314+
yield to_close
1315+
except:
1316+
if hasattr(self, '_devnull'):
1317+
to_close.append(self._devnull)
1318+
del self._devnull
1319+
for fd in to_close:
1320+
try:
1321+
if _mswindows and isinstance(fd, Handle):
1322+
fd.Close()
1323+
else:
1324+
os.close(fd)
1325+
except OSError:
1326+
pass
1327+
raise
1328+
13091329
if _mswindows:
13101330
#
13111331
# Windows methods
@@ -1321,22 +1341,18 @@ def _get_handles(self, stdin, stdout, stderr):
13211341
c2pread, c2pwrite = -1, -1
13221342
errread, errwrite = -1, -1
13231343

1324-
stdin_needsclose = False
1325-
stdout_needsclose = False
1326-
stderr_needsclose = False
1327-
1328-
try:
1344+
with self._on_error_fd_closer() as err_close_fds:
13291345
if stdin is None:
13301346
p2cread = _winapi.GetStdHandle(_winapi.STD_INPUT_HANDLE)
13311347
if p2cread is None:
1332-
stdin_needsclose = True
13331348
p2cread, _ = _winapi.CreatePipe(None, 0)
13341349
p2cread = Handle(p2cread)
13351350
_winapi.CloseHandle(_)
1351+
err_close_fds.append(p2cread)
13361352
elif stdin == PIPE:
1337-
stdin_needsclose = True
13381353
p2cread, p2cwrite = _winapi.CreatePipe(None, 0)
13391354
p2cread, p2cwrite = Handle(p2cread), Handle(p2cwrite)
1355+
err_close_fds.extend((p2cread, p2cwrite))
13401356
elif stdin == DEVNULL:
13411357
p2cread = msvcrt.get_osfhandle(self._get_devnull())
13421358
elif isinstance(stdin, int):
@@ -1349,14 +1365,14 @@ def _get_handles(self, stdin, stdout, stderr):
13491365
if stdout is None:
13501366
c2pwrite = _winapi.GetStdHandle(_winapi.STD_OUTPUT_HANDLE)
13511367
if c2pwrite is None:
1352-
stdout_needsclose = True
13531368
_, c2pwrite = _winapi.CreatePipe(None, 0)
13541369
c2pwrite = Handle(c2pwrite)
13551370
_winapi.CloseHandle(_)
1371+
err_close_fds.append(c2pwrite)
13561372
elif stdout == PIPE:
1357-
stdout_needsclose = True
13581373
c2pread, c2pwrite = _winapi.CreatePipe(None, 0)
13591374
c2pread, c2pwrite = Handle(c2pread), Handle(c2pwrite)
1375+
err_close_fds.extend((c2pread, c2pwrite))
13601376
elif stdout == DEVNULL:
13611377
c2pwrite = msvcrt.get_osfhandle(self._get_devnull())
13621378
elif isinstance(stdout, int):
@@ -1369,14 +1385,14 @@ def _get_handles(self, stdin, stdout, stderr):
13691385
if stderr is None:
13701386
errwrite = _winapi.GetStdHandle(_winapi.STD_ERROR_HANDLE)
13711387
if errwrite is None:
1372-
stderr_needsclose = True
13731388
_, errwrite = _winapi.CreatePipe(None, 0)
13741389
errwrite = Handle(errwrite)
13751390
_winapi.CloseHandle(_)
1391+
err_close_fds.append(errwrite)
13761392
elif stderr == PIPE:
1377-
stderr_needsclose = True
13781393
errread, errwrite = _winapi.CreatePipe(None, 0)
13791394
errread, errwrite = Handle(errread), Handle(errwrite)
1395+
err_close_fds.extend((errread, errwrite))
13801396
elif stderr == STDOUT:
13811397
errwrite = c2pwrite
13821398
elif stderr == DEVNULL:
@@ -1388,27 +1404,6 @@ def _get_handles(self, stdin, stdout, stderr):
13881404
errwrite = msvcrt.get_osfhandle(stderr.fileno())
13891405
errwrite = self._make_inheritable(errwrite)
13901406

1391-
except BaseException:
1392-
to_close = []
1393-
if stdin_needsclose and p2cwrite != -1:
1394-
to_close.append(p2cread)
1395-
to_close.append(p2cwrite)
1396-
if stdout_needsclose and p2cwrite != -1:
1397-
to_close.append(c2pread)
1398-
to_close.append(c2pwrite)
1399-
if stderr_needsclose and errwrite != -1:
1400-
to_close.append(errread)
1401-
to_close.append(errwrite)
1402-
for file in to_close:
1403-
if isinstance(file, Handle):
1404-
file.Close()
1405-
else:
1406-
os.close(file)
1407-
if hasattr(self, "_devnull"):
1408-
os.close(self._devnull)
1409-
del self._devnull
1410-
raise
1411-
14121407
return (p2cread, p2cwrite,
14131408
c2pread, c2pwrite,
14141409
errread, errwrite)
@@ -1678,13 +1673,14 @@ def _get_handles(self, stdin, stdout, stderr):
16781673
c2pread, c2pwrite = -1, -1
16791674
errread, errwrite = -1, -1
16801675

1681-
try:
1676+
with self._on_error_fd_closer() as err_close_fds:
16821677
if stdin is None:
16831678
pass
16841679
elif stdin == PIPE:
16851680
p2cread, p2cwrite = os.pipe()
16861681
if self.pipesize > 0 and hasattr(fcntl, "F_SETPIPE_SZ"):
16871682
fcntl.fcntl(p2cwrite, fcntl.F_SETPIPE_SZ, self.pipesize)
1683+
err_close_fds.extend((p2cread, p2cwrite))
16881684
elif stdin == DEVNULL:
16891685
p2cread = self._get_devnull()
16901686
elif isinstance(stdin, int):
@@ -1699,6 +1695,7 @@ def _get_handles(self, stdin, stdout, stderr):
16991695
c2pread, c2pwrite = os.pipe()
17001696
if self.pipesize > 0 and hasattr(fcntl, "F_SETPIPE_SZ"):
17011697
fcntl.fcntl(c2pwrite, fcntl.F_SETPIPE_SZ, self.pipesize)
1698+
err_close_fds.extend((c2pread, c2pwrite))
17021699
elif stdout == DEVNULL:
17031700
c2pwrite = self._get_devnull()
17041701
elif isinstance(stdout, int):
@@ -1713,6 +1710,7 @@ def _get_handles(self, stdin, stdout, stderr):
17131710
errread, errwrite = os.pipe()
17141711
if self.pipesize > 0 and hasattr(fcntl, "F_SETPIPE_SZ"):
17151712
fcntl.fcntl(errwrite, fcntl.F_SETPIPE_SZ, self.pipesize)
1713+
err_close_fds.extend((errread, errwrite))
17161714
elif stderr == STDOUT:
17171715
if c2pwrite != -1:
17181716
errwrite = c2pwrite
@@ -1726,22 +1724,6 @@ def _get_handles(self, stdin, stdout, stderr):
17261724
# Assuming file-like object
17271725
errwrite = stderr.fileno()
17281726

1729-
except BaseException:
1730-
# Close the file descriptors we opened to avoid leakage
1731-
if stdin == PIPE and p2cwrite != -1:
1732-
os.close(p2cread)
1733-
os.close(p2cwrite)
1734-
if stdout == PIPE and c2pwrite != -1:
1735-
os.close(c2pread)
1736-
os.close(c2pwrite)
1737-
if stderr == PIPE and errwrite != -1:
1738-
os.close(errread)
1739-
os.close(errwrite)
1740-
if hasattr(self, "_devnull"):
1741-
os.close(self._devnull)
1742-
del self._devnull
1743-
raise
1744-
17451727
return (p2cread, p2cwrite,
17461728
c2pread, c2pwrite,
17471729
errread, errwrite)

0 commit comments

Comments
 (0)