about summary refs log tree commit diff
diff options
context:
space:
mode:
-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 6b294a4d2c..9cd01bb61b 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 b8613427e0..5c548755c6 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 764b4e4420..ab2d097f8b 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 85952535db..743d238611 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. */