From: Fabian Groffen Date: Sat, 11 Apr 2009 11:40:10 +0000 (-0000) Subject: Merged from trunk -r13305:13313 X-Git-Url: http://git.tremily.us/gitweb.cgi?a=commitdiff_plain;h=038498b0a227bb0050046bfec6ae296c6487ca4a;p=portage.git Merged from trunk -r13305:13313 | 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 --- diff --git a/bin/egencache b/bin/egencache index 47e4ea2c7..89708ad71 100755 --- a/bin/egencache +++ b/bin/egencache @@ -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): diff --git a/pym/_emerge/__init__.py b/pym/_emerge/__init__.py index f889ed0b0..3afe96d02 100644 --- a/pym/_emerge/__init__.py +++ b/pym/_emerge/__init__.py @@ -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" diff --git a/pym/portage/__init__.py b/pym/portage/__init__.py index 0e0cefb1b..aa90dcade 100644 --- a/pym/portage/__init__.py +++ b/pym/portage/__init__.py @@ -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): diff --git a/pym/portage/eclass_cache.py b/pym/portage/eclass_cache.py index 15602fc02..8f80ec53e 100644 --- a/pym/portage/eclass_cache.py +++ b/pym/portage/eclass_cache.py @@ -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__):