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

Skip to content

Commit b5461b9

Browse files
committed
Prevent a possible double close of parent pipe fds when the subprocess
exec runs into an error. Prevent a regular multi-close of the /dev/null fd when any of stdin, stdout and stderr was set to DEVNULL.
1 parent 53e5ea7 commit b5461b9

1 file changed

Lines changed: 25 additions & 18 deletions

File tree

Lib/subprocess.py

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -810,6 +810,7 @@ def __init__(self, args, bufsize=-1, executable=None,
810810
if universal_newlines:
811811
self.stderr = io.TextIOWrapper(self.stderr)
812812

813+
self._closed_child_pipe_fds = False
813814
try:
814815
self._execute_child(args, executable, preexec_fn, close_fds,
815816
pass_fds, cwd, env,
@@ -826,19 +827,21 @@ def __init__(self, args, bufsize=-1, executable=None,
826827
except EnvironmentError:
827828
pass # Ignore EBADF or other errors.
828829

829-
# Make sure the child pipes are closed as well.
830-
to_close = []
831-
if stdin == PIPE:
832-
to_close.append(p2cread)
833-
if stdout == PIPE:
834-
to_close.append(c2pwrite)
835-
if stderr == PIPE:
836-
to_close.append(errwrite)
837-
for fd in to_close:
838-
try:
839-
os.close(fd)
840-
except EnvironmentError:
841-
pass
830+
if not self._closed_child_pipe_fds:
831+
to_close = []
832+
if stdin == PIPE:
833+
to_close.append(p2cread)
834+
if stdout == PIPE:
835+
to_close.append(c2pwrite)
836+
if stderr == PIPE:
837+
to_close.append(errwrite)
838+
if hasattr(self, '_devnull'):
839+
to_close.append(self._devnull)
840+
for fd in to_close:
841+
try:
842+
os.close(fd)
843+
except EnvironmentError:
844+
pass
842845

843846
raise
844847

@@ -1383,14 +1386,18 @@ def _execute_child(self, args, executable, preexec_fn, close_fds,
13831386
# be sure the FD is closed no matter what
13841387
os.close(errpipe_write)
13851388

1386-
if p2cread != -1 and p2cwrite != -1:
1389+
# self._devnull is not always defined.
1390+
devnull_fd = getattr(self, '_devnull', None)
1391+
if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd:
13871392
os.close(p2cread)
1388-
if c2pwrite != -1 and c2pread != -1:
1393+
if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd:
13891394
os.close(c2pwrite)
1390-
if errwrite != -1 and errread != -1:
1395+
if errwrite != -1 and errread != -1 and errwrite != devnull_fd:
13911396
os.close(errwrite)
1392-
if hasattr(self, '_devnull'):
1393-
os.close(self._devnull)
1397+
if devnull_fd is not None:
1398+
os.close(devnull_fd)
1399+
# Prevent a double close of these fds from __init__ on error.
1400+
self._closed_child_pipe_fds = True
13941401

13951402
# Wait for exec to fail or succeed; possibly raising an
13961403
# exception (limited in size)

0 commit comments

Comments
 (0)