Merged from trunk -r13305:13313
authorFabian Groffen <grobian@gentoo.org>
Sat, 11 Apr 2009 11:40:10 +0000 (11:40 -0000)
committerFabian Groffen <grobian@gentoo.org>
Sat, 11 Apr 2009 11:40:10 +0000 (11:40 -0000)
   | 13306   | Bug #264435 - Handle EAGAIN errors when writing to stdout,   |
   | zmedico | due to poorly behaved subprocesses that set O_NONBLOCK mode  |
   |         | on inherited file descriptors. TODO: When possible, avoid    |
   |         | having child processes inherit stdio file descriptors from   |
   |         | portage (maybe it can't be avoided with                      |
   |         | PROPERTIES=interactive).                                     |

   | 13307   | Initialize self._trg_cache.ec inside the GenCache            |
   | zmedico | constructor.                                                 |

   | 13308   | Remove --nocolor since it's been replaced by --color=n and   |
   | zmedico | the support code no longer exists.                           |

   | 13309   | Fix typo in docstring.                                       |
   | zmedico |                                                              |

   | 13310   | In config.setcpv(), don't add empty values to                |
   | zmedico | self.configdict['pkg'] for keys that don't exist in the      |
   |         | given dict.                                                  |

   | 13311   | Use _doebuild_exit_status_check() for unsuccessful return    |
   | zmedico | codes (no just successful ones), since we want to be sure to |
   |         | produce an informative warning message whenever the shell    |
   |         | exits unexpectedly (whether it's successful or               |
   |         | unsuccessful). This is important since it can be makes these |
   |         | kinds of issues easier to diagnose (otherwise the user might |
   |         | blame portage, when it's really the ebuild/eclasses that is  |
   |         | at fault).                                                   |

   | 13312   | Bug #265034 - In depgraph.loadResumeCommand(), tolerate      |
   | zmedico | missing packages since it's possible that the resume list is |
   |         | still partially valid.                                       |

   | 13313   | Fix broken logic from previous commit.                       |
   | zmedico |                                                              |

svn path=/main/branches/prefix/; revision=13321

bin/egencache
pym/_emerge/__init__.py
pym/portage/__init__.py
pym/portage/eclass_cache.py

index 47e4ea2c7b627129ba76f5e4d3cf7d288cef4c7f..89708ad71fc5698fd97707a8739e516fba178713 100755 (executable)
@@ -133,6 +133,11 @@ class GenCache(object):
                        "metadata/cache", portage.auxdbkeys[:])
                if rsync:
                        self._trg_cache.raise_stat_collision = True
+               try:
+                       self._trg_cache.ec = \
+                               portdb._repo_info[portdb.porttrees[0]].eclass_db
+               except AttributeError:
+                       pass
                self._existing_nodes = set()
 
        def _metadata_callback(self, cpv, ebuild_path, repo_path, metadata):
index f889ed0b0d757c00e52f103749c36cd8f2bfa40c..3afe96d022a80de4ce064268a506ccc81671698a 100644 (file)
@@ -217,7 +217,7 @@ options=[
 "--help",         "--ignore-default-opts",
 "--keep-going",
 "--noconfmem",
-"--newuse",       "--nocolor",
+"--newuse",
 "--nodeps",       "--noreplace",
 "--nospinner",    "--oneshot",
 "--onlydeps",     "--pretend",
@@ -2453,8 +2453,41 @@ class SpawnProcess(SubProcess):
 
                        if buf:
                                if not self.background:
-                                       buf.tofile(files.stdout)
-                                       files.stdout.flush()
+                                       write_successful = False
+                                       failures = 0
+                                       while True:
+                                               try:
+                                                       if not write_successful:
+                                                               buf.tofile(files.stdout)
+                                                               write_successful = True
+                                                       files.stdout.flush()
+                                                       break
+                                               except IOError, e:
+                                                       if e.errno != errno.EAGAIN:
+                                                               raise
+                                                       del e
+                                                       failures += 1
+                                                       if failures > 50:
+                                                               # Avoid a potentially infinite loop. In
+                                                               # most cases, the failure count is zero
+                                                               # and it's unlikely to exceed 1.
+                                                               raise
+
+                                                       # This means that a subprocess has put an inherited
+                                                       # stdio file descriptor (typically stdin) into
+                                                       # O_NONBLOCK mode. This is not acceptable (see bug
+                                                       # #264435), so revert it. We need to use a loop
+                                                       # here since there's a race condition due to
+                                                       # parallel processes being able to change the
+                                                       # flags on the inherited file descriptor.
+                                                       # TODO: When possible, avoid having child processes
+                                                       # 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.F_GETFL) ^ os.O_NONBLOCK)
+
                                buf.tofile(files.log)
                                files.log.flush()
                        else:
@@ -8757,7 +8790,8 @@ class depgraph(object):
                if world_locked:
                        world_set.unlock()
 
-       def loadResumeCommand(self, resume_data, skip_masked=False):
+       def loadResumeCommand(self, resume_data, skip_masked=True,
+               skip_missing=True):
                """
                Add a resume command to the graph and validate it in the process.  This
                will raise a PackageNotFound exception if a package is not available.
@@ -8792,6 +8826,9 @@ class depgraph(object):
                                # It does no exist or it is corrupt.
                                if action == "uninstall":
                                        continue
+                               if skip_missing:
+                                       # TODO: log these somewhere
+                                       continue
                                raise portage.exception.PackageNotFound(pkg_key)
                        installed = action == "uninstall"
                        built = pkg_type != "ebuild"
index 0e0cefb1b0c5d17d504d1a5f152831a2d849673f..aa90dcade6f2ef974f9408801edb201bc92b77a7 100644 (file)
@@ -2145,7 +2145,9 @@ class config(object):
                if mydb:
                        if not hasattr(mydb, "aux_get"):
                                for k in aux_keys:
-                                       pkg_configdict[k] = mydb.get(k, '')
+                                       v = mydb.get(k)
+                                       if v is not None:
+                                               pkg_configdict[k] = v
                        else:
                                for k, v in izip(aux_keys, mydb.aux_get(self.mycpv, aux_keys)):
                                        pkg_configdict[k] = v
@@ -4771,14 +4773,14 @@ def spawnebuild(mydo, actionmap, mysettings, debug, alwaysdep=0,
        if returnpid:
                return phase_retval
 
-       if phase_retval == os.EX_OK:
-               msg = _doebuild_exit_status_check(mydo, mysettings)
-               if msg:
+       msg = _doebuild_exit_status_check(mydo, mysettings)
+       if msg:
+               if phase_retval == os.EX_OK:
                        phase_retval = 1
-                       from textwrap import wrap
-                       from portage.elog.messages import eerror
-                       for l in wrap(msg, 72):
-                               eerror(l, phase=mydo, key=mysettings.mycpv)
+               from textwrap import wrap
+               from portage.elog.messages import eerror
+               for l in wrap(msg, 72):
+                       eerror(l, phase=mydo, key=mysettings.mycpv)
 
        _post_phase_userpriv_perms(mysettings)
        if mydo == "install":
@@ -5051,14 +5053,16 @@ def _spawn_misc_sh(mysettings, commands, **kwargs):
                        logfile=logfile, **kwargs)
        finally:
                pass
-       if rval == os.EX_OK:
-               msg = _doebuild_exit_status_check(mydo, mysettings)
-               if msg:
+
+       msg = _doebuild_exit_status_check(mydo, mysettings)
+       if msg:
+               if rval == os.EX_OK:
                        rval = 1
-                       from textwrap import wrap
-                       from portage.elog.messages import eerror
-                       for l in wrap(msg, 72):
-                               eerror(l, phase=mydo, key=mysettings.mycpv)
+               from textwrap import wrap
+               from portage.elog.messages import eerror
+               for l in wrap(msg, 72):
+                       eerror(l, phase=mydo, key=mysettings.mycpv)
+
        return rval
 
 _testing_eapis = frozenset(["3_pre1"])
@@ -5612,11 +5616,10 @@ def _doebuild_exit_status_check(mydo, settings):
        return msg
 
 def _doebuild_exit_status_check_and_log(settings, mydo, retval):
-       if retval != os.EX_OK:
-               return retval
        msg = _doebuild_exit_status_check(mydo, settings)
        if msg:
-               retval = 1
+               if retval == os.EX_OK:
+                       retval = 1
                from textwrap import wrap
                from portage.elog.messages import eerror
                for l in wrap(msg, 72):
@@ -5844,11 +5847,10 @@ def doebuild(myebuild, mydo, myroot, mysettings, debug=0, listonly=0,
                        _doebuild_manifest_cache = mf
 
        def exit_status_check(retval):
-               if retval != os.EX_OK:
-                       return retval
                msg = _doebuild_exit_status_check(mydo, mysettings)
                if msg:
-                       retval = 1
+                       if retval == os.EX_OK:
+                               retval = 1
                        from textwrap import wrap
                        from portage.elog.messages import eerror
                        for l in wrap(msg, 72):
index 15602fc023d2e402e71d5f2c3a935231bea2e17e..8f80ec53e6c39135147123dfe10201806e832b9b 100644 (file)
@@ -48,7 +48,7 @@ class cache(object):
        def append(self, other):
                """
                Append another instance to this instance. This will cause eclasses
-               from the other instance to override and eclases from this instance
+               from the other instance to override any eclasses from this instance
                that have the same name.
                """
                if not isinstance(other, self.__class__):