QProcess/Unix: fix possible race condition inside waitForXXX() loops

Calling QCoreApplication::processEvents() from a slot connected to the
readyRead() signal might cause desynchronization in the waitForXXX()
loop, if the process has been finished during the event processing.
This results in unnecessary timeouts and causes waitForFinished() to
fail unexpectedly.

So, a proposed solution is to check the state on each iteration of the
loop, as Windows implementation does.

Given issue is tested by tst_QProcess::processEventsInAReadyReadSlot()
which was unstable in CI.

Task-number: QTBUG-62584
Change-Id: I7438cf67b0163bbf49314008a9dc660c0977fb7b
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Alex Trotsenko 2017-08-17 09:16:16 +03:00 committed by Edward Welbourne
parent 1cd91a0ee5
commit 362466c7d2

View File

@ -792,6 +792,10 @@ bool QProcessPrivate::waitForReadyRead(int msecs)
if (qt_pollfd_check(poller.stdinPipe(), POLLOUT))
_q_canWrite();
// Signals triggered by I/O may have stopped this process:
if (processState == QProcess::NotRunning)
return false;
if (qt_pollfd_check(poller.forkfd(), POLLIN)) {
if (_q_processDied())
return false;
@ -838,6 +842,10 @@ bool QProcessPrivate::waitForBytesWritten(int msecs)
if (qt_pollfd_check(poller.stderrPipe(), POLLIN))
_q_canReadStandardError();
// Signals triggered by I/O may have stopped this process:
if (processState == QProcess::NotRunning)
return false;
if (qt_pollfd_check(poller.forkfd(), POLLIN)) {
if (_q_processDied())
return false;
@ -883,6 +891,10 @@ bool QProcessPrivate::waitForFinished(int msecs)
if (qt_pollfd_check(poller.stderrPipe(), POLLIN))
_q_canReadStandardError();
// Signals triggered by I/O may have stopped this process:
if (processState == QProcess::NotRunning)
return true;
if (qt_pollfd_check(poller.forkfd(), POLLIN)) {
if (_q_processDied())
return true;