From 5b7dcb3005ed38d4634f228f01852ae18b2d9cd4 Mon Sep 17 00:00:00 2001 From: midnightveil Date: Fri, 10 May 2024 15:25:12 +1000 Subject: [PATCH] Allow enabling core dumps from builds for nix & child processes Fixes https://git.lix.systems/lix-project/lix/issues/268 Change-Id: I3f1b0ddf064f891cca8b53229c5c31c74cea3d9f --- doc/manual/change-authors.yml | 5 +++++ doc/manual/rl-next/enable-coredumps.md | 13 +++++++++++++ src/libstore/build/local-derivation-goal.cc | 3 +++ src/libstore/globals.hh | 9 +++++++++ tests/nixos/coredumps/default.nix | 15 +++++++++++++++ tests/nixos/coredumps/package.nix | 16 ++++++++++++++++ tests/nixos/default.nix | 2 ++ tests/nixos/util.nix | 7 ++++++- 8 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 doc/manual/rl-next/enable-coredumps.md create mode 100644 tests/nixos/coredumps/default.nix create mode 100644 tests/nixos/coredumps/package.nix diff --git a/doc/manual/change-authors.yml b/doc/manual/change-authors.yml index 732c459a8..8c07d7e90 100644 --- a/doc/manual/change-authors.yml +++ b/doc/manual/change-authors.yml @@ -61,3 +61,8 @@ edolstra: roberth: display_name: Robert Hensing github: roberth + +midnightveil: + display_name: julia + forgejo: midnightveil + github: midnightveil diff --git a/doc/manual/rl-next/enable-coredumps.md b/doc/manual/rl-next/enable-coredumps.md new file mode 100644 index 000000000..092aa58a1 --- /dev/null +++ b/doc/manual/rl-next/enable-coredumps.md @@ -0,0 +1,13 @@ +--- +synopsis: "Add an option `enable-core-dumps` that enables core dumps from builds" +cls: 1088 +credits: midnightveil +category: Features +--- + +In the past, Lix disabled core dumps by setting the soft `RLIMIT_CORE` to 0 +unconditionally. Although this rlimit could be altered from the builder since +it is just the soft limit, this was kind of annoying to do. By passing +`--option enable-core-dumps true` to an offending build, one can now cause the +core dumps to be handled by the system in the normal way (winding up in +`coredumpctl`, say, on Linux). diff --git a/src/libstore/build/local-derivation-goal.cc b/src/libstore/build/local-derivation-goal.cc index 3429afafa..cdbd0f5a7 100644 --- a/src/libstore/build/local-derivation-goal.cc +++ b/src/libstore/build/local-derivation-goal.cc @@ -1977,6 +1977,9 @@ void LocalDerivationGoal::runChild() /* Disable core dumps by default. */ struct rlimit limit = { 0, RLIM_INFINITY }; + if (settings.enableCoreDumps) { + limit.rlim_cur = RLIM_INFINITY; + } setrlimit(RLIMIT_CORE, &limit); // FIXME: set other limits to deterministic values? diff --git a/src/libstore/globals.hh b/src/libstore/globals.hh index 16af3a415..8856d8fae 100644 --- a/src/libstore/globals.hh +++ b/src/libstore/globals.hh @@ -290,6 +290,15 @@ public: Setting reservedSize{this, 8 * 1024 * 1024, "gc-reserved-space", "Amount of reserved disk space for the garbage collector."}; + Setting enableCoreDumps{ + this, false, "enable-core-dumps", + R"( + If set to `false` (the default), `RLIMIT_CORE` has a soft limit of zero. + If set to `true`, the soft limit is infinite. + + The hard limit is always infinite. + )"}; + Setting fsyncMetadata{ this, true, "fsync-metadata", R"( diff --git a/tests/nixos/coredumps/default.nix b/tests/nixos/coredumps/default.nix new file mode 100644 index 000000000..3d0d62945 --- /dev/null +++ b/tests/nixos/coredumps/default.nix @@ -0,0 +1,15 @@ +let + inherit (import ../util.nix) mkNixBuildTest; +in mkNixBuildTest rec { + name = "coredumps"; + extraMachineConfig = { pkgs, ... }: { + boot.kernel.sysctl."kernel.core_pattern" = "core"; + }; + + expressionFile = ./package.nix; + + testScriptPost = '' + # do a test, but this time with coredumps enabled. + machine.succeed('nix-build --option enable-core-dumps true --expr "let pkgs = import {}; in pkgs.callPackage ${expressionFile} { shouldBePresent = true; }"') + ''; +} diff --git a/tests/nixos/coredumps/package.nix b/tests/nixos/coredumps/package.nix new file mode 100644 index 000000000..a7f6434ed --- /dev/null +++ b/tests/nixos/coredumps/package.nix @@ -0,0 +1,16 @@ +{ lib, runCommand, shouldBePresent ? false }: + +runCommand "core-dump-now" { } '' + set -m + sleep infinity & + + # make a coredump + kill -SIGSEGV %1 + + if ${lib.optionalString (shouldBePresent) "!"} test -n "$(find . -maxdepth 1 -name 'core*' -print -quit)"; then + echo "core file was in wrong presence state, expected: ${if shouldBePresent then "present" else "missing"}" + exit 1 + fi + + touch $out +'' diff --git a/tests/nixos/default.nix b/tests/nixos/default.nix index 987463b07..9dd888916 100644 --- a/tests/nixos/default.nix +++ b/tests/nixos/default.nix @@ -166,4 +166,6 @@ in rootInSandbox = runNixOSTestFor "x86_64-linux" ./root-in-sandbox; broken-userns = runNixOSTestFor "x86_64-linux" ./broken-userns.nix; + + coredumps = runNixOSTestFor "x86_64-linux" ./coredumps; } diff --git a/tests/nixos/util.nix b/tests/nixos/util.nix index 0c51cc075..1b8b4223c 100644 --- a/tests/nixos/util.nix +++ b/tests/nixos/util.nix @@ -1,5 +1,6 @@ { - mkNixBuildTest = { name, expressionFile, extraMachineConfig ? {} }: + mkNixBuildTest = + { name, expressionFile, extraMachineConfig ? {}, testScriptPre ? "", testScriptPost ? "" }: { lib, pkgs, ... }: { inherit name; @@ -17,7 +18,11 @@ testScript = { nodes }: '' start_all() + ${testScriptPre} + machine.succeed('nix-build --expr "let pkgs = import {}; in pkgs.callPackage ${expressionFile} {}"') + + ${testScriptPost} ''; }; }