summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorQt CI Bot <qt_ci_bot@qt-project.org>2021-03-25 15:25:08 +0000
committerQt CI Bot <qt_ci_bot@qt-project.org>2021-03-25 15:25:08 +0000
commit9145650302d3cfe7df0fbc2a11f5d8f5f867897d (patch)
tree127fbed0c253383f4427814c6948fd11dc0d83f8 /src
parent14eeb520858b624a2c9e09b5bd95ea8fb90a1f5a (diff)
parent82c67623db5d9708d2565bed2e8f68ad3dd190b1 (diff)
Merge integration refs/builds/qtci/dev/1616671507
Diffstat (limited to 'src')
-rw-r--r--src/corelib/io/qprocess_win.cpp112
-rw-r--r--src/corelib/io/qwindowspipereader.cpp3
-rw-r--r--src/corelib/io/qwindowspipereader_p.h2
-rw-r--r--src/corelib/io/qwindowspipewriter.cpp3
-rw-r--r--src/corelib/io/qwindowspipewriter_p.h52
5 files changed, 87 insertions, 85 deletions
diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp
index 84fbeb539d..7c261e7558 100644
--- a/src/corelib/io/qprocess_win.cpp
+++ b/src/corelib/io/qprocess_win.cpp
@@ -85,6 +85,46 @@ QProcessEnvironment QProcessEnvironment::systemEnvironment()
#if QT_CONFIG(process)
+namespace {
+struct QProcessPoller
+{
+ QProcessPoller(const QProcessPrivate &proc);
+
+ int poll(const QDeadlineTimer &deadline);
+
+ enum { maxHandles = 4 };
+ HANDLE handles[maxHandles];
+ DWORD handleCount = 0;
+};
+
+QProcessPoller::QProcessPoller(const QProcessPrivate &proc)
+{
+ if (proc.stdinChannel.writer)
+ handles[handleCount++] = proc.stdinChannel.writer->syncEvent();
+ if (proc.stdoutChannel.reader)
+ handles[handleCount++] = proc.stdoutChannel.reader->syncEvent();
+ if (proc.stderrChannel.reader)
+ handles[handleCount++] = proc.stderrChannel.reader->syncEvent();
+
+ handles[handleCount++] = proc.pid->hProcess;
+}
+
+int QProcessPoller::poll(const QDeadlineTimer &deadline)
+{
+ DWORD waitRet;
+
+ do {
+ waitRet = WaitForMultipleObjectsEx(handleCount, handles, FALSE,
+ deadline.remainingTime(), TRUE);
+ } while (waitRet == WAIT_IO_COMPLETION);
+
+ if (waitRet - WAIT_OBJECT_0 < handleCount)
+ return 1;
+
+ return (waitRet == WAIT_TIMEOUT) ? 0 : -1;
+}
+} // anonymous namespace
+
static bool qt_create_pipe(Q_PIPE *pipe, bool isInputPipe, BOOL defInheritFlag)
{
// Anomymous pipes do not support asynchronous I/O. Thus we
@@ -658,16 +698,22 @@ bool QProcessPrivate::drainOutputPipes()
bool QProcessPrivate::waitForReadyRead(const QDeadlineTimer &deadline)
{
- QIncrementalSleepTimer timer(deadline.remainingTime());
-
forever {
if (!writeBuffer.isEmpty() && !_q_canWrite())
return false;
- if (stdinChannel.writer && stdinChannel.writer->waitForWrite(0))
- timer.resetIncrements();
- if ((stdoutChannel.reader && stdoutChannel.reader->waitForReadyRead(0))
- || (stderrChannel.reader && stderrChannel.reader->waitForReadyRead(0)))
+ QProcessPoller poller(*this);
+ int ret = poller.poll(deadline);
+ if (ret < 0)
+ return false;
+ if (ret == 0)
+ break;
+
+ if (stdinChannel.writer)
+ stdinChannel.writer->checkForWrite();
+
+ if ((stdoutChannel.reader && stdoutChannel.reader->checkForReadyRead())
+ || (stderrChannel.reader && stderrChannel.reader->checkForReadyRead()))
return true;
if (!pid)
@@ -678,10 +724,6 @@ bool QProcessPrivate::waitForReadyRead(const QDeadlineTimer &deadline)
processFinished();
return readyReadEmitted;
}
-
- Sleep(timer.nextSleepTime());
- if (timer.hasTimedOut())
- break;
}
setError(QProcess::Timedout);
@@ -690,8 +732,6 @@ bool QProcessPrivate::waitForReadyRead(const QDeadlineTimer &deadline)
bool QProcessPrivate::waitForBytesWritten(const QDeadlineTimer &deadline)
{
- QIncrementalSleepTimer timer(deadline.remainingTime());
-
forever {
// If no write is pending, try to start one. However, at entry into
// the loop the write buffer can be empty to start with, in which
@@ -699,17 +739,24 @@ bool QProcessPrivate::waitForBytesWritten(const QDeadlineTimer &deadline)
if (pipeWriterBytesToWrite() == 0 && !_q_canWrite())
return false;
+ QProcessPoller poller(*this);
+ int ret = poller.poll(deadline);
+ if (ret < 0)
+ return false;
+ if (ret == 0)
+ break;
+
Q_ASSERT(stdinChannel.writer);
- if (stdinChannel.writer->waitForWrite(0))
+ if (stdinChannel.writer->checkForWrite())
return true;
// If we wouldn't write anything, check if we can read stdout.
- if (stdoutChannel.reader && stdoutChannel.reader->waitForReadyRead(0))
- timer.resetIncrements();
+ if (stdoutChannel.reader)
+ stdoutChannel.reader->checkForReadyRead();
// Check if we can read stderr.
- if (stderrChannel.reader && stderrChannel.reader->waitForReadyRead(0))
- timer.resetIncrements();
+ if (stderrChannel.reader)
+ stderrChannel.reader->checkForReadyRead();
// Check if the process died while reading.
if (!pid)
@@ -723,10 +770,6 @@ bool QProcessPrivate::waitForBytesWritten(const QDeadlineTimer &deadline)
processFinished();
return false;
}
-
- // Only wait for as long as we've been asked.
- if (timer.hasTimedOut())
- break;
}
setError(QProcess::Timedout);
@@ -739,30 +782,33 @@ bool QProcessPrivate::waitForFinished(const QDeadlineTimer &deadline)
qDebug("QProcessPrivate::waitForFinished(%lld)", deadline.remainingTime());
#endif
- QIncrementalSleepTimer timer(deadline.remainingTime());
-
forever {
if (!writeBuffer.isEmpty() && !_q_canWrite())
return false;
- if (stdinChannel.writer && stdinChannel.writer->waitForWrite(0))
- timer.resetIncrements();
- if (stdoutChannel.reader && stdoutChannel.reader->waitForReadyRead(0))
- timer.resetIncrements();
- if (stderrChannel.reader && stderrChannel.reader->waitForReadyRead(0))
- timer.resetIncrements();
+
+ QProcessPoller poller(*this);
+ int ret = poller.poll(deadline);
+ if (ret < 0)
+ return false;
+ if (ret == 0)
+ break;
+
+ if (stdinChannel.writer)
+ stdinChannel.writer->checkForWrite();
+ if (stdoutChannel.reader)
+ stdoutChannel.reader->checkForReadyRead();
+ if (stderrChannel.reader)
+ stderrChannel.reader->checkForReadyRead();
if (!pid)
return true;
- if (WaitForSingleObject(pid->hProcess, timer.nextSleepTime()) == WAIT_OBJECT_0) {
+ if (WaitForSingleObject(pid->hProcess, 0) == WAIT_OBJECT_0) {
drainOutputPipes();
if (pid)
processFinished();
return true;
}
-
- if (timer.hasTimedOut())
- break;
}
setError(QProcess::Timedout);
diff --git a/src/corelib/io/qwindowspipereader.cpp b/src/corelib/io/qwindowspipereader.cpp
index bf03737c39..638405ae75 100644
--- a/src/corelib/io/qwindowspipereader.cpp
+++ b/src/corelib/io/qwindowspipereader.cpp
@@ -51,7 +51,7 @@ QWindowsPipeReader::QWindowsPipeReader(QObject *parent)
: QObject(parent),
handle(INVALID_HANDLE_VALUE),
eventHandle(CreateEvent(NULL, FALSE, FALSE, NULL)),
- syncHandle(CreateEvent(NULL, FALSE, FALSE, NULL)),
+ syncHandle(CreateEvent(NULL, TRUE, FALSE, NULL)),
waitObject(NULL),
readBufferMaxSize(0),
actualReadBufferSize(0),
@@ -396,6 +396,7 @@ bool QWindowsPipeReader::event(QEvent *e)
*/
bool QWindowsPipeReader::consumePendingAndEmit(bool allowWinActPosting)
{
+ ResetEvent(syncHandle);
mutex.lock();
// Enable QEvent::WinEventAct posting.
diff --git a/src/corelib/io/qwindowspipereader_p.h b/src/corelib/io/qwindowspipereader_p.h
index a284f55b3b..8ae292da46 100644
--- a/src/corelib/io/qwindowspipereader_p.h
+++ b/src/corelib/io/qwindowspipereader_p.h
@@ -81,9 +81,11 @@ public:
qint64 read(char *data, qint64 maxlen);
bool canReadLine() const;
bool waitForReadyRead(int msecs);
+ bool checkForReadyRead() { return consumePendingAndEmit(false); }
bool waitForPipeClosed(int msecs);
bool isReadOperationActive() const;
+ HANDLE syncEvent() const { return syncHandle; }
Q_SIGNALS:
void winError(ulong, const QString &);
diff --git a/src/corelib/io/qwindowspipewriter.cpp b/src/corelib/io/qwindowspipewriter.cpp
index 5ed584c6e3..d711528c8f 100644
--- a/src/corelib/io/qwindowspipewriter.cpp
+++ b/src/corelib/io/qwindowspipewriter.cpp
@@ -49,7 +49,7 @@ QWindowsPipeWriter::QWindowsPipeWriter(HANDLE pipeWriteEnd, QObject *parent)
: QObject(parent),
handle(pipeWriteEnd),
eventHandle(CreateEvent(NULL, FALSE, FALSE, NULL)),
- syncHandle(CreateEvent(NULL, FALSE, FALSE, NULL)),
+ syncHandle(CreateEvent(NULL, TRUE, FALSE, NULL)),
waitObject(NULL),
pendingBytesWrittenValue(0),
lastError(ERROR_SUCCESS),
@@ -267,6 +267,7 @@ bool QWindowsPipeWriter::event(QEvent *e)
*/
bool QWindowsPipeWriter::consumePendingAndEmit(bool allowWinActPosting)
{
+ ResetEvent(syncHandle);
QMutexLocker locker(&mutex);
// Enable QEvent::WinEventAct posting.
diff --git a/src/corelib/io/qwindowspipewriter_p.h b/src/corelib/io/qwindowspipewriter_p.h
index b648d7b846..d33c2753a8 100644
--- a/src/corelib/io/qwindowspipewriter_p.h
+++ b/src/corelib/io/qwindowspipewriter_p.h
@@ -52,8 +52,6 @@
// We mean it.
//
-#include <QtCore/private/qglobal_p.h>
-#include <qelapsedtimer.h>
#include <qobject.h>
#include <qdeadlinetimer.h>
#include <qmutex.h>
@@ -63,54 +61,6 @@
QT_BEGIN_NAMESPACE
-#define SLEEPMIN 10
-#define SLEEPMAX 500
-
-class QIncrementalSleepTimer
-{
-
-public:
- QIncrementalSleepTimer(int msecs)
- : totalTimeOut(msecs)
- , nextSleep(qMin(SLEEPMIN, totalTimeOut))
- {
- if (totalTimeOut == -1)
- nextSleep = SLEEPMIN;
- timer.start();
- }
-
- int nextSleepTime()
- {
- int tmp = nextSleep;
- nextSleep = qMin(nextSleep * 2, qMin(SLEEPMAX, timeLeft()));
- return tmp;
- }
-
- int timeLeft() const
- {
- if (totalTimeOut == -1)
- return SLEEPMAX;
- return qMax(int(totalTimeOut - timer.elapsed()), 0);
- }
-
- bool hasTimedOut() const
- {
- if (totalTimeOut == -1)
- return false;
- return timer.elapsed() >= totalTimeOut;
- }
-
- void resetIncrements()
- {
- nextSleep = qMin(SLEEPMIN, timeLeft());
- }
-
-private:
- QElapsedTimer timer;
- int totalTimeOut;
- int nextSleep;
-};
-
class Q_CORE_EXPORT QWindowsPipeWriter : public QObject
{
Q_OBJECT
@@ -121,8 +71,10 @@ public:
bool write(const QByteArray &ba);
void stop();
bool waitForWrite(int msecs);
+ bool checkForWrite() { return consumePendingAndEmit(false); }
bool isWriteOperationActive() const;
qint64 bytesToWrite() const;
+ HANDLE syncEvent() const { return syncHandle; }
Q_SIGNALS:
void canWrite();