Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Build loops trying to substitute when output is missing #3964

Closed
roberth opened this issue Aug 26, 2020 · 8 comments · Fixed by #4158
Closed

Build loops trying to substitute when output is missing #3964

roberth opened this issue Aug 26, 2020 · 8 comments · Fixed by #4158
Labels

Comments

@roberth
Copy link
Member

roberth commented Aug 26, 2020

Describe the bug

Suppose we have a derivation with two outputs, out and doc, where out will reference doc.
out is in the cache but doc has been removed.

  1. Something needs out to be valid
  2. out narinfo is fetched. out depends on doc
  3. doc narinfo is fetched; is missing
  4. doc needs to be built. Build the drv
  5. drv may be substitutable, let's fetch out. go to 2, infinitely

So the false "assumption" seems to be that a path dependency implies a derivation dependency, whereas it could be the same derivation.

Steps To Reproduce

$ nix copy $(nix-build channel:nixos-unstable -A nix --no-out-link) --to file://$HOME/tmp/nixcache-2020-08-26
$ nix-store -q --references $(nix-build channel:nixos-unstable -A nix --no-out-link)
...
/nix/store/wbj5y36q3si9ipwa0vnnjgvpmbggxibd-nix-2.3.7-man
...
$ rm ~/tmp/nixcache-2020-08-26/wbj5y36q3si9ipwa0vnnjgvpmbggxibd.narinfo
$ nix-store --delete $(nix-store -q --outputs $(nix-instantiate channel:nixos-unstable -A nix))
$ nix-build -vvv channel:nixos-unstable -A nix --option substituters file://$HOME/tmp/nixcache-2020-08-26 --option narinfo-cache-negative-ttl 10

-vvv is the least verbose level that prints from the loop.

Expected behavior

build.cc determines that not all outputs are substitutable and proceeds to build.

(It may still need to build input derivations that by definition of input can not be the same derivation.)

nix-env --version output
nix-env (Nix) 2.3.6

Additional context

Add any other context about the problem here.

@roberth roberth added the bug label Aug 26, 2020
@Ericson2314
Copy link
Member

So I've wanted to shift the division of labor between subtitution and derivation goals: I think we shoul just have substitution and building goals:

  • no more wanted outputs, building goals build all outputs

  • substitution goals fall back on building if cannot substitue

  • building goals don't try to substitute

I beleive that would incidentally solve your problem!

@roberth
Copy link
Member Author

roberth commented Aug 26, 2020

@Ericson2314 that sounds good. So if I understand correctly, after instantiation you'd make substitution goals for all top-level outputs, which will fall back to building as necessary.
When a substitution fails, we'll still need a state for substituting the inputs. So,

building goals don't try to substitute

If I understand correctly, you mean: building goals don't try to substitute their outputs
This will be the responsibility of the code that creates the DerivationGoal.

Is that something you want to implement?

@Ericson2314
Copy link
Member

@roberth Yes I think we're on the same page. I'd love to take a look at implementing it as soon as next week, because it is also good for building derivations that are themselves the outputs of derivations.

@domenkozar
Copy link
Member

Most probably also the cause for #3534

@Ericson2314
Copy link
Member

nix/src/libstore/build.cc

Lines 1204 to 1207 in f156513

/* We are first going to try to create the invalid output paths
through substitutes. If that doesn't work, we'll build
them. */
if (settings.useSubstitutes && parsedDrv->substitutesAllowed())

Ah slight bummer, with the new plan I would still have to read in derivation in the substitution goal to decide whether to immediately fallback on building rather than trying to substitute.

@Ericson2314
Copy link
Member

Ah, better plan: a 3rd goal type. If we have a "plain goal", where we haven't decided whether substitute or build yet, and again get rid of wantedOutputs limiting build goals to just the drv path, we solve this problem and clearly support substitutesAllowed. Yay!

@roberth
Copy link
Member Author

roberth commented Oct 9, 2020

Sounds good! So we'll start with something like RealisationGoal which then produces SubstitutionGoal or BuildGoal.
I do think it makes sense to keep wantedOutputs, so we don't fetch more than necessary from substituters, but of course we can forget wantedOutputs when switching to BuildGoal.

@Ericson2314
Copy link
Member

I do think it makes sense to keep wantedOutputs

My idea was to have a single output per realization goal, so we aren't change the "goal of the goal" in flight.

but of course we can forget wantedOutputs when switching to BuildGoal

And indeed they are cleared already.


Regardless, I took a stab at this yesterday, and it's proved irksome.

For example, see retrySubstitution which currently the derivation goal restart after kicking of inputDrv subgoals to try to repair the substitution closure. I kept on imaging fancier and fancier refactors in my head, such separating derivation goals which just load a derivation from the new RealisationGoal and BuildGoal giving us 4 goal types total

I think I'd want to definitely talk more about what we want --- perhaps in real time at the hackathon? --- to try to come up with a design we all pre-agree upon. (And through in the other stuff I mention in #4114 (comment) and the scale of the endeavor just goes up further.)

roberth added a commit to hercules-ci/nix that referenced this issue Oct 18, 2020
roberth added a commit to hercules-ci/nix that referenced this issue Oct 18, 2020
edolstra added a commit that referenced this issue Oct 18, 2020
roberth added a commit to hercules-ci/nix that referenced this issue Dec 22, 2020
(cherry picked from commit ea8d320)
roberth added a commit to hercules-ci/nix that referenced this issue Dec 22, 2020
(cherry picked from commit ea8d320)
roberth added a commit to hercules-ci/nix that referenced this issue Dec 22, 2020
This reverts commit e90530e.

It appears that this backported test relies on new functionality.

The error is:

    + nix copy --to file:///build/nix-test/binary-cache /build/nix-test/store/dckdy2xp7sn8qvyx8axxjq7clnxddri1-multi-output
    warning: you don't have Internet access; disabling some network-dependent features
    error: uploading to 'file:///build/nix-test/binary-cache/nar/0hpfhrig9h6fvbjmiwsb7zkaxr19vr2w048y4xb3nrs36bagf92n.nar.xz' is not supported
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants