Process: Fix EventLoopMode::On

Queue the call to start() so that it's executed after the nested
event loop is started, otherwise it fails on Windows with QProcessImpl.

Fixes: QTCREATORBUG-30066
Change-Id: Ibb17ef0f668f52c05b26a521e18c94e637992ba5
Reviewed-by: Alessandro Portale <alessandro.portale@qt.io>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
This commit is contained in:
Jarek Kobus
2024-01-13 01:21:32 +01:00
parent 85a27b3ddd
commit 7802e475ce
2 changed files with 30 additions and 38 deletions

View File

@@ -1865,23 +1865,22 @@ void Process::setWriteData(const QByteArray &writeData)
void Process::runBlocking(EventLoopMode eventLoopMode)
{
QDateTime startTime;
static const int blockingThresholdMs = qtcEnvironmentVariableIntValue("QTC_PROCESS_THRESHOLD");
auto starter = [this, eventLoopMode, &startTime] {
// Attach a dynamic property with info about blocking type
d->storeEventLoopDebugInfo(int(eventLoopMode));
QDateTime startTime;
static const int blockingThresholdMs = qtcEnvironmentVariableIntValue("QTC_PROCESS_THRESHOLD");
if (blockingThresholdMs > 0 && isMainThread())
startTime = QDateTime::currentDateTime();
Process::start();
start();
// Remove the dynamic property so that it's not reused in subseqent start()
d->storeEventLoopDebugInfo({});
};
if (eventLoopMode == EventLoopMode::On) {
// Start failure is triggered immediately if the executable cannot be found in the path.
// In this case the process is left in NotRunning state.
// Do not start the event loop in that case.
if (state() == QProcess::Starting) {
QTimer timer(this);
connect(&timer, &QTimer::timeout, d, &ProcessPrivate::slotTimeout);
timer.setInterval(1000);
@@ -1893,6 +1892,9 @@ void Process::runBlocking(EventLoopMode eventLoopMode)
QEventLoop eventLoop(this);
QTC_ASSERT(!d->m_eventLoop, return);
d->m_eventLoop = &eventLoop;
// Queue the call to start() so that it's executed after the nested event loop is started,
// otherwise it fails on Windows with QProcessImpl. See QTCREATORBUG-30066.
QMetaObject::invokeMethod(this, starter, Qt::QueuedConnection);
eventLoop.exec(QEventLoop::ExcludeUserInputEvents);
d->m_eventLoop = nullptr;
timer.stop();
@@ -1900,8 +1902,8 @@ void Process::runBlocking(EventLoopMode eventLoopMode)
if (isGuiEnabled())
QGuiApplication::restoreOverrideCursor();
#endif
}
} else {
starter();
if (!waitForStarted(d->m_maxHangTimerCount * 1000)) {
d->m_result = ProcessResult::StartFailed;
return;

View File

@@ -1595,17 +1595,7 @@ void tst_Process::eventLoopMode()
subConfig.setupSubProcess(&process);
process.setProcessImpl(processImpl);
process.runBlocking(eventLoopMode);
const ProcessResult actualResult = process.result();
// FIXME: On Windows, Process::runBlocking(EventLoopMode::On) and ProcessImpl::QProcess fails
// with ProcessResult::StartFailed. Details: QTCREATORBUG-30066
const bool isFailingCombination = HostOsInfo::isWindowsHost()
&& processImpl == ProcessImpl::QProcess
&& eventLoopMode == EventLoopMode::On;
const ProcessResult expectedResult = isFailingCombination ? ProcessResult::StartFailed
: ProcessResult::FinishedWithSuccess;
QCOMPARE(actualResult, expectedResult);
QCOMPARE(process.result(), ProcessResult::FinishedWithSuccess);
}
QTEST_GUILESS_MAIN(tst_Process)