From 9bfef6a06c806c813b2c6ebcea9c8c4abc7c5298 Mon Sep 17 00:00:00 2001 From: Raito Bezarius Date: Mon, 25 Aug 2025 14:01:00 +0200 Subject: [PATCH] legacy/nix-build: create various temporary directories into a known tempdir Fixes fj#940. When running `nix-shell`, the `$NIX_BUILD_TOP` environment variable is set to `$TMPDIR` or `/tmp`. nixpkgs stdenv uses $NIX_BUILD_TOP to create `$NIX_BUILD_TOP/env-vars` which contains all the environment variables set by stdenv. This is used for debugging purposes in combination with `--keep-failed` to reload the bash environment of a derivation. `$TMPDIR` is often unset, therefore, `/tmp/env-vars` was constantly being created. On a multi-user system or, when you run Lix as root, you might create a `/tmp/env-vars` with different permission bits. As a result, `nix-shell` can cease to function because that file will fail creation for an unprivileged user for example. fj#940 rightfully remark that the code is not consistent between nix3-develop and nix-shell and it should be reworked. Change-Id: Iddf15945385d8bd497b2800b37fee5e1f97689b7 Signed-off-by: Raito Bezarius (cherry picked from commit feab75bde0577f9fdf3202eb217166f8cad1570b) --- doc/manual/rl-next/shell-build-dir-in-tempdir.md | 13 +++++++++++++ lix/legacy/nix-build.cc | 4 +++- 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 doc/manual/rl-next/shell-build-dir-in-tempdir.md diff --git a/doc/manual/rl-next/shell-build-dir-in-tempdir.md b/doc/manual/rl-next/shell-build-dir-in-tempdir.md new file mode 100644 index 000000000..a22ab7629 --- /dev/null +++ b/doc/manual/rl-next/shell-build-dir-in-tempdir.md @@ -0,0 +1,13 @@ +--- +synopsis: "`nix-shell` default shell directory is not `/tmp` anymore for `$NIX_BUILD_TOP`" +cls: [] +issues: [fj#940] +category: "Fixes" +credits: [raito] +--- + +Previously, Lix `nix-shell`s could exit non-zero status when `stdenv`'s `dumpVars` phase failed to write to `$NIX_BUILD_TOP/env-vars`, despite `dumpVars` being intended as a debugging aid. + +This happens when `TMPDIR` is not set and defaults therefore to `/tmp`, resulting in a `/tmp/env-vars` global file that every `nix-shell` wants to write. + +We fix this issue by reusing a pre-created, unique, and writable location, as the build top directory, avoiding shell exiting from write failures silently. diff --git a/lix/legacy/nix-build.cc b/lix/legacy/nix-build.cc index fd09d8945..fa6a75d9b 100644 --- a/lix/legacy/nix-build.cc +++ b/lix/legacy/nix-build.cc @@ -188,6 +188,7 @@ static void main_nix_build(AsyncIoRoot & aio, std::string programName, Strings a throw UsageError("'-p' and '-E' are mutually exclusive"); AutoDelete tmpDir(createTempDir("", myName)); + AutoDelete buildTopTmpDir(createTempDir(tmpDir, "build-top")); if (outLink.empty()) outLink = (Path) tmpDir + "/result"; @@ -431,7 +432,8 @@ static void main_nix_build(AsyncIoRoot & aio, std::string programName, Strings a } // Don't use defaultTempDir() here! We want to preserve the user's TMPDIR for the shell - env["NIX_BUILD_TOP"] = env["TMPDIR"] = env["TEMPDIR"] = env["TMP"] = env["TEMP"] = getEnvNonEmpty("TMPDIR").value_or("/tmp"); + env["NIX_BUILD_TOP"] = env["TMPDIR"] = env["TEMPDIR"] = env["TMP"] = env["TEMP"] = + getEnvNonEmpty("TMPDIR").value_or(buildTopTmpDir); env["NIX_STORE"] = store->config().storeDir; env["NIX_BUILD_CORES"] = std::to_string(settings.buildCores);