From d92712673ba8d169606a1db83224969952f8ac07 Mon Sep 17 00:00:00 2001 From: Jade Lovelace Date: Thu, 27 Jun 2024 22:43:02 -0700 Subject: [PATCH 1/2] store: guess the URL of failing fixed-output derivations This is a shameless layering violation in favour of UX. It falls back trivially to "unknown", so it's purely a UX feature. Diagnostic sample: ``` error: hash mismatch in fixed-output derivation '/nix/store/sjfw324j4533lwnpmr5z4icpb85r63ai-x1.drv': likely URL: https://meow.puppy.forge/puppy.tar.gz specified: sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= got: sha256-a1Qvp3FOOkWpL9kFHgugU1ok5UtRPSu+NwCZKbbaEro= ``` Change-Id: I873eedcf7984ab23f57a6754be00232b5cb5b02c --- doc/manual/rl-next/fod-failure-includes-url.md | 16 ++++++++++++++++ src/libstore/build/local-derivation-goal.cc | 5 ++++- tests/functional/build.sh | 5 +++++ tests/functional/fod-failing.nix | 2 ++ 4 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 doc/manual/rl-next/fod-failure-includes-url.md diff --git a/doc/manual/rl-next/fod-failure-includes-url.md b/doc/manual/rl-next/fod-failure-includes-url.md new file mode 100644 index 000000000..43179aa52 --- /dev/null +++ b/doc/manual/rl-next/fod-failure-includes-url.md @@ -0,0 +1,16 @@ +--- +synopsis: "Hash mismatch diagnostics for fixed-output derivations include the URL" +cls: [1536] +credits: [jade] +category: Improvements +--- + +Now, when building fixed-output derivations, Lix will guess the URL that was used in the derivation using the `url` or `urls` properties in the derivation environment. +This is a layering violation but making these diagnostics tractable when there are multiple instances of the `AAAA` hash is too significant of an improvement to pass it up. + +``` +error: hash mismatch in fixed-output derivation '/nix/store/sjfw324j4533lwnpmr5z4icpb85r63ai-x1.drv': + likely URL: https://meow.puppy.forge/puppy.tar.gz + specified: sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= + got: sha256-a1Qvp3FOOkWpL9kFHgugU1ok5UtRPSu+NwCZKbbaEro= +``` diff --git a/src/libstore/build/local-derivation-goal.cc b/src/libstore/build/local-derivation-goal.cc index 968f669ec..1dd2ad8aa 100644 --- a/src/libstore/build/local-derivation-goal.cc +++ b/src/libstore/build/local-derivation-goal.cc @@ -2546,9 +2546,12 @@ SingleDrvOutputs LocalDerivationGoal::registerOutputs() /* Throw an error after registering the path as valid. */ worker.hashMismatch = true; + // XXX: shameless layering violation hack that makes the hash mismatch error at least not utterly worthless + auto guessedUrl = getOr(drv->env, "urls", getOr(drv->env, "url", "(unknown)")); delayedException = std::make_exception_ptr( - BuildError("hash mismatch in fixed-output derivation '%s':\n specified: %s\n got: %s", + BuildError("hash mismatch in fixed-output derivation '%s':\n likely URL: %s\n specified: %s\n got: %s", worker.store.printStorePath(drvPath), + guessedUrl, wanted.to_string(SRI, true), got.to_string(SRI, true))); } diff --git a/tests/functional/build.sh b/tests/functional/build.sh index 95a20dc6a..a540cf8fd 100644 --- a/tests/functional/build.sh +++ b/tests/functional/build.sh @@ -142,6 +142,8 @@ test "$(<<<"$out" grep -E '^error:' | wc -l)" = 2 <<<"$out" grepQuiet -E "hash mismatch in fixed-output derivation '.*-x1\\.drv'" <<<"$out" grepQuiet -vE "hash mismatch in fixed-output derivation '.*-x3\\.drv'" <<<"$out" grepQuiet -vE "hash mismatch in fixed-output derivation '.*-x2\\.drv'" +<<<"$out" grepQuiet -E "likely URL: https://meow.puppy.forge/puppy.tar.gz" +<<<"$out" grepQuiet -vE "likely URL: https://kitty.forge/cat.tar.gz" <<<"$out" grepQuiet -E "error: build of '.*-x[1-4]\\.drv\\^out', '.*-x[1-4]\\.drv\\^out', '.*-x[1-4]\\.drv\\^out', '.*-x[1-4]\\.drv\\^out' failed" out="$(nix build -f fod-failing.nix -L x1 x2 x3 --keep-going 2>&1)" && status=0 || status=$? @@ -151,6 +153,9 @@ test "$(<<<"$out" grep -E '^error:' | wc -l)" = 4 <<<"$out" grepQuiet -E "hash mismatch in fixed-output derivation '.*-x1\\.drv'" <<<"$out" grepQuiet -E "hash mismatch in fixed-output derivation '.*-x3\\.drv'" <<<"$out" grepQuiet -E "hash mismatch in fixed-output derivation '.*-x2\\.drv'" +<<<"$out" grepQuiet -E "likely URL: https://meow.puppy.forge/puppy.tar.gz" +<<<"$out" grepQuiet -E "likely URL: https://kitty.forge/cat.tar.gz" +<<<"$out" grepQuiet -E "likely URL: \(unknown\)" <<<"$out" grepQuiet -E "error: build of '.*-x[1-3]\\.drv\\^out', '.*-x[1-3]\\.drv\\^out', '.*-x[1-3]\\.drv\\^out' failed" out="$(nix build -f fod-failing.nix -L x4 2>&1)" && status=0 || status=$? diff --git a/tests/functional/fod-failing.nix b/tests/functional/fod-failing.nix index 37c04fe12..b63fbd900 100644 --- a/tests/functional/fod-failing.nix +++ b/tests/functional/fod-failing.nix @@ -6,6 +6,7 @@ rec { '' echo $name > $out ''; + url = "https://meow.puppy.forge/puppy.tar.gz"; outputHashMode = "recursive"; outputHash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="; }; @@ -15,6 +16,7 @@ rec { '' echo $name > $out ''; + urls = "https://kitty.forge/cat.tar.gz"; outputHashMode = "recursive"; outputHash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="; }; From d85309f7ca154c014cf53777c76df5af44b50500 Mon Sep 17 00:00:00 2001 From: Jade Lovelace Date: Thu, 27 Jun 2024 22:47:21 -0700 Subject: [PATCH 2/2] store: delete obsolete lsof-disabling code Since Ifa0adda7984e, we don't use this code anymore on macOS, so we have no reason to have a knob to disable it anymore. Change-Id: Ie29a8a8978d9aefd4551895f4f9b3cc0827496df --- doc/manual/src/contributing/testing.md | 3 --- src/libstore/gc.cc | 28 ++++++++++++-------------- 2 files changed, 13 insertions(+), 18 deletions(-) diff --git a/doc/manual/src/contributing/testing.md b/doc/manual/src/contributing/testing.md index 84836b891..b6b5318e0 100644 --- a/doc/manual/src/contributing/testing.md +++ b/doc/manual/src/contributing/testing.md @@ -433,9 +433,6 @@ I grepped `src/` for `get[eE]nv\("` to find the mentions in Lix code. - `NIX_PROFILE` - Selects which profile `nix-env` will operate on. Documented elsewhere. - `NIX_SSHOPTS` - Options passed to `ssh(1)` when using a ssh remote store. Incorrectly documented on `nix-copy-closure` which is *surely* not the only place they are used?? -- `_NIX_TEST_NO_LSOF` - Used on non-Linux, non-macOS platforms to disable using `lsof` when finding gc roots. - - Since https://git.lix.systems/lix-project/lix/issues/156 was fixed, this should probably just be removed as it was a bad workaround for a macOS issue. - `_NIX_TEST_GC_SYNC_1` - Path to a pipe that is used to block the GC briefly to validate invariants from the test suite. - `_NIX_TEST_GC_SYNC_2` - Path to a pipe that is used to block the GC briefly to validate invariants from the test suite. - `_NIX_TEST_FREE_SPACE_FILE` - Path to a file containing a decimal number with the free space that the GC is to believe it has. diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc index d58e3c8eb..02234d404 100644 --- a/src/libstore/gc.cc +++ b/src/libstore/gc.cc @@ -321,22 +321,20 @@ Roots LocalStore::findRoots(bool censor) void LocalStore::findPlatformRoots(UncheckedRoots & unchecked) { - // lsof is really slow on OS X. This actually causes the gc-concurrent.sh test to fail. - // See: https://github.com/NixOS/nix/issues/3011 - // Because of this we disable lsof when running the tests. - if (getEnv("_NIX_TEST_NO_LSOF") != "1") { - try { - std::regex lsofRegex(R"(^n(/.*)$)"); - auto lsofLines = - tokenizeString>(runProgram(LSOF, true, { "-n", "-w", "-F", "n" }), "\n"); - for (const auto & line : lsofLines) { - std::smatch match; - if (std::regex_match(line, match, lsofRegex)) - unchecked[match[1]].emplace("{lsof}"); - } - } catch (ExecError & e) { - /* lsof not installed, lsof failed */ + // N.B. This is (read: undertested!) fallback code only used for + // non-Darwin, non-Linux platforms. Both major platforms have + // platform-specific code in src/libstore/platform/ + try { + std::regex lsofRegex(R"(^n(/.*)$)"); + auto lsofLines = + tokenizeString>(runProgram(LSOF, true, { "-n", "-w", "-F", "n" }), "\n"); + for (const auto & line : lsofLines) { + std::smatch match; + if (std::regex_match(line, match, lsofRegex)) + unchecked[match[1]].emplace("{lsof}"); } + } catch (ExecError & e) { + /* lsof not installed, lsof failed */ } }