aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'portage_with_autodep/pym/_emerge/SpawnProcess.py')
-rw-r--r--portage_with_autodep/pym/_emerge/SpawnProcess.py107
1 files changed, 60 insertions, 47 deletions
diff --git a/portage_with_autodep/pym/_emerge/SpawnProcess.py b/portage_with_autodep/pym/_emerge/SpawnProcess.py
index b72971c..9fbc964 100644
--- a/portage_with_autodep/pym/_emerge/SpawnProcess.py
+++ b/portage_with_autodep/pym/_emerge/SpawnProcess.py
@@ -26,29 +26,16 @@ class SpawnProcess(SubProcess):
"path_lookup", "pre_exec")
__slots__ = ("args",) + \
- _spawn_kwarg_names + ("_selinux_type",)
+ _spawn_kwarg_names + ("_log_file_real", "_selinux_type",)
_file_names = ("log", "process", "stdout")
_files_dict = slot_dict_class(_file_names, prefix="")
def _start(self):
- if self.cancelled:
- return
-
if self.fd_pipes is None:
self.fd_pipes = {}
fd_pipes = self.fd_pipes
- fd_pipes.setdefault(0, sys.stdin.fileno())
- fd_pipes.setdefault(1, sys.stdout.fileno())
- fd_pipes.setdefault(2, sys.stderr.fileno())
-
- # flush any pending output
- for fd in fd_pipes.values():
- if fd == sys.stdout.fileno():
- sys.stdout.flush()
- if fd == sys.stderr.fileno():
- sys.stderr.flush()
self._files = self._files_dict()
files = self._files
@@ -56,34 +43,46 @@ class SpawnProcess(SubProcess):
master_fd, slave_fd = self._pipe(fd_pipes)
fcntl.fcntl(master_fd, fcntl.F_SETFL,
fcntl.fcntl(master_fd, fcntl.F_GETFL) | os.O_NONBLOCK)
+ files.process = master_fd
logfile = None
if self._can_log(slave_fd):
logfile = self.logfile
null_input = None
- fd_pipes_orig = fd_pipes.copy()
- if self.background:
+ if not self.background or 0 in fd_pipes:
+ # Subclasses such as AbstractEbuildProcess may have already passed
+ # in a null file descriptor in fd_pipes, so use that when given.
+ pass
+ else:
# TODO: Use job control functions like tcsetpgrp() to control
# access to stdin. Until then, use /dev/null so that any
# attempts to read from stdin will immediately return EOF
# instead of blocking indefinitely.
- null_input = open('/dev/null', 'rb')
- fd_pipes[0] = null_input.fileno()
- else:
- fd_pipes[0] = fd_pipes_orig[0]
+ null_input = os.open('/dev/null', os.O_RDWR)
+ fd_pipes[0] = null_input
+
+ fd_pipes.setdefault(0, sys.stdin.fileno())
+ fd_pipes.setdefault(1, sys.stdout.fileno())
+ fd_pipes.setdefault(2, sys.stderr.fileno())
+
+ # flush any pending output
+ for fd in fd_pipes.values():
+ if fd == sys.stdout.fileno():
+ sys.stdout.flush()
+ if fd == sys.stderr.fileno():
+ sys.stderr.flush()
- # WARNING: It is very important to use unbuffered mode here,
- # in order to avoid issue 5380 with python3.
- files.process = os.fdopen(master_fd, 'rb', 0)
if logfile is not None:
+ fd_pipes_orig = fd_pipes.copy()
fd_pipes[1] = slave_fd
fd_pipes[2] = slave_fd
files.log = open(_unicode_encode(logfile,
encoding=_encodings['fs'], errors='strict'), mode='ab')
if logfile.endswith('.gz'):
+ self._log_file_real = files.log
files.log = gzip.GzipFile(filename='', mode='ab',
fileobj=files.log)
@@ -92,7 +91,7 @@ class SpawnProcess(SubProcess):
mode=0o660)
if not self.background:
- files.stdout = os.fdopen(os.dup(fd_pipes_orig[1]), 'wb')
+ files.stdout = os.dup(fd_pipes_orig[1])
output_handler = self._output_handler
@@ -116,7 +115,7 @@ class SpawnProcess(SubProcess):
kwargs["returnpid"] = True
kwargs.pop("logfile", None)
- self._reg_id = self.scheduler.register(files.process.fileno(),
+ self._reg_id = self.scheduler.register(files.process,
self._registered_events, output_handler)
self._registered = True
@@ -124,7 +123,7 @@ class SpawnProcess(SubProcess):
os.close(slave_fd)
if null_input is not None:
- null_input.close()
+ os.close(null_input)
if isinstance(retval, int):
# spawn failed
@@ -161,22 +160,30 @@ class SpawnProcess(SubProcess):
def _output_handler(self, fd, event):
files = self._files
- buf = self._read_buf(files.process, event)
+ while True:
+ buf = self._read_buf(fd, event)
+
+ if buf is None:
+ # not a POLLIN event, EAGAIN, etc...
+ break
- if buf is not None:
+ if not buf:
+ # EOF
+ self._unregister()
+ self.wait()
+ break
- if buf:
+ else:
if not self.background:
write_successful = False
failures = 0
while True:
try:
if not write_successful:
- buf.tofile(files.stdout)
+ os.write(files.stdout, buf)
write_successful = True
- files.stdout.flush()
break
- except IOError as e:
+ except OSError as e:
if e.errno != errno.EAGAIN:
raise
del e
@@ -198,22 +205,17 @@ class SpawnProcess(SubProcess):
# inherit stdio file descriptors from portage
# (maybe it can't be avoided with
# PROPERTIES=interactive).
- fcntl.fcntl(files.stdout.fileno(), fcntl.F_SETFL,
- fcntl.fcntl(files.stdout.fileno(),
+ fcntl.fcntl(files.stdout, fcntl.F_SETFL,
+ fcntl.fcntl(files.stdout,
fcntl.F_GETFL) ^ os.O_NONBLOCK)
- try:
- buf.tofile(files.log)
- except TypeError:
- # array.tofile() doesn't work with GzipFile
- files.log.write(buf.tostring())
+ files.log.write(buf)
files.log.flush()
- else:
- self._unregister()
- self.wait()
self._unregister_if_appropriate(event)
+ return True
+
def _dummy_handler(self, fd, event):
"""
This method is mainly interested in detecting EOF, since
@@ -221,15 +223,26 @@ class SpawnProcess(SubProcess):
monitor the process from inside a poll() loop.
"""
- buf = self._read_buf(self._files.process, event)
+ while True:
+ buf = self._read_buf(fd, event)
- if buf is not None:
+ if buf is None:
+ # not a POLLIN event, EAGAIN, etc...
+ break
- if buf:
- pass
- else:
+ if not buf:
+ # EOF
self._unregister()
self.wait()
+ break
self._unregister_if_appropriate(event)
+ return True
+
+ def _unregister(self):
+ super(SpawnProcess, self)._unregister()
+ if self._log_file_real is not None:
+ # Avoid "ResourceWarning: unclosed file" since python 3.2.
+ self._log_file_real.close()
+ self._log_file_real = None