Commit 4ccaf93b authored by Facundo Batista's avatar Facundo Batista

Issue #6274. Fixed a potential FD leak in subprocess.py.

parent 2cf40b1c
...@@ -1034,6 +1034,8 @@ class Popen(object): ...@@ -1034,6 +1034,8 @@ class Popen(object):
# The first char specifies the exception type: 0 means # The first char specifies the exception type: 0 means
# OSError, 1 means some other error. # OSError, 1 means some other error.
errpipe_read, errpipe_write = os.pipe() errpipe_read, errpipe_write = os.pipe()
try:
try:
self._set_cloexec_flag(errpipe_write) self._set_cloexec_flag(errpipe_write)
gc_was_enabled = gc.isenabled() gc_was_enabled = gc.isenabled()
...@@ -1067,11 +1069,12 @@ class Popen(object): ...@@ -1067,11 +1069,12 @@ class Popen(object):
if errwrite is not None: if errwrite is not None:
os.dup2(errwrite, 2) os.dup2(errwrite, 2)
# Close pipe fds. Make sure we don't close the same # Close pipe fds. Make sure we don't close the
# fd more than once, or standard fds. # same fd more than once, or standard fds.
if p2cread is not None and p2cread not in (0,): if p2cread is not None and p2cread not in (0,):
os.close(p2cread) os.close(p2cread)
if c2pwrite is not None and c2pwrite not in (p2cread, 1): if c2pwrite is not None and \
c2pwrite not in (p2cread, 1):
os.close(c2pwrite) os.close(c2pwrite)
if (errwrite is not None and if (errwrite is not None and
errwrite not in (p2cread, c2pwrite, 2)): errwrite not in (p2cread, c2pwrite, 2)):
...@@ -1094,21 +1097,25 @@ class Popen(object): ...@@ -1094,21 +1097,25 @@ class Popen(object):
except: except:
exc_type, exc_value, tb = sys.exc_info() exc_type, exc_value, tb = sys.exc_info()
# Save the traceback and attach it to the exception object # Save the traceback and attach it to the exception
# object
exc_lines = traceback.format_exception(exc_type, exc_lines = traceback.format_exception(exc_type,
exc_value, exc_value,
tb) tb)
exc_value.child_traceback = ''.join(exc_lines) exc_value.child_traceback = ''.join(exc_lines)
os.write(errpipe_write, pickle.dumps(exc_value)) os.write(errpipe_write, pickle.dumps(exc_value))
# This exitcode won't be reported to applications, so it # This exitcode won't be reported to applications, so
# really doesn't matter what we return. # it really doesn't matter what we return.
os._exit(255) os._exit(255)
# Parent # Parent
if gc_was_enabled: if gc_was_enabled:
gc.enable() gc.enable()
finally:
# be sure the FD is closed no matter what
os.close(errpipe_write) os.close(errpipe_write)
if p2cread is not None and p2cwrite is not None: if p2cread is not None and p2cwrite is not None:
os.close(p2cread) os.close(p2cread)
if c2pwrite is not None and c2pread is not None: if c2pwrite is not None and c2pread is not None:
...@@ -1116,9 +1123,13 @@ class Popen(object): ...@@ -1116,9 +1123,13 @@ class Popen(object):
if errwrite is not None and errread is not None: if errwrite is not None and errread is not None:
os.close(errwrite) os.close(errwrite)
# Wait for exec to fail or succeed; possibly raising exception # Wait for exec to fail or succeed; possibly raising an
data = os.read(errpipe_read, 1048576) # Exceptions limited to 1 MB # exception (limited to 1 MB)
data = os.read(errpipe_read, 1048576)
finally:
# be sure the FD is closed no matter what
os.close(errpipe_read) os.close(errpipe_read)
if data: if data:
os.waitpid(self.pid, 0) os.waitpid(self.pid, 0)
child_exception = pickle.loads(data) child_exception = pickle.loads(data)
......
...@@ -15,6 +15,8 @@ Core and Builtins ...@@ -15,6 +15,8 @@ Core and Builtins
Library Library
------- -------
- Issue #6274: Fixed possible file descriptors leak in subprocess.py
- Accessing io.StringIO.buffer now raises an AttributeError instead of - Accessing io.StringIO.buffer now raises an AttributeError instead of
io.UnsupportedOperation. io.UnsupportedOperation.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment