summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoerg Bornemann <joerg.bornemann@digia.com>2013-04-30 15:31:46 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-05-07 15:02:34 +0200
commit28ee554b37be39c03c231e7b857f71163dc6ea73 (patch)
tree4ec16a30d8bda651b585d2af526abe479d708f2e
parent36b7c3cd2bee59964ea07e9677a5a789676f2eae (diff)
QProcess/Win: drain output pipes on process finish
If a process dies before all output is read into the internal buffer of QProcess, we might lose data. Therefore we must drain the output pipes like we already do in the synchronous wait functions. Task-number: QTBUG-30843 Change-Id: I8bbc5265275c9ebd33218ba600267ae87d93ed61 Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@digia.com> Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com>
-rw-r--r--src/corelib/io/qprocess.cpp1
-rw-r--r--src/corelib/io/qprocess_p.h1
-rw-r--r--src/corelib/io/qprocess_win.cpp22
-rw-r--r--tests/auto/corelib/io/qprocess/tst_qprocess.cpp34
4 files changed, 47 insertions, 11 deletions
diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp
index 59b6db7c79..3de1345585 100644
--- a/src/corelib/io/qprocess.cpp
+++ b/src/corelib/io/qprocess.cpp
@@ -1006,6 +1006,7 @@ bool QProcessPrivate::_q_processDied()
return false;
#endif
#ifdef Q_OS_WIN
+ drainOutputPipes();
if (processFinishedNotifier)
processFinishedNotifier->setEnabled(false);
#endif
diff --git a/src/corelib/io/qprocess_p.h b/src/corelib/io/qprocess_p.h
index f658e54d4b..bd6943c8d0 100644
--- a/src/corelib/io/qprocess_p.h
+++ b/src/corelib/io/qprocess_p.h
@@ -317,6 +317,7 @@ public:
bool waitForDeadChild();
#endif
#ifdef Q_OS_WIN
+ bool drainOutputPipes();
void flushPipeWriter();
qint64 pipeWriterBytesToWrite() const;
#endif
diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp
index 0f36c3adbf..7776852277 100644
--- a/src/corelib/io/qprocess_win.cpp
+++ b/src/corelib/io/qprocess_win.cpp
@@ -625,21 +625,21 @@ bool QProcessPrivate::waitForStarted(int)
return false;
}
-static bool drainOutputPipes(QProcessPrivate *d)
+bool QProcessPrivate::drainOutputPipes()
{
- if (!d->stdoutReader && !d->stderrReader)
+ if (!stdoutReader && !stderrReader)
return false;
bool readyReadEmitted = false;
forever {
bool readOperationActive = false;
- if (d->stdoutReader) {
- readyReadEmitted |= d->stdoutReader->waitForReadyRead(0);
- readOperationActive = d->stdoutReader->isReadOperationActive();
+ if (stdoutReader) {
+ readyReadEmitted |= stdoutReader->waitForReadyRead(0);
+ readOperationActive = stdoutReader->isReadOperationActive();
}
- if (d->stderrReader) {
- readyReadEmitted |= d->stderrReader->waitForReadyRead(0);
- readOperationActive |= d->stderrReader->isReadOperationActive();
+ if (stderrReader) {
+ readyReadEmitted |= stderrReader->waitForReadyRead(0);
+ readOperationActive |= stderrReader->isReadOperationActive();
}
if (!readOperationActive)
break;
@@ -669,7 +669,7 @@ bool QProcessPrivate::waitForReadyRead(int msecs)
if (!pid)
return false;
if (WaitForSingleObject(pid->hProcess, 0) == WAIT_OBJECT_0) {
- bool readyReadEmitted = drainOutputPipes(this);
+ bool readyReadEmitted = drainOutputPipes();
_q_processDied();
return readyReadEmitted;
}
@@ -772,12 +772,12 @@ bool QProcessPrivate::waitForFinished(int msecs)
timer.resetIncrements();
if (!pid) {
- drainOutputPipes(this);
+ drainOutputPipes();
return true;
}
if (WaitForSingleObject(pid->hProcess, timer.nextSleepTime()) == WAIT_OBJECT_0) {
- drainOutputPipes(this);
+ drainOutputPipes();
_q_processDied();
return true;
}
diff --git a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp
index f01e319872..613bfd5c17 100644
--- a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp
+++ b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp
@@ -152,6 +152,7 @@ private slots:
void invalidProgramString_data();
void invalidProgramString();
void onlyOneStartedSignal();
+ void finishProcessBeforeReadingDone();
// keep these at the end, since they use lots of processes and sometimes
// caused obscure failures to occur in tests that followed them (esp. on the Mac)
@@ -2168,6 +2169,39 @@ void tst_QProcess::onlyOneStartedSignal()
QCOMPARE(spyFinished.count(), 1);
}
+//-----------------------------------------------------------------------------
+
+class BlockOnReadStdOut : public QObject
+{
+ Q_OBJECT
+public:
+ BlockOnReadStdOut(QProcess *process)
+ {
+ connect(process, SIGNAL(readyReadStandardOutput()), SLOT(block()));
+ }
+
+public slots:
+ void block()
+ {
+ QThread::sleep(1);
+ }
+};
+
+void tst_QProcess::finishProcessBeforeReadingDone()
+{
+ QProcess process;
+ BlockOnReadStdOut blocker(&process);
+ QEventLoop loop;
+ connect(&process, SIGNAL(finished(int)), &loop, SLOT(quit()));
+ process.start("testProcessOutput/testProcessOutput");
+ QVERIFY(process.waitForStarted());
+ loop.exec();
+ QStringList lines = QString::fromLocal8Bit(process.readAllStandardOutput()).split(
+ QRegExp(QStringLiteral("[\r\n]")), QString::SkipEmptyParts);
+ QVERIFY(!lines.isEmpty());
+ QCOMPARE(lines.last(), QStringLiteral("10239 -this is a number"));
+}
+
#endif //QT_NO_PROCESS
QTEST_MAIN(tst_QProcess)