aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Ericson <John.Ericson@Obsidian.Systems>2023-06-22 14:23:25 -0400
committerJohn Ericson <John.Ericson@Obsidian.Systems>2023-06-22 14:29:45 -0400
commit97df060588e4d328a7e219107553087149a77bac (patch)
tree1f6cc6209b382c437757cc438b8f29fa9783a05b
parent2291232dc18fe01baceefcbc83e909aa160bd255 (diff)
Better document build failure exit codes
- Improved API docs from comment - Exit codes are for `nix-build`, not just `nix-store --release` - Make note in tests so the magic numbers are not surprising Picking up where #8387 left off.
-rw-r--r--doc/manual/src/command-ref/nix-build.md2
-rw-r--r--doc/manual/src/command-ref/nix-store/realise.md31
-rw-r--r--doc/manual/src/command-ref/status-build-failure.md34
-rw-r--r--src/libstore/build/entry-points.cc10
-rw-r--r--src/libstore/build/worker.cc11
-rw-r--r--src/libstore/build/worker.hh23
-rw-r--r--tests/check.sh3
-rw-r--r--tests/linux-sandbox.sh3
8 files changed, 72 insertions, 45 deletions
diff --git a/doc/manual/src/command-ref/nix-build.md b/doc/manual/src/command-ref/nix-build.md
index 7369ea2eb..b548edf82 100644
--- a/doc/manual/src/command-ref/nix-build.md
+++ b/doc/manual/src/command-ref/nix-build.md
@@ -70,6 +70,8 @@ except for `--arg` and `--attr` / `-A` which are passed to [`nix-instantiate`](n
Change the name of the symlink to the output path created from
`result` to *outlink*.
+{{#include ./status-build-failure.md}}
+
{{#include ./opt-common.md}}
{{#include ./env-common.md}}
diff --git a/doc/manual/src/command-ref/nix-store/realise.md b/doc/manual/src/command-ref/nix-store/realise.md
index 6b50d2145..c19aea75e 100644
--- a/doc/manual/src/command-ref/nix-store/realise.md
+++ b/doc/manual/src/command-ref/nix-store/realise.md
@@ -54,36 +54,7 @@ The following flags are available:
previous build, the new output path is left in
`/nix/store/name.check.`
-Special exit codes:
-
- - `100`\
- Generic build failure, the builder process returned with a non-zero
- exit code.
-
- - `101`\
- Build timeout, the build was aborted because it did not complete
- within the specified `timeout`.
-
- - `102`\
- Hash mismatch, the build output was rejected because it does not
- match the [`outputHash` attribute of the
- derivation](@docroot@/language/advanced-attributes.md).
-
- - `104`\
- Not deterministic, the build succeeded in check mode but the
- resulting output is not binary reproducible.
-
-With the `--keep-going` flag it's possible for multiple failures to
-occur, in this case the 1xx status codes are or combined using binary
-or.
-
- 1100100
- ^^^^
- |||`- timeout
- ||`-- output hash mismatch
- |`--- build failure
- `---- not deterministic
-
+{{#include ../status-build-failure.md}}
{{#include ./opt-common.md}}
diff --git a/doc/manual/src/command-ref/status-build-failure.md b/doc/manual/src/command-ref/status-build-failure.md
new file mode 100644
index 000000000..06114eb29
--- /dev/null
+++ b/doc/manual/src/command-ref/status-build-failure.md
@@ -0,0 +1,34 @@
+# Special exit codes for build failure
+
+1xx status codes are used when requested builds failed.
+The following codes are in use:
+
+- `100` Generic build failure
+
+ The builder process returned with a non-zero exit code.
+
+- `101` Build timeout
+
+ The build was aborted because it did not complete within the specified `timeout`.
+
+- `102` Hash mismatch
+
+ The build output was rejected because it does not match the
+ [`outputHash` attribute of the derivation](@docroot@/language/advanced-attributes.md).
+
+- `104` Not deterministic
+
+ The build succeeded in check mode but the resulting output is not binary reproducible.
+
+With the `--keep-going` flag it's possible for multiple failures to occur.
+In this case the 1xx status codes are or combined using
+[bitwise OR](https://en.wikipedia.org/wiki/Bitwise_operation#OR).
+
+```
+0b1100100
+ ^^^^
+ |||`- timeout
+ ||`-- output hash mismatch
+ |`--- build failure
+ `---- not deterministic
+```
diff --git a/src/libstore/build/entry-points.cc b/src/libstore/build/entry-points.cc
index edd6cb6d2..4aa4d6dca 100644
--- a/src/libstore/build/entry-points.cc
+++ b/src/libstore/build/entry-points.cc
@@ -31,11 +31,11 @@ void Store::buildPaths(const std::vector<DerivedPath> & reqs, BuildMode buildMod
}
if (failed.size() == 1 && ex) {
- ex->status = worker.exitStatus();
+ ex->status = worker.failingExitStatus();
throw std::move(*ex);
} else if (!failed.empty()) {
if (ex) logError(ex->info());
- throw Error(worker.exitStatus(), "build of %s failed", showPaths(failed));
+ throw Error(worker.failingExitStatus(), "build of %s failed", showPaths(failed));
}
}
@@ -102,10 +102,10 @@ void Store::ensurePath(const StorePath & path)
if (goal->exitCode != Goal::ecSuccess) {
if (goal->ex) {
- goal->ex->status = worker.exitStatus();
+ goal->ex->status = worker.failingExitStatus();
throw std::move(*goal->ex);
} else
- throw Error(worker.exitStatus(), "path '%s' does not exist and cannot be created", printStorePath(path));
+ throw Error(worker.failingExitStatus(), "path '%s' does not exist and cannot be created", printStorePath(path));
}
}
@@ -128,7 +128,7 @@ void Store::repairPath(const StorePath & path)
goals.insert(worker.makeDerivationGoal(*info->deriver, OutputsSpec::All { }, bmRepair));
worker.run(goals);
} else
- throw Error(worker.exitStatus(), "cannot repair path '%s'", printStorePath(path));
+ throw Error(worker.failingExitStatus(), "cannot repair path '%s'", printStorePath(path));
}
}
diff --git a/src/libstore/build/worker.cc b/src/libstore/build/worker.cc
index ee334d54a..a9ca9cbbc 100644
--- a/src/libstore/build/worker.cc
+++ b/src/libstore/build/worker.cc
@@ -468,16 +468,9 @@ void Worker::waitForInput()
}
-unsigned int Worker::exitStatus()
+unsigned int Worker::failingExitStatus()
{
- /*
- * 1100100
- * ^^^^
- * |||`- timeout
- * ||`-- output hash mismatch
- * |`--- build failure
- * `---- not deterministic
- */
+ // See API docs in header for explanation
unsigned int mask = 0;
bool buildFailure = permanentFailure || timedOut || hashMismatch;
if (buildFailure)
diff --git a/src/libstore/build/worker.hh b/src/libstore/build/worker.hh
index 63624d910..5abceca0d 100644
--- a/src/libstore/build/worker.hh
+++ b/src/libstore/build/worker.hh
@@ -280,7 +280,28 @@ public:
*/
void waitForInput();
- unsigned int exitStatus();
+ /***
+ * The exit status in case of failure.
+ *
+ * In the case of a build failure, returned value follows this
+ * bitmask:
+ *
+ * ```
+ * 0b1100100
+ * ^^^^
+ * |||`- timeout
+ * ||`-- output hash mismatch
+ * |`--- build failure
+ * `---- not deterministic
+ * ```
+ *
+ * In other words, the failure code is at least 100 (0b1100100), but
+ * might also be greater.
+ *
+ * Otherwise (no build failure, but some other sort of failure by
+ * assumption), this returned value is 1.
+ */
+ unsigned int failingExitStatus();
/**
* Check whether the given valid path exists and has the right
diff --git a/tests/check.sh b/tests/check.sh
index 645b90222..e13abf747 100644
--- a/tests/check.sh
+++ b/tests/check.sh
@@ -18,6 +18,9 @@ clearStore
nix-build dependencies.nix --no-out-link
nix-build dependencies.nix --no-out-link --check
+# Build failure exit codes (100, 104, etc.) are from
+# doc/manual/src/command-ref/status-build-failure.md
+
# check for dangling temporary build directories
# only retain if build fails and --keep-failed is specified, or...
# ...build is non-deterministic and --check and --keep-failed are both specified
diff --git a/tests/linux-sandbox.sh b/tests/linux-sandbox.sh
index f2a77174d..ff7d257bd 100644
--- a/tests/linux-sandbox.sh
+++ b/tests/linux-sandbox.sh
@@ -36,11 +36,13 @@ nix-sandbox-build dependencies.nix --check
# Test that sandboxed builds with --check and -K can move .check directory to store
nix-sandbox-build check.nix -A nondeterministic
+# `100 + 4` means non-determinstic, see doc/manual/src/command-ref/status-build-failure.md
expectStderr 104 nix-sandbox-build check.nix -A nondeterministic --check -K > $TEST_ROOT/log
grepQuietInverse 'error: renaming' $TEST_ROOT/log
grepQuiet 'may not be deterministic' $TEST_ROOT/log
# Test that sandboxed builds cannot write to /etc easily
+# `100` means build failure without extra info, see doc/manual/src/command-ref/status-build-failure.md
expectStderr 100 nix-sandbox-build -E 'with import ./config.nix; mkDerivation { name = "etc-write"; buildCommand = "echo > /etc/test"; }' |
grepQuiet "/etc/test: Permission denied"
@@ -50,6 +52,7 @@ testCert () {
expectation=$1 # "missing" | "present"
mode=$2 # "normal" | "fixed-output"
certFile=$3 # a string that can be the path to a cert file
+ # `100` means build failure without extra info, see doc/manual/src/command-ref/status-build-failure.md
[ "$mode" == fixed-output ] && ret=1 || ret=100
expectStderr $ret nix-sandbox-build linux-sandbox-cert-test.nix --argstr mode "$mode" --option ssl-cert-file "$certFile" |
grepQuiet "CERT_${expectation}_IN_SANDBOX"