Fix error display if execve() in the builder fails

After we've send "\2\n" to the parent, we can't send a serialized
exception anymore. It will show up garbled like

  $ nix-build --store /tmp/nix --expr 'derivation { name = "foo"; system = "x86_64-linux"; builder = "/foo/bar"; }'
  this derivation will be built:
    /nix/store/xmdip0z5x1zqpp6gnxld3vqng7zbpapp-foo.drv
  building '/nix/store/xmdip0z5x1zqpp6gnxld3vqng7zbpapp-foo.drv'...

  ErrorErrorEexecuting '/foo/bar': No such file or directory
  error: builder for '/nix/store/xmdip0z5x1zqpp6gnxld3vqng7zbpapp-foo.drv' failed with exit code 1
This commit is contained in:
Eelco Dolstra 2022-10-13 21:35:16 +02:00
parent 27ed3d0458
commit 0359d6d123

View file

@ -1594,6 +1594,8 @@ void LocalDerivationGoal::runChild()
/* Warning: in the child we should absolutely not make any SQLite /* Warning: in the child we should absolutely not make any SQLite
calls! */ calls! */
bool sendException = true;
try { /* child */ try { /* child */
commonChildInit(builderOut); commonChildInit(builderOut);
@ -2050,6 +2052,8 @@ void LocalDerivationGoal::runChild()
/* Indicate that we managed to set up the build environment. */ /* Indicate that we managed to set up the build environment. */
writeFull(STDERR_FILENO, std::string("\2\n")); writeFull(STDERR_FILENO, std::string("\2\n"));
sendException = false;
/* Execute the program. This should not return. */ /* Execute the program. This should not return. */
if (drv->isBuiltin()) { if (drv->isBuiltin()) {
try { try {
@ -2103,10 +2107,13 @@ void LocalDerivationGoal::runChild()
throw SysError("executing '%1%'", drv->builder); throw SysError("executing '%1%'", drv->builder);
} catch (Error & e) { } catch (Error & e) {
writeFull(STDERR_FILENO, "\1\n"); if (sendException) {
FdSink sink(STDERR_FILENO); writeFull(STDERR_FILENO, "\1\n");
sink << e; FdSink sink(STDERR_FILENO);
sink.flush(); sink << e;
sink.flush();
} else
std::cerr << e.msg();
_exit(1); _exit(1);
} }
} }