aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2020-10-07 16:34:03 +0200
committerEelco Dolstra <edolstra@gmail.com>2020-10-07 16:34:03 +0200
commitbe149acfdaae06667bc58df467c04c41827b69d0 (patch)
tree29bd64b3867cf616387d92cb5332eac1737d6ab4 /src
parent27ca87c46a57e1e6603028c1902189b53635d576 (diff)
Serialize exceptions from the sandbox process to the parent
Fixes #4118.
Diffstat (limited to 'src')
-rw-r--r--src/libstore/build.cc16
-rw-r--r--src/libutil/serialise.cc42
-rw-r--r--src/libutil/serialise.hh3
3 files changed, 56 insertions, 5 deletions
diff --git a/src/libstore/build.cc b/src/libstore/build.cc
index 9497e7b3e..fa7283588 100644
--- a/src/libstore/build.cc
+++ b/src/libstore/build.cc
@@ -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);
}
}
diff --git a/src/libutil/serialise.cc b/src/libutil/serialise.cc
index a469a1e73..5c9f6f901 100644
--- a/src/libutil/serialise.cc
+++ b/src/libutil/serialise.cc
@@ -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;
diff --git a/src/libutil/serialise.hh b/src/libutil/serialise.hh
index b41e58f33..d7fe0b81e 100644
--- a/src/libutil/serialise.hh
+++ b/src/libutil/serialise.hh
@@ -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