mirror of
https://github.com/NixOS/nix
synced 2025-06-28 22:01:15 +02:00
Merge pull request #11343 from DeterminateSystems/no-framedsink-threads
withFramedSink(): Don't use a thread to monitor the other side
This commit is contained in:
commit
915db74dbf
7 changed files with 69 additions and 52 deletions
|
@ -402,6 +402,9 @@ static void performOp(TunnelLogger * logger, ref<Store> store,
|
|||
logger->startWork();
|
||||
auto pathInfo = [&]() {
|
||||
// NB: FramedSource must be out of scope before logger->stopWork();
|
||||
// FIXME: this means that if there is an error
|
||||
// half-way through, the client will keep sending
|
||||
// data, since we haven't sent it the error yet.
|
||||
auto [contentAddressMethod, hashAlgo] = ContentAddressMethod::parseWithAlgo(camStr);
|
||||
FramedSource source(conn.from);
|
||||
FileSerialisationMethod dumpMethod;
|
||||
|
|
|
@ -49,7 +49,7 @@ struct RemoteStore::ConnectionHandle
|
|||
RemoteStore::Connection & operator * () { return *handle; }
|
||||
RemoteStore::Connection * operator -> () { return &*handle; }
|
||||
|
||||
void processStderr(Sink * sink = 0, Source * source = 0, bool flush = true);
|
||||
void processStderr(Sink * sink = 0, Source * source = 0, bool flush = true, bool block = true);
|
||||
|
||||
void withFramedSink(std::function<void(Sink & sink)> fun);
|
||||
};
|
||||
|
|
|
@ -153,9 +153,9 @@ RemoteStore::ConnectionHandle::~ConnectionHandle()
|
|||
}
|
||||
}
|
||||
|
||||
void RemoteStore::ConnectionHandle::processStderr(Sink * sink, Source * source, bool flush)
|
||||
void RemoteStore::ConnectionHandle::processStderr(Sink * sink, Source * source, bool flush, bool block)
|
||||
{
|
||||
handle->processStderr(&daemonException, sink, source, flush);
|
||||
handle->processStderr(&daemonException, sink, source, flush, block);
|
||||
}
|
||||
|
||||
|
||||
|
@ -926,43 +926,17 @@ void RemoteStore::ConnectionHandle::withFramedSink(std::function<void(Sink & sin
|
|||
{
|
||||
(*this)->to.flush();
|
||||
|
||||
std::exception_ptr ex;
|
||||
|
||||
/* Handle log messages / exceptions from the remote on a separate
|
||||
thread. */
|
||||
std::thread stderrThread([&]()
|
||||
{
|
||||
try {
|
||||
ReceiveInterrupts receiveInterrupts;
|
||||
processStderr(nullptr, nullptr, false);
|
||||
} catch (...) {
|
||||
ex = std::current_exception();
|
||||
}
|
||||
});
|
||||
|
||||
Finally joinStderrThread([&]()
|
||||
{
|
||||
if (stderrThread.joinable()) {
|
||||
stderrThread.join();
|
||||
if (ex) {
|
||||
try {
|
||||
std::rethrow_exception(ex);
|
||||
} catch (...) {
|
||||
ignoreException();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
{
|
||||
FramedSink sink((*this)->to, ex);
|
||||
FramedSink sink((*this)->to, [&]() {
|
||||
/* Periodically process stderr messages and exceptions
|
||||
from the daemon. */
|
||||
processStderr(nullptr, nullptr, false, false);
|
||||
});
|
||||
fun(sink);
|
||||
sink.flush();
|
||||
}
|
||||
|
||||
stderrThread.join();
|
||||
if (ex)
|
||||
std::rethrow_exception(ex);
|
||||
processStderr(nullptr, nullptr, false);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -32,7 +32,8 @@ static Logger::Fields readFields(Source & from)
|
|||
return fields;
|
||||
}
|
||||
|
||||
std::exception_ptr WorkerProto::BasicClientConnection::processStderrReturn(Sink * sink, Source * source, bool flush)
|
||||
std::exception_ptr
|
||||
WorkerProto::BasicClientConnection::processStderrReturn(Sink * sink, Source * source, bool flush, bool block)
|
||||
{
|
||||
if (flush)
|
||||
to.flush();
|
||||
|
@ -41,6 +42,9 @@ std::exception_ptr WorkerProto::BasicClientConnection::processStderrReturn(Sink
|
|||
|
||||
while (true) {
|
||||
|
||||
if (!block && !from.hasData())
|
||||
break;
|
||||
|
||||
auto msg = readNum<uint64_t>(from);
|
||||
|
||||
if (msg == STDERR_WRITE) {
|
||||
|
@ -95,8 +99,10 @@ std::exception_ptr WorkerProto::BasicClientConnection::processStderrReturn(Sink
|
|||
logger->result(act, type, fields);
|
||||
}
|
||||
|
||||
else if (msg == STDERR_LAST)
|
||||
else if (msg == STDERR_LAST) {
|
||||
assert(block);
|
||||
break;
|
||||
}
|
||||
|
||||
else
|
||||
throw Error("got unknown message type %x from Nix daemon", msg);
|
||||
|
@ -130,9 +136,10 @@ std::exception_ptr WorkerProto::BasicClientConnection::processStderrReturn(Sink
|
|||
}
|
||||
}
|
||||
|
||||
void WorkerProto::BasicClientConnection::processStderr(bool * daemonException, Sink * sink, Source * source, bool flush)
|
||||
void WorkerProto::BasicClientConnection::processStderr(
|
||||
bool * daemonException, Sink * sink, Source * source, bool flush, bool block)
|
||||
{
|
||||
auto ex = processStderrReturn(sink, source, flush);
|
||||
auto ex = processStderrReturn(sink, source, flush, block);
|
||||
if (ex) {
|
||||
*daemonException = true;
|
||||
std::rethrow_exception(ex);
|
||||
|
|
|
@ -70,9 +70,10 @@ struct WorkerProto::BasicClientConnection : WorkerProto::BasicConnection
|
|||
|
||||
virtual void closeWrite() = 0;
|
||||
|
||||
std::exception_ptr processStderrReturn(Sink * sink = 0, Source * source = 0, bool flush = true);
|
||||
std::exception_ptr processStderrReturn(Sink * sink = 0, Source * source = 0, bool flush = true, bool block = true);
|
||||
|
||||
void processStderr(bool * daemonException, Sink * sink = 0, Source * source = 0, bool flush = true);
|
||||
void
|
||||
processStderr(bool * daemonException, Sink * sink = 0, Source * source = 0, bool flush = true, bool block = true);
|
||||
|
||||
/**
|
||||
* Establishes connection, negotiating version.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue