Serialize exceptions from the daemon to the client

This commit is contained in:
Eelco Dolstra 2020-10-07 17:13:54 +02:00
parent be149acfda
commit c43e882f54
3 changed files with 24 additions and 11 deletions

View file

@ -101,17 +101,20 @@ struct TunnelLogger : public Logger
/* stopWork() means that we're done; stop sending stderr to the /* stopWork() means that we're done; stop sending stderr to the
client. */ client. */
void stopWork(bool success = true, const string & msg = "", unsigned int status = 0) void stopWork(const Error * ex = nullptr)
{ {
auto state(state_.lock()); auto state(state_.lock());
state->canSendStderr = false; state->canSendStderr = false;
if (success) if (!ex)
to << STDERR_LAST; to << STDERR_LAST;
else { else {
to << STDERR_ERROR << msg; if (GET_PROTOCOL_MINOR(clientVersion) >= 26) {
if (status != 0) to << status; to << STDERR_ERROR << *ex;
} else {
to << STDERR_ERROR << ex->what() << ex->status;
}
} }
} }
@ -935,10 +938,11 @@ void processConnection(
during addTextToStore() / importPath(). If that during addTextToStore() / importPath(). If that
happens, just send the error message and exit. */ happens, just send the error message and exit. */
bool errorAllowed = tunnelLogger->state_.lock()->canSendStderr; bool errorAllowed = tunnelLogger->state_.lock()->canSendStderr;
tunnelLogger->stopWork(false, e.msg(), e.status); tunnelLogger->stopWork(&e);
if (!errorAllowed) throw; if (!errorAllowed) throw;
} catch (std::bad_alloc & e) { } catch (std::bad_alloc & e) {
tunnelLogger->stopWork(false, "Nix daemon out of memory", 1); auto ex = Error("Nix daemon out of memory");
tunnelLogger->stopWork(&ex);
throw; throw;
} }
@ -947,8 +951,13 @@ void processConnection(
assert(!tunnelLogger->state_.lock()->canSendStderr); assert(!tunnelLogger->state_.lock()->canSendStderr);
}; };
} catch (Error & e) {
tunnelLogger->stopWork(&e);
to.flush();
return;
} catch (std::exception & e) { } catch (std::exception & e) {
tunnelLogger->stopWork(false, e.what(), 1); auto ex = Error(e.what());
tunnelLogger->stopWork(&ex);
to.flush(); to.flush();
return; return;
} }

View file

@ -925,10 +925,14 @@ std::exception_ptr RemoteStore::Connection::processStderr(Sink * sink, Source *
} }
else if (msg == STDERR_ERROR) { else if (msg == STDERR_ERROR) {
if (GET_PROTOCOL_MINOR(daemonVersion) >= 26) {
return std::make_exception_ptr(readError(from));
} else {
string error = readString(from); string error = readString(from);
unsigned int status = readInt(from); unsigned int status = readInt(from);
return std::make_exception_ptr(Error(status, error)); return std::make_exception_ptr(Error(status, error));
} }
}
else if (msg == STDERR_NEXT) else if (msg == STDERR_NEXT)
printError(chomp(readString(from))); printError(chomp(readString(from)));

View file

@ -6,7 +6,7 @@ namespace nix {
#define WORKER_MAGIC_1 0x6e697863 #define WORKER_MAGIC_1 0x6e697863
#define WORKER_MAGIC_2 0x6478696f #define WORKER_MAGIC_2 0x6478696f
#define PROTOCOL_VERSION 0x119 #define PROTOCOL_VERSION 0x11a
#define GET_PROTOCOL_MAJOR(x) ((x) & 0xff00) #define GET_PROTOCOL_MAJOR(x) ((x) & 0xff00)
#define GET_PROTOCOL_MINOR(x) ((x) & 0x00ff) #define GET_PROTOCOL_MINOR(x) ((x) & 0x00ff)