Commit ffd10321 authored by Denis Bilenko's avatar Denis Bilenko

subprocess: pull in a few fixes from Python 2.7.3

parent f17ecc85
......@@ -504,7 +504,7 @@ class Popen(object):
if stdin is None:
pass
elif stdin == PIPE:
p2cread, p2cwrite = os.pipe()
p2cread, p2cwrite = self.pipe_cloexec()
elif isinstance(stdin, int):
p2cread = stdin
else:
......@@ -514,7 +514,7 @@ class Popen(object):
if stdout is None:
pass
elif stdout == PIPE:
c2pread, c2pwrite = os.pipe()
c2pread, c2pwrite = self.pipe_cloexec()
elif isinstance(stdout, int):
c2pwrite = stdout
else:
......@@ -524,7 +524,7 @@ class Popen(object):
if stderr is None:
pass
elif stderr == PIPE:
errread, errwrite = os.pipe()
errread, errwrite = self.pipe_cloexec()
elif stderr == STDOUT:
errwrite = c2pwrite
elif isinstance(stderr, int):
......@@ -549,6 +549,17 @@ class Popen(object):
else:
fcntl.fcntl(fd, fcntl.F_SETFD, old & ~cloexec_flag)
def pipe_cloexec(self):
"""Create a pipe with FDs set CLOEXEC."""
# Pipes' FDs are set CLOEXEC by default because we don't want them
# to be inherited by other subprocesses: the CLOEXEC flag is removed
# from the child's FDs by _dup2(), between fork() and exec().
# This is not atomic: we would need the pipe2() syscall for that.
r, w = os.pipe()
self._set_cloexec_flag(r)
self._set_cloexec_flag(w)
return r, w
def _close_fds(self, but):
if hasattr(os, 'closerange'):
os.closerange(3, but)
......@@ -586,11 +597,9 @@ class Popen(object):
# For transferring possible exec failure from child to parent
# The first char specifies the exception type: 0 means
# OSError, 1 means some other error.
errpipe_read, errpipe_write = os.pipe()
errpipe_read, errpipe_write = self.pipe_cloexec()
try:
try:
self._set_cloexec_flag(errpipe_write)
gc_was_enabled = gc.isenabled()
# Disable gc to avoid bug where gc -> file_dealloc ->
# write to stderr -> hang. http://bugs.python.org/issue1336
......@@ -613,6 +622,14 @@ class Popen(object):
os.close(errread)
os.close(errpipe_read)
# When duping fds, if there arises a situation
# where one of the fds is either 0, 1 or 2, it
# is possible that it is overwritten (#12607).
if c2pwrite == 0:
c2pwrite = os.dup(c2pwrite)
if errwrite == 0 or errwrite == 1:
errwrite = os.dup(errwrite)
# Dup fds for child
def _dup2(a, b):
# dup2() removes the CLOEXEC flag but
......
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