forked from qt-creator/qt-creator
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:
@@ -1865,43 +1865,45 @@ void Process::setWriteData(const QByteArray &writeData)
|
|||||||
|
|
||||||
void Process::runBlocking(EventLoopMode eventLoopMode)
|
void Process::runBlocking(EventLoopMode eventLoopMode)
|
||||||
{
|
{
|
||||||
// Attach a dynamic property with info about blocking type
|
|
||||||
d->storeEventLoopDebugInfo(int(eventLoopMode));
|
|
||||||
|
|
||||||
QDateTime startTime;
|
QDateTime startTime;
|
||||||
static const int blockingThresholdMs = qtcEnvironmentVariableIntValue("QTC_PROCESS_THRESHOLD");
|
static const int blockingThresholdMs = qtcEnvironmentVariableIntValue("QTC_PROCESS_THRESHOLD");
|
||||||
if (blockingThresholdMs > 0 && isMainThread())
|
|
||||||
startTime = QDateTime::currentDateTime();
|
|
||||||
Process::start();
|
|
||||||
|
|
||||||
// Remove the dynamic property so that it's not reused in subseqent start()
|
auto starter = [this, eventLoopMode, &startTime] {
|
||||||
d->storeEventLoopDebugInfo({});
|
// Attach a dynamic property with info about blocking type
|
||||||
|
d->storeEventLoopDebugInfo(int(eventLoopMode));
|
||||||
|
|
||||||
|
if (blockingThresholdMs > 0 && isMainThread())
|
||||||
|
startTime = QDateTime::currentDateTime();
|
||||||
|
start();
|
||||||
|
|
||||||
|
// Remove the dynamic property so that it's not reused in subseqent start()
|
||||||
|
d->storeEventLoopDebugInfo({});
|
||||||
|
};
|
||||||
|
|
||||||
if (eventLoopMode == EventLoopMode::On) {
|
if (eventLoopMode == EventLoopMode::On) {
|
||||||
// Start failure is triggered immediately if the executable cannot be found in the path.
|
QTimer timer(this);
|
||||||
// In this case the process is left in NotRunning state.
|
connect(&timer, &QTimer::timeout, d, &ProcessPrivate::slotTimeout);
|
||||||
// Do not start the event loop in that case.
|
timer.setInterval(1000);
|
||||||
if (state() == QProcess::Starting) {
|
timer.start();
|
||||||
QTimer timer(this);
|
|
||||||
connect(&timer, &QTimer::timeout, d, &ProcessPrivate::slotTimeout);
|
|
||||||
timer.setInterval(1000);
|
|
||||||
timer.start();
|
|
||||||
#ifdef QT_GUI_LIB
|
#ifdef QT_GUI_LIB
|
||||||
if (isGuiEnabled())
|
if (isGuiEnabled())
|
||||||
QGuiApplication::setOverrideCursor(Qt::WaitCursor);
|
QGuiApplication::setOverrideCursor(Qt::WaitCursor);
|
||||||
#endif
|
#endif
|
||||||
QEventLoop eventLoop(this);
|
QEventLoop eventLoop(this);
|
||||||
QTC_ASSERT(!d->m_eventLoop, return);
|
QTC_ASSERT(!d->m_eventLoop, return);
|
||||||
d->m_eventLoop = &eventLoop;
|
d->m_eventLoop = &eventLoop;
|
||||||
eventLoop.exec(QEventLoop::ExcludeUserInputEvents);
|
// Queue the call to start() so that it's executed after the nested event loop is started,
|
||||||
d->m_eventLoop = nullptr;
|
// otherwise it fails on Windows with QProcessImpl. See QTCREATORBUG-30066.
|
||||||
timer.stop();
|
QMetaObject::invokeMethod(this, starter, Qt::QueuedConnection);
|
||||||
|
eventLoop.exec(QEventLoop::ExcludeUserInputEvents);
|
||||||
|
d->m_eventLoop = nullptr;
|
||||||
|
timer.stop();
|
||||||
#ifdef QT_GUI_LIB
|
#ifdef QT_GUI_LIB
|
||||||
if (isGuiEnabled())
|
if (isGuiEnabled())
|
||||||
QGuiApplication::restoreOverrideCursor();
|
QGuiApplication::restoreOverrideCursor();
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
|
starter();
|
||||||
if (!waitForStarted(d->m_maxHangTimerCount * 1000)) {
|
if (!waitForStarted(d->m_maxHangTimerCount * 1000)) {
|
||||||
d->m_result = ProcessResult::StartFailed;
|
d->m_result = ProcessResult::StartFailed;
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -1595,17 +1595,7 @@ void tst_Process::eventLoopMode()
|
|||||||
subConfig.setupSubProcess(&process);
|
subConfig.setupSubProcess(&process);
|
||||||
process.setProcessImpl(processImpl);
|
process.setProcessImpl(processImpl);
|
||||||
process.runBlocking(eventLoopMode);
|
process.runBlocking(eventLoopMode);
|
||||||
const ProcessResult actualResult = process.result();
|
QCOMPARE(process.result(), ProcessResult::FinishedWithSuccess);
|
||||||
|
|
||||||
// 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QTEST_GUILESS_MAIN(tst_Process)
|
QTEST_GUILESS_MAIN(tst_Process)
|
||||||
|
|||||||
Reference in New Issue
Block a user