Bug 1627163 - Avoid scanning ConfigureSandbox._implied_options when handling implied options. r=firefox-build-system-reviewers,rstewart

ConfigureSandbox._implied_options is a list of ReadOnlyNamespaces.
In python 3.5, ReadOnlyNamespaces end up with no guarantee in the order
of their __dict__. So when comparing

   ReadOnlyNamespace(a=1, b=2)

and

   ReadOnlyNamespace(a=3, b=4)

It's not guaranteed that the a's are compared before the b's.

In ConfigureSandbox._implied_options, some of those ReadOnlyNamespace
fields are SandboxDependsFunctions, which actually raise an error when
they're being compared, because we don't want that to happen in the
sandbox.

So when using python 3, configure would randomly fail when trying to
remove items from the ConfigureSandbox._implied_options list because
removing an item from a list scans the list to find the first element
that matches.

And ConfigureSandbox._implied_options needs to be ordered, which is why
it's currently a list.

So instead of removing by value, we create a new list with the remaining
values. But because the loop recurses, and needs the updated list, we
filter first.

Differential Revision: https://phabricator.services.mozilla.com/D69535

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Mike Hommey 2020-04-07 15:38:29 +00:00
Родитель 6de3ea1964
Коммит 6f5d58ae41
1 изменённых файлов: 9 добавлений и 4 удалений

Просмотреть файл

@ -555,11 +555,16 @@ class ConfigureSandbox(dict):
@memoize
def _value_for_option(self, option):
implied = {}
for implied_option in self._implied_options[:]:
if implied_option.name not in (option.name, option.env):
continue
self._implied_options.remove(implied_option)
matching_implied_options = [
o for o in self._implied_options if o.name in (option.name, option.env)
]
# Update self._implied_options before going into the loop with the non-matching
# options.
self._implied_options = [
o for o in self._implied_options if o.name not in (option.name, option.env)
]
for implied_option in matching_implied_options:
if (implied_option.when and
not self._value_for(implied_option.when)):
continue