summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--pym/_emerge/__init__.py35
1 files changed, 33 insertions, 2 deletions
diff --git a/pym/_emerge/__init__.py b/pym/_emerge/__init__.py
index af0ecd323..0abb57602 100644
--- a/pym/_emerge/__init__.py
+++ b/pym/_emerge/__init__.py
@@ -4060,8 +4060,36 @@ class MergeTask(object):
self.pkgsettings[root] = portage.config(
clone=trees[root]["vartree"].settings)
self.curval = 0
+ self._spawned_pids = []
def merge(self, mylist, favorites, mtimedb):
+ try:
+ return self._merge(mylist, favorites, mtimedb)
+ finally:
+ if self._spawned_pids:
+ from portage import process
+ process.spawned_pids.extend(self._spawned_pids)
+ self._spawned_pids = []
+
+ def _poll_child_processes(self):
+ """
+ After each merge, collect status from child processes
+ in order to clean up zombies (such as the parallel-fetch
+ process).
+ """
+ spawned_pids = self._spawned_pids
+ if not spawned_pids:
+ return
+ for pid in list(spawned_pids):
+ try:
+ if os.waitpid(pid, os.WNOHANG) == (0, 0):
+ continue
+ except OSError:
+ # This pid has been cleaned up elsewhere.
+ continue
+ spawned_pids.remove(pid)
+
+ def _merge(self, mylist, favorites, mtimedb):
from portage.elog import elog_process
from portage.elog.filtering import filter_mergephases
failed_fetches = []
@@ -4168,8 +4196,10 @@ class MergeTask(object):
fetch_args.append(myopt)
else:
fetch_args.append(myopt +"="+ myarg)
- portage.process.spawn(fetch_args, env=fetch_env,
- fd_pipes=fd_pipes, returnpid=True)
+ self._spawned_pids.extend(
+ portage.process.spawn(
+ fetch_args, env=fetch_env,
+ fd_pipes=fd_pipes, returnpid=True))
logfile.close() # belongs to the spawned process
del fetch_log, logfile, fd_pipes, fetch_env, fetch_args, \
resume_opts
@@ -4504,6 +4534,7 @@ class MergeTask(object):
# due to power failure, SIGKILL, etc...
mtimedb.commit()
self.curval += 1
+ self._poll_child_processes()
if "--pretend" not in self.myopts:
emergelog(xterm_titles, " *** Finished. Cleaning up...")