aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2018-03-20 15:17:59 +0100
committerEelco Dolstra <edolstra@gmail.com>2018-03-20 15:25:26 +0100
commit1aca195e52d4fbf76908e6588b55ed8b5b25cfc8 (patch)
tree54c34371afebf63b886d3f5a9e747d5d237e0ab7
parent78d0c72b52835161fd15058b111aa05d69ce062b (diff)
Hack to get SSH error messages from build-remote
E.g. cannot build on 'ssh://mac1': cannot connect to 'mac1': bash: nix-store: command not found cannot build on 'ssh://mac2': cannot connect to 'mac2': Host key verification failed. cannot build on 'ssh://mac3': cannot connect to 'mac3': Received disconnect from 213... port 6001:2: Too many authentication failures Authentication failed.
-rw-r--r--src/build-remote/build-remote.cc8
-rw-r--r--src/libstore/build.cc5
-rw-r--r--src/libutil/util.cc23
-rw-r--r--src/libutil/util.hh4
4 files changed, 33 insertions, 7 deletions
diff --git a/src/build-remote/build-remote.cc b/src/build-remote/build-remote.cc
index 6b294a4d2..9cd01bb61 100644
--- a/src/build-remote/build-remote.cc
+++ b/src/build-remote/build-remote.cc
@@ -191,8 +191,10 @@ int main (int argc, char * * argv)
storeUri = bestMachine->storeUri;
} catch (std::exception & e) {
- printError("unable to open SSH connection to '%s': %s; trying other available machines...",
- bestMachine->storeUri, e.what());
+ auto msg = chomp(drainFD(5, false));
+ printError("cannot build on '%s': %s%s",
+ bestMachine->storeUri, e.what(),
+ (msg.empty() ? "" : ": " + msg));
bestMachine->enabled = false;
continue;
}
@@ -202,6 +204,8 @@ int main (int argc, char * * argv)
}
connected:
+ close(5);
+
std::cerr << "# accept\n" << storeUri << "\n";
auto inputs = readStrings<PathSet>(source);
diff --git a/src/libstore/build.cc b/src/libstore/build.cc
index b8613427e..5c548755c 100644
--- a/src/libstore/build.cc
+++ b/src/libstore/build.cc
@@ -652,6 +652,11 @@ HookInstance::HookInstance()
if (dup2(builderOut.writeSide.get(), 4) == -1)
throw SysError("dupping builder's stdout/stderr");
+ /* Hack: pass the read side of that fd to allow build-remote
+ to read SSH error messages. */
+ if (dup2(builderOut.readSide.get(), 5) == -1)
+ throw SysError("dupping builder's stdout/stderr");
+
Strings args = {
baseNameOf(settings.buildHook),
std::to_string(verbosity),
diff --git a/src/libutil/util.cc b/src/libutil/util.cc
index 764b4e442..ab2d097f8 100644
--- a/src/libutil/util.cc
+++ b/src/libutil/util.cc
@@ -567,21 +567,38 @@ void writeFull(int fd, const string & s, bool allowInterrupts)
}
-string drainFD(int fd)
+string drainFD(int fd, bool block)
{
StringSink sink;
- drainFD(fd, sink);
+ drainFD(fd, sink, block);
return std::move(*sink.s);
}
-void drainFD(int fd, Sink & sink)
+void drainFD(int fd, Sink & sink, bool block)
{
+ int saved;
+
+ Finally finally([&]() {
+ if (!block) {
+ if (fcntl(fd, F_SETFL, saved) == -1)
+ throw SysError("making file descriptor blocking");
+ }
+ });
+
+ if (!block) {
+ saved = fcntl(fd, F_GETFL);
+ if (fcntl(fd, F_SETFL, saved | O_NONBLOCK) == -1)
+ throw SysError("making file descriptor non-blocking");
+ }
+
std::vector<unsigned char> buf(4096);
while (1) {
checkInterrupt();
ssize_t rd = read(fd, buf.data(), buf.size());
if (rd == -1) {
+ if (!block && (errno == EAGAIN || errno == EWOULDBLOCK))
+ break;
if (errno != EINTR)
throw SysError("reading from file");
}
diff --git a/src/libutil/util.hh b/src/libutil/util.hh
index 85952535d..743d23861 100644
--- a/src/libutil/util.hh
+++ b/src/libutil/util.hh
@@ -151,9 +151,9 @@ MakeError(EndOfFile, Error)
/* Read a file descriptor until EOF occurs. */
-string drainFD(int fd);
+string drainFD(int fd, bool block = true);
-void drainFD(int fd, Sink & sink);
+void drainFD(int fd, Sink & sink, bool block = true);
/* Automatic cleanup of resources. */