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

If by some chance the moc executable does not exist while running
AUTOMOC, instead of showing an error, the CMake Autogen invocation
hangs indefinitely.

This happens because UVProcessFinished() is not called if the process
does not launch correctly.

Make sure to call UVProcessFinished() even if the process launch fails,
and also report the error returned by libuv.
This commit is contained in:
Alexandru Croitor
2019-03-22 15:27:39 +01:00
parent 89abbdd8c8
commit e7a760fe7d
2 changed files with 17 additions and 3 deletions

View File

@@ -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

View File

@@ -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();
}
}