Serialize exceptions from the sandbox process to the parent

Fixes #4118.
This commit is contained in:
Eelco Dolstra 2020-10-07 16:34:03 +02:00
parent 27ca87c46a
commit be149acfda
3 changed files with 56 additions and 5 deletions

View file

@ -2737,9 +2737,12 @@ void DerivationGoal::startBuilder()
/* Check if setting up the build environment failed. */
while (true) {
string msg = readLine(builderOut.readSide.get());
if (string(msg, 0, 1) == "\2") break;
if (string(msg, 0, 1) == "\1") {
if (msg.size() == 1) break;
throw Error(string(msg, 1));
FdSource source(builderOut.readSide.get());
auto ex = readError(source);
ex.addTrace({}, "while setting up the build environment");
throw ex;
}
debug(msg);
}
@ -3785,7 +3788,7 @@ void DerivationGoal::runChild()
args.push_back(rewriteStrings(i, inputRewrites));
/* Indicate that we managed to set up the build environment. */
writeFull(STDERR_FILENO, string("\1\n"));
writeFull(STDERR_FILENO, string("\2\n"));
/* Execute the program. This should not return. */
if (drv->isBuiltin()) {
@ -3815,8 +3818,11 @@ void DerivationGoal::runChild()
throw SysError("executing '%1%'", drv->builder);
} catch (std::exception & e) {
writeFull(STDERR_FILENO, "\1while setting up the build environment: " + string(e.what()) + "\n");
} catch (Error & e) {
writeFull(STDERR_FILENO, "\1\n");
FdSink sink(STDERR_FILENO);
sink << e;
sink.flush();
_exit(1);
}
}

View file

@ -266,6 +266,24 @@ Sink & operator << (Sink & sink, const StringSet & s)
return sink;
}
Sink & operator << (Sink & sink, const Error & ex)
{
auto info = ex.info();
sink
<< "Error"
<< info.level
<< info.name
<< info.description
<< (info.hint ? info.hint->str() : "")
<< 0 // FIXME: info.errPos
<< info.traces.size();
for (auto & trace : info.traces) {
sink << 0; // FIXME: trace.pos
sink << trace.hint.str();
}
return sink;
}
void readPadding(size_t len, Source & source)
{
@ -319,6 +337,30 @@ template Paths readStrings(Source & source);
template PathSet readStrings(Source & source);
Error readError(Source & source)
{
auto type = readString(source);
assert(type == "Error");
ErrorInfo info;
info.level = (Verbosity) readInt(source);
info.name = readString(source);
info.description = readString(source);
auto hint = readString(source);
if (hint != "") info.hint = hintformat(std::move(format("%s") % hint));
auto havePos = readNum<size_t>(source);
assert(havePos == 0);
auto nrTraces = readNum<size_t>(source);
for (size_t i = 0; i < nrTraces; ++i) {
havePos = readNum<size_t>(source);
assert(havePos == 0);
info.traces.push_back(Trace {
.hint = hintformat(std::move(format("%s") % readString(source)))
});
}
return Error(std::move(info));
}
void StringSink::operator () (const unsigned char * data, size_t len)
{
static bool warned = false;

View file

@ -321,6 +321,7 @@ inline Sink & operator << (Sink & sink, uint64_t n)
Sink & operator << (Sink & sink, const string & s);
Sink & operator << (Sink & sink, const Strings & s);
Sink & operator << (Sink & sink, const StringSet & s);
Sink & operator << (Sink & in, const Error & ex);
MakeError(SerialisationError, Error);
@ -382,6 +383,8 @@ Source & operator >> (Source & in, bool & b)
return in;
}
Error readError(Source & source);
/* An adapter that converts a std::basic_istream into a source. */
struct StreamToSourceAdapter : Source