Browse Source

Merge topic 'fix_autogen_deadlock'

e7a760fe7d Autogen: Fix deadlock when uv_spawn() fails while trying to run moc

Acked-by: Kitware Robot <[email protected]>
Tested-by: Sebastian Holtermann <[email protected]>
Merge-request: !3139
Brad King 6 years ago
parent
commit
f288383b3f
2 changed files with 17 additions and 3 deletions
  1. 12 2
      Source/cmQtAutoGenerator.cxx
  2. 5 1
      Source/cmQtAutoGeneratorMocUic.cxx

+ 12 - 2
Source/cmQtAutoGenerator.cxx

@@ -15,6 +15,7 @@
 #include "cmake.h"
 
 #include <algorithm>
+#include <sstream>
 #include <utility>
 
 // -- Class methods
@@ -504,6 +505,13 @@ void cmQtAutoGenerator::ReadOnlyProcessT::setup(
   Setup_.MergedOutput = mergedOutput;
 }
 
+static std::string getUVError(const char* prefixString, int uvErrorCode)
+{
+  std::ostringstream ost;
+  ost << prefixString << ": " << uv_strerror(uvErrorCode);
+  return ost.str();
+}
+
 bool cmQtAutoGenerator::ReadOnlyProcessT::start(
   uv_loop_t* uv_loop, std::function<void()>&& finishedCallback)
 {
@@ -560,8 +568,10 @@ bool cmQtAutoGenerator::ReadOnlyProcessT::start(
     UVOptions_.stdio = UVOptionsStdIO_.data();
 
     // -- Spawn process
-    if (UVProcess_.spawn(*uv_loop, UVOptions_, this) != 0) {
-      Result()->ErrorMessage = "libuv process spawn failed";
+    int uvErrorCode = UVProcess_.spawn(*uv_loop, UVOptions_, this);
+    if (uvErrorCode != 0) {
+      Result()->ErrorMessage =
+        getUVError("libuv process spawn failed ", uvErrorCode);
     }
   }
   // -- Start reading from stdio streams

+ 5 - 1
Source/cmQtAutoGeneratorMocUic.cxx

@@ -1107,13 +1107,17 @@ void cmQtAutoGeneratorMocUic::WorkerT::UVProcessStart(uv_async_t* handle)
       wrk.Process_->start(handle->loop, [&wrk] { wrk.UVProcessFinished(); });
     }
   }
+
+  if (!wrk.Process_->IsStarted()) {
+    wrk.UVProcessFinished();
+  }
 }
 
 void cmQtAutoGeneratorMocUic::WorkerT::UVProcessFinished()
 {
   {
     std::lock_guard<std::mutex> lock(ProcessMutex_);
-    if (Process_ && Process_->IsFinished()) {
+    if (Process_ && (Process_->IsFinished() || !Process_->IsStarted())) {
       Process_.reset();
     }
   }