about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2017-03-13T13·56+0100
committerEelco Dolstra <edolstra@gmail.com>2017-03-15T15·49+0100
commitfbbc4d8dda4d347351c0667d1d9a571b201256cf (patch)
tree7d4d752e408708d04d92ff19b7191b491c2a8933 /src
parente8186085e07104d4b844208613c2d704b5b57dec (diff)
Fix deadlock in runProgram() when input is larger than the pipe buffer size
Diffstat (limited to 'src')
-rw-r--r--src/libutil/util.cc12
1 files changed, 9 insertions, 3 deletions
diff --git a/src/libutil/util.cc b/src/libutil/util.cc
index 0a5f796e4eaa..bc66b0c53223 100644
--- a/src/libutil/util.cc
+++ b/src/libutil/util.cc
@@ -870,11 +870,14 @@ string runProgram(Path program, bool searchPath, const Strings & args,
 
     out.writeSide = -1;
 
-    /* FIXME: This can deadlock if the input is too long. */
+    std::thread writerThread;
+
     if (!input.empty()) {
         in.readSide = -1;
-        writeFull(in.writeSide.get(), input);
-        in.writeSide = -1;
+        writerThread = std::thread([&]() {
+            writeFull(in.writeSide.get(), input);
+            in.writeSide = -1;
+        });
     }
 
     string result = drainFD(out.readSide.get());
@@ -885,6 +888,9 @@ string runProgram(Path program, bool searchPath, const Strings & args,
         throw ExecError(status, format("program ‘%1%’ %2%")
             % program % statusToString(status));
 
+    if (!input.empty())
+        writerThread.join();
+
     return result;
 }