fix assertion in QProcess/Win

Do not call bytesAvailableInChannel if the source pipe end is
invalid. This is the case when redirecting channels on Windows.
The assertions in bytesAvailableInChannel were triggered whenever
an output process or output file was set and waitForBytesWritten
was called.

Task-number: QTBUG-45548
Change-Id: I225dfea2c5e27e122f75008a3a06d425554e00fe
Reviewed-by: Alex Trotsenko <alex1973tr@gmail.com>
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com>
This commit is contained in:
Joerg Bornemann 2015-07-28 13:43:54 +02:00
parent ec4426fada
commit 507625d984
2 changed files with 32 additions and 5 deletions

View File

@ -704,13 +704,15 @@ bool QProcessPrivate::waitForBytesWritten(int msecs)
return true; return true;
// If we wouldn't write anything, check if we can read stdout. // If we wouldn't write anything, check if we can read stdout.
if (bytesAvailableInChannel(&stdoutChannel) != 0) { if (stdoutChannel.pipe[0] != INVALID_Q_PIPE
&& bytesAvailableInChannel(&stdoutChannel) != 0) {
tryReadFromChannel(&stdoutChannel); tryReadFromChannel(&stdoutChannel);
timer.resetIncrements(); timer.resetIncrements();
} }
// Check if we can read stderr. // Check if we can read stderr.
if (bytesAvailableInChannel(&stderrChannel) != 0) { if (stderrChannel.pipe[0] != INVALID_Q_PIPE
&& bytesAvailableInChannel(&stderrChannel) != 0) {
tryReadFromChannel(&stderrChannel); tryReadFromChannel(&stderrChannel);
timer.resetIncrements(); timer.resetIncrements();
} }

View File

@ -118,6 +118,7 @@ private slots:
void setStandardOutputFile_data(); void setStandardOutputFile_data();
void setStandardOutputFile(); void setStandardOutputFile();
void setStandardOutputFile2(); void setStandardOutputFile2();
void setStandardOutputFileAndWaitForBytesWritten();
void setStandardOutputProcess_data(); void setStandardOutputProcess_data();
void setStandardOutputProcess(); void setStandardOutputProcess();
void removeFileWhileProcessIsRunning(); void removeFileWhileProcessIsRunning();
@ -2068,6 +2069,26 @@ void tst_QProcess::setStandardOutputFile()
QCOMPARE(all.size(), expectedsize); QCOMPARE(all.size(), expectedsize);
} }
void tst_QProcess::setStandardOutputFileAndWaitForBytesWritten()
{
static const char testdata[] = "Test data.";
QFile file("data");
QProcess process;
process.setStandardOutputFile(file.fileName());
process.start("testProcessEcho2/testProcessEcho2");
process.write(testdata, sizeof testdata);
process.waitForBytesWritten();
QPROCESS_VERIFY(process, waitForFinished());
// open the file again and verify the data
QVERIFY(file.open(QIODevice::ReadOnly));
QByteArray all = file.readAll();
file.close();
QCOMPARE(all, QByteArray::fromRawData(testdata, sizeof testdata - 1));
}
#endif #endif
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -2076,17 +2097,19 @@ void tst_QProcess::setStandardOutputFile()
void tst_QProcess::setStandardOutputProcess_data() void tst_QProcess::setStandardOutputProcess_data()
{ {
QTest::addColumn<bool>("merged"); QTest::addColumn<bool>("merged");
QTest::newRow("separate") << false; QTest::addColumn<bool>("waitForBytesWritten");
QTest::newRow("merged") << true; QTest::newRow("separate") << false << false;
QTest::newRow("separate with waitForBytesWritten") << false << true;
QTest::newRow("merged") << true << false;
} }
void tst_QProcess::setStandardOutputProcess() void tst_QProcess::setStandardOutputProcess()
{ {
QProcess source; QProcess source;
QProcess sink; QProcess sink;
QFETCH(bool, merged); QFETCH(bool, merged);
QFETCH(bool, waitForBytesWritten);
source.setReadChannelMode(merged ? QProcess::MergedChannels : QProcess::SeparateChannels); source.setReadChannelMode(merged ? QProcess::MergedChannels : QProcess::SeparateChannels);
source.setStandardOutputProcess(&sink); source.setStandardOutputProcess(&sink);
@ -2095,6 +2118,8 @@ void tst_QProcess::setStandardOutputProcess()
QByteArray data("Hello, World"); QByteArray data("Hello, World");
source.write(data); source.write(data);
if (waitForBytesWritten)
source.waitForBytesWritten();
source.closeWriteChannel(); source.closeWriteChannel();
QPROCESS_VERIFY(source, waitForFinished()); QPROCESS_VERIFY(source, waitForFinished());
QPROCESS_VERIFY(sink, waitForFinished()); QPROCESS_VERIFY(sink, waitForFinished());