Bug 1576097 - Deal with config.status breakage more gracefully. r=nalexander
authorMike Hommey <mh+mozilla@glandium.org>
Fri, 23 Aug 2019 22:26:02 +0000
changeset 489690 c4c43bf71488d253bd9035afdff47c5c0d31aa45
parent 489689 5d843f2c8ed9c2c4b3895588a492de3a3e526e5a
child 489691 014630236d2de0057ecc97598243747d6f419701
push id93535
push usermh@glandium.org
push dateFri, 23 Aug 2019 23:44:29 +0000
treeherderautoland@014630236d2d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnalexander
bugs1576097, 1575774, 1575959
milestone70.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1576097 - Deal with config.status breakage more gracefully. r=nalexander As seen in bug 1575774/1575959, things can go badly when config.status doesn't match expectations, especially when most mach commands try to read it, starting with mach clobber, which is supposed to be the one commant to get away from most problems. The idea here is to throw a recognizable exception so that callers can react accordingly. While not obvious from the patch, the result is that running e.g. mach build with a broken config.status will automatically run configure (because the relevant caller actually handles the rethrown exception that way). There are other calls to from_config_status in the mozbuild reader, but that can't be reached before MozbuildObject.config_environment. Differential Revision: https://phabricator.services.mozilla.com/D43214
python/mozbuild/mozbuild/backend/configenvironment.py
python/mozbuild/mozbuild/base.py
--- a/python/mozbuild/mozbuild/backend/configenvironment.py
+++ b/python/mozbuild/mozbuild/backend/configenvironment.py
@@ -18,16 +18,20 @@ from mozbuild.util import (
     FileAvoidWrite,
     memoized_property,
     ReadOnlyDict,
     system_encoding,
 )
 from mozbuild.shellutil import quote as shell_quote
 
 
+class ConfigStatusFailure(Exception):
+    """Error loading config.status"""
+
+
 class BuildConfig(object):
     """Represents the output of configure."""
 
     _CODE_CACHE = {}
 
     def __init__(self):
         self.topsrcdir = None
         self.topobjdir = None
@@ -59,17 +63,20 @@ class BuildConfig(object):
                     compile(source, path, 'exec', dont_inherit=1)
                 )
 
         g = {
             '__builtins__': __builtins__,
             '__file__': path,
         }
         l = {}
-        exec(code_cache[path][1], g, l)
+        try:
+            exec(code_cache[path][1], g, l)
+        except Exception:
+            raise ConfigStatusFailure()
 
         config = BuildConfig()
 
         for name in l['__all__']:
             setattr(config, name, l[name])
 
         return config
 
--- a/python/mozbuild/mozbuild/base.py
+++ b/python/mozbuild/mozbuild/base.py
@@ -19,17 +19,20 @@ from mozfile import which
 from mozversioncontrol import (
     get_repository_from_build_config,
     get_repository_object,
     GitRepository,
     HgRepository,
     InvalidRepoPath,
 )
 
-from .backend.configenvironment import ConfigEnvironment
+from .backend.configenvironment import (
+    ConfigEnvironment,
+    ConfigStatusFailure,
+)
 from .configure import ConfigureSandbox
 from .controller.clobber import Clobberer
 from .mozconfig import (
     MozconfigFindException,
     MozconfigLoadException,
     MozconfigLoader,
 )
 from .pythonutil import find_python3_executable
@@ -331,18 +334,22 @@ class MozbuildObject(ProcessExecutionMix
         if self._config_environment:
             return self._config_environment
 
         config_status = os.path.join(self.topobjdir, 'config.status')
 
         if not os.path.exists(config_status) or not os.path.getsize(config_status):
             raise BuildEnvironmentNotFoundException('config.status not available. Run configure.')
 
-        self._config_environment = \
-            ConfigEnvironment.from_config_status(config_status)
+        try:
+            self._config_environment = \
+                ConfigEnvironment.from_config_status(config_status)
+        except ConfigStatusFailure as e:
+            six.raise_from(BuildEnvironmentNotFoundException(
+                'config.status is outdated or broken. Run configure.'), e)
 
         return self._config_environment
 
     @property
     def defines(self):
         return self.config_environment.defines
 
     @property