Index: pym/portage/dbapi/_MergeProcess.py |
diff --git a/pym/portage/dbapi/_MergeProcess.py b/pym/portage/dbapi/_MergeProcess.py |
index f717d12df81b5bc7ca513cafee26afcc5d63daa1..6e63f84fda3c78d4eec64b5820d17b3878478781 100644 |
--- a/pym/portage/dbapi/_MergeProcess.py |
+++ b/pym/portage/dbapi/_MergeProcess.py |
@@ -4,30 +4,72 @@ |
import signal |
import traceback |
+import errno |
+import fcntl |
import portage |
-from portage import os |
+from portage import os, StringIO |
+import portage.elog.messages |
+from _emerge.PollConstants import PollConstants |
from _emerge.SpawnProcess import SpawnProcess |
class MergeProcess(SpawnProcess): |
""" |
- Merge package files in a subprocess, so the Scheduler can run in the |
- main thread while files are moved or copied asynchronously. |
+ Merge packages in a subprocess, so the Scheduler can run in the main |
+ thread while files are moved or copied asynchronously. |
""" |
- __slots__ = ('cfgfiledict', 'conf_mem_file', \ |
- 'destroot', 'dblink', 'srcroot',) |
+ __slots__ = ('dblink', 'mycat', 'mypkg', 'settings', 'treetype', |
+ 'vartree', 'scheduler', 'blockers', 'pkgloc', 'infloc', 'myebuild', |
+ 'mydbapi', 'prev_mtimes', '_elog_reader_fd', '_elog_reg_id', |
+ '_buf') |
- def _spawn(self, args, fd_pipes=None, **kwargs): |
+ def _elog_output_handler(self, fd, event): |
+ output = None |
+ if event & PollConstants.POLLIN: |
+ try: |
+ output = os.read(fd, self._bufsize) |
+ except OSError as e: |
+ if e.errno not in (errno.EAGAIN, errno.EINTR): |
+ raise |
+ if output: |
+ lines = output.split('\n') |
+ if len(lines) == 1: |
+ self._buf += lines[0] |
+ else: |
+ lines[0] = self._buf + lines[0] |
+ self._buf = lines.pop() |
+ out = StringIO() |
+ for line in lines: |
+ funcname, phase, key, msg = line.split(' ', 3) |
+ reporter = getattr(portage.elog.messages, funcname) |
+ reporter(msg, phase=phase, key=key, out=out) |
+ |
+ def _spawn(self, args, fd_pipes, **kwargs): |
""" |
Fork a subprocess, apply local settings, and call |
- dblink._merge_process(). |
+ dblink.merge(). |
""" |
+ files = self._files |
+ elog_reader_fd, elog_writer_fd = os.pipe() |
+ fcntl.fcntl(elog_reader_fd, fcntl.F_SETFL, |
+ fcntl.fcntl(elog_reader_fd, fcntl.F_GETFL) | os.O_NONBLOCK) |
+ mylink = self.dblink(self.mycat, self.mypkg, settings=self.settings, |
+ treetype=self.treetype, vartree=self.vartree, |
+ blockers=self.blockers, scheduler=self.scheduler, |
+ pipe=elog_writer_fd) |
+ fd_pipes[elog_writer_fd] = elog_writer_fd |
+ self._elog_reg_id = self.scheduler.register(elog_reader_fd, |
+ self._registered_events, self._elog_output_handler) |
+ |
pid = os.fork() |
if pid != 0: |
+ self._elog_reader_fd = elog_reader_fd |
+ self._buf = "" |
portage.process.spawned_pids.append(pid) |
return [pid] |
+ os.close(elog_reader_fd) |
portage.process._setup_pipes(fd_pipes) |
# Use default signal handlers since the ones inherited |
@@ -35,18 +77,19 @@ class MergeProcess(SpawnProcess): |
signal.signal(signal.SIGINT, signal.SIG_DFL) |
signal.signal(signal.SIGTERM, signal.SIG_DFL) |
- portage.output.havecolor = self.dblink.settings.get('NOCOLOR') \ |
+ portage.output.havecolor = self.settings.get('NOCOLOR') \ |
not in ('yes', 'true') |
- # In this subprocess we want dblink._display_merge() to use |
+ # In this subprocess we want mylink._display_merge() to use |
# stdout/stderr directly since they are pipes. This behavior |
- # is triggered when dblink._scheduler is None. |
- self.dblink._scheduler = None |
+ # is triggered when mylink._scheduler is None. |
+ mylink._scheduler = None |
rval = 1 |
try: |
- rval = self.dblink._merge_process(self.srcroot, self.destroot, |
- self.cfgfiledict, self.conf_mem_file) |
+ rval = mylink.merge(self.pkgloc, self.infloc, |
+ myebuild=self.myebuild, mydbapi=self.mydbapi, |
+ prev_mtimes=self.prev_mtimes) |
except SystemExit: |
raise |
except: |
@@ -55,3 +98,16 @@ class MergeProcess(SpawnProcess): |
# Call os._exit() from finally block, in order to suppress any |
# finally blocks from earlier in the call stack. See bug #345289. |
os._exit(rval) |
+ |
+ def _unregister(self): |
+ """ |
+ Unregister from the scheduler and close open files. |
+ """ |
+ if self._elog_reg_id is not None: |
+ self.scheduler.unregister(self._elog_reg_id) |
+ self._elog_reg_id = None |
+ if self._elog_reader_fd: |
+ os.close(self._elog_reader_fd) |
+ self._elog_reader_fd = None |
+ |
+ super(MergeProcess, self)._unregister() |