Shut down write side before draining the read side

This is important if the remote side *does* execute
nix-store/nix-daemon successfully, but stdout is polluted
(e.g. because the remote user's bashrc script prints something to
stdout). In that case we have to shutdown the write side to force the
remote nix process to exit.
This commit is contained in:
Eelco Dolstra 2021-09-23 18:01:04 +02:00
parent 994348e9e0
commit ea9df6fe51
6 changed files with 24 additions and 1 deletions

View file

@ -89,6 +89,8 @@ struct LegacySSHStore : public virtual LegacySSHStoreConfig, public virtual Stor
if (magic != SERVE_MAGIC_2) if (magic != SERVE_MAGIC_2)
throw Error("'nix-store --serve' protocol mismatch from '%s'", host); throw Error("'nix-store --serve' protocol mismatch from '%s'", host);
} catch (SerialisationError & e) { } catch (SerialisationError & e) {
/* In case the other side is waiting for our input,
close it. */
conn->sshConn->in.close(); conn->sshConn->in.close();
auto msg = conn->from.drain(); auto msg = conn->from.drain();
throw Error("'nix-store --serve' protocol mismatch from '%s', got '%s'", throw Error("'nix-store --serve' protocol mismatch from '%s', got '%s'",

View file

@ -169,6 +169,9 @@ void RemoteStore::initConnection(Connection & conn)
if (magic != WORKER_MAGIC_2) if (magic != WORKER_MAGIC_2)
throw Error("protocol mismatch"); throw Error("protocol mismatch");
} catch (SerialisationError & e) { } catch (SerialisationError & e) {
/* In case the other side is waiting for our input, close
it. */
conn.closeWrite();
auto msg = conn.from.drain(); auto msg = conn.from.drain();
throw Error("protocol mismatch, got '%s'", chomp(*saved.s + msg)); throw Error("protocol mismatch, got '%s'", chomp(*saved.s + msg));
} }

View file

@ -125,7 +125,6 @@ public:
struct Connection struct Connection
{ {
AutoCloseFD fd;
FdSink to; FdSink to;
FdSource from; FdSource from;
unsigned int daemonVersion; unsigned int daemonVersion;
@ -133,6 +132,8 @@ public:
virtual ~Connection(); virtual ~Connection();
virtual void closeWrite() = 0;
std::exception_ptr processStderr(Sink * sink = 0, Source * source = 0, bool flush = true); std::exception_ptr processStderr(Sink * sink = 0, Source * source = 0, bool flush = true);
}; };

View file

@ -57,6 +57,11 @@ private:
struct Connection : RemoteStore::Connection struct Connection : RemoteStore::Connection
{ {
std::unique_ptr<SSHMaster::Connection> sshConn; std::unique_ptr<SSHMaster::Connection> sshConn;
void closeWrite() override
{
sshConn->in.close();
}
}; };
ref<RemoteStore::Connection> openConnection() override; ref<RemoteStore::Connection> openConnection() override;

View file

@ -45,6 +45,12 @@ std::string UDSRemoteStore::getUri()
} }
void UDSRemoteStore::Connection::closeWrite()
{
shutdown(fd.get(), SHUT_WR);
}
ref<RemoteStore::Connection> UDSRemoteStore::openConnection() ref<RemoteStore::Connection> UDSRemoteStore::openConnection()
{ {
auto conn = make_ref<Connection>(); auto conn = make_ref<Connection>();

View file

@ -40,6 +40,12 @@ public:
private: private:
struct Connection : RemoteStore::Connection
{
AutoCloseFD fd;
void closeWrite() override;
};
ref<RemoteStore::Connection> openConnection() override; ref<RemoteStore::Connection> openConnection() override;
std::optional<std::string> path; std::optional<std::string> path;
}; };