diff options
author | Todd Gamblin <tgamblin@llnl.gov> | 2021-01-04 01:28:16 -0800 |
---|---|---|
committer | Tamara Dahlgren <dahlgren1@llnl.gov> | 2021-02-17 17:07:35 -0800 |
commit | 56acb5a0c7e504f4262b05610d826821ca4dea52 (patch) | |
tree | 110573103b8e26122b107579ab093c4215b5680c /lib | |
parent | ec42016241588075cdcac12e8a3d6011c536af8a (diff) | |
download | spack-56acb5a0c7e504f4262b05610d826821ca4dea52.tar.gz spack-56acb5a0c7e504f4262b05610d826821ca4dea52.tar.bz2 spack-56acb5a0c7e504f4262b05610d826821ca4dea52.tar.xz spack-56acb5a0c7e504f4262b05610d826821ca4dea52.zip |
bugfix: infinite loop when building a set from incomplete specs (#20649)
This code in `SpecBuilder.build_specs()` introduced in #20203, can loop
seemingly interminably for very large specs:
```python
set([spec.root for spec in self._specs.values()])
```
It's deceptive, because it seems like there must be an issue with
`spec.root`, but that works fine. It's building the set afterwards that
takes forever, at least on `r-rminer`. Currently if you try running
`spack solve r-rminer`, it loops infinitely and spins up your fan.
The issue (I think) is that the spec is not yet complete when this is
run, and something is going wrong when constructing and comparing so many
values produced by `_cmp_key()`. We can investigate the efficiency of
`_cmp_key()` separately, but for now, the fix is:
```python
roots = [spec.root for spec in self._specs.values()]
roots = dict((id(r), r) for r in roots)
```
We know the specs in `self._specs` are distinct (they just came out of
the solver), so we can just use their `id()` to unique them here. This
gets rid of the infinite loop.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/spack/spack/solver/asp.py | 7 |
1 files changed, 6 insertions, 1 deletions
diff --git a/lib/spack/spack/solver/asp.py b/lib/spack/spack/solver/asp.py index 47331a3629..a4e55715ed 100644 --- a/lib/spack/spack/solver/asp.py +++ b/lib/spack/spack/solver/asp.py @@ -1602,7 +1602,12 @@ class SpecBuilder(object): # fix flags after all specs are constructed self.reorder_flags() - for root in set([spec.root for spec in self._specs.values()]): + # inject patches -- note that we' can't use set() to unique the + # roots here, because the specs aren't complete, and the hash + # function will loop forever. + roots = [spec.root for spec in self._specs.values()] + roots = dict((id(r), r) for r in roots) + for root in roots.values(): spack.spec.Spec.inject_patches_variant(root) # Add external paths to specs with just external modules |