summaryrefslogtreecommitdiffstats
path: root/pym
diff options
context:
space:
mode:
authorZac Medico <zmedico@gentoo.org>2008-07-04 03:03:44 +0000
committerZac Medico <zmedico@gentoo.org>2008-07-04 03:03:44 +0000
commit9845d081c30352f7d5246ae79f372373b3b0d76a (patch)
treee2187cb154747eaf84f12e323f7d7878fc5a0a69 /pym
parente97b8f08b2ebcded360ea1d9c11420e7d931234b (diff)
downloadportage-9845d081c30352f7d5246ae79f372373b3b0d76a.tar.gz
portage-9845d081c30352f7d5246ae79f372373b3b0d76a.tar.bz2
portage-9845d081c30352f7d5246ae79f372373b3b0d76a.zip
When logging is disabled, make the EbuildPhase create a dummy pipe to provide
a file descriptor that the scheduler can use to monitor the process from inside a poll() loop. svn path=/main/trunk/; revision=10920
Diffstat (limited to 'pym')
-rw-r--r--pym/_emerge/__init__.py51
1 files changed, 45 insertions, 6 deletions
diff --git a/pym/_emerge/__init__.py b/pym/_emerge/__init__.py
index 25cbc3bb5..b02d347bc 100644
--- a/pym/_emerge/__init__.py
+++ b/pym/_emerge/__init__.py
@@ -1881,6 +1881,11 @@ class EbuildPhase(SubProcess):
_files_dict = slot_dict_class(_file_names, prefix="")
_bufsize = 4096
+ # A file descriptor is required for the scheduler to monitor changes from
+ # inside a poll() loop. When logging is not enabled, create a pipe just to
+ # serve this purpose alone.
+ _dummy_pipe_fd = 9
+
def start(self):
root_config = self.pkg.root_config
tree = self.tree
@@ -1931,7 +1936,6 @@ class EbuildPhase(SubProcess):
mode[1] &= ~termios.OPOST
termios.tcsetattr(slave_fd, termios.TCSANOW, mode)
- import fcntl
fcntl.fcntl(master_fd, fcntl.F_SETFL,
fcntl.fcntl(master_fd, fcntl.F_GETFL) | os.O_NONBLOCK)
@@ -1945,6 +1949,17 @@ class EbuildPhase(SubProcess):
fd_pipes[1] = slave_fd
fd_pipes[2] = slave_fd
+ else:
+ # Create a dummy pipe so the scheduler can monitor
+ # the process from inside a poll() loop.
+ master_fd, slave_fd = os.pipe()
+ fcntl.fcntl(master_fd, fcntl.F_SETFL,
+ fcntl.fcntl(master_fd, fcntl.F_GETFL) | os.O_NONBLOCK)
+ fd_pipes.setdefault(0, sys.stdin.fileno())
+ fd_pipes.setdefault(1, sys.stdout.fileno())
+ fd_pipes.setdefault(2, sys.stderr.fileno())
+ fd_pipes[self._dummy_pipe_fd] = slave_fd
+
retval = portage.doebuild(ebuild_path, self.phase,
root_config.root, settings, debug,
mydbapi=mydbapi, tree=tree,
@@ -1953,13 +1968,16 @@ class EbuildPhase(SubProcess):
self.pid = retval[0]
if logfile:
- os.close(slave_fd)
files.log = open(logfile, 'a')
files.stdout = os.fdopen(os.dup(fd_pipes_orig[1]), 'w')
- files.ebuild = os.fdopen(master_fd, 'r')
- self.registered = True
- self.register(files.ebuild.fileno(),
- select.POLLIN, self._output_handler)
+ output_handler = self._output_handler
+ else:
+ output_handler = self._dummy_handler
+
+ os.close(slave_fd)
+ files.ebuild = os.fdopen(master_fd, 'r')
+ self.registered = True
+ self.register(files.ebuild.fileno(), select.POLLIN, output_handler)
def _output_handler(self, fd, event):
files = self.files
@@ -1980,6 +1998,27 @@ class EbuildPhase(SubProcess):
self.registered = False
self.unregister(fd)
+ def _dummy_handler(self, fd, event):
+ """
+ This method is mainly interested in detecting EOF, since
+ the only purpose of the pipe is to allow the scheduler to
+ monitor the process from inside a poll() loop.
+ """
+ files = self.files
+ buf = array.array('B')
+ try:
+ buf.fromfile(files.ebuild, self._bufsize)
+ except EOFError:
+ pass
+ if buf:
+ pass
+ else:
+ fd = files.ebuild.fileno()
+ for f in files.values():
+ f.close()
+ self.registered = False
+ self.unregister(fd)
+
def _set_returncode(self, wait_retval):
SubProcess._set_returncode(self, wait_retval)
msg = portage._doebuild_exit_status_check(