From 507625d984f9467b056e603560d62a2e4a56074d Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Tue, 28 Jul 2015 13:43:54 +0200 Subject: [PATCH] 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 Reviewed-by: Oswald Buddenhagen --- src/corelib/io/qprocess_win.cpp | 6 ++-- .../auto/corelib/io/qprocess/tst_qprocess.cpp | 31 +++++++++++++++++-- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp index cef961ecbde..eb88ded2c97 100644 --- a/src/corelib/io/qprocess_win.cpp +++ b/src/corelib/io/qprocess_win.cpp @@ -704,13 +704,15 @@ bool QProcessPrivate::waitForBytesWritten(int msecs) return true; // 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); timer.resetIncrements(); } // Check if we can read stderr. - if (bytesAvailableInChannel(&stderrChannel) != 0) { + if (stderrChannel.pipe[0] != INVALID_Q_PIPE + && bytesAvailableInChannel(&stderrChannel) != 0) { tryReadFromChannel(&stderrChannel); timer.resetIncrements(); } diff --git a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp index 7064b45d07b..11bdaec9c45 100644 --- a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp +++ b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp @@ -118,6 +118,7 @@ private slots: void setStandardOutputFile_data(); void setStandardOutputFile(); void setStandardOutputFile2(); + void setStandardOutputFileAndWaitForBytesWritten(); void setStandardOutputProcess_data(); void setStandardOutputProcess(); void removeFileWhileProcessIsRunning(); @@ -2068,6 +2069,26 @@ void tst_QProcess::setStandardOutputFile() 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 //----------------------------------------------------------------------------- @@ -2076,17 +2097,19 @@ void tst_QProcess::setStandardOutputFile() void tst_QProcess::setStandardOutputProcess_data() { QTest::addColumn("merged"); - QTest::newRow("separate") << false; - QTest::newRow("merged") << true; + QTest::addColumn("waitForBytesWritten"); + QTest::newRow("separate") << false << false; + QTest::newRow("separate with waitForBytesWritten") << false << true; + QTest::newRow("merged") << true << false; } void tst_QProcess::setStandardOutputProcess() { - QProcess source; QProcess sink; QFETCH(bool, merged); + QFETCH(bool, waitForBytesWritten); source.setReadChannelMode(merged ? QProcess::MergedChannels : QProcess::SeparateChannels); source.setStandardOutputProcess(&sink); @@ -2095,6 +2118,8 @@ void tst_QProcess::setStandardOutputProcess() QByteArray data("Hello, World"); source.write(data); + if (waitForBytesWritten) + source.waitForBytesWritten(); source.closeWriteChannel(); QPROCESS_VERIFY(source, waitForFinished()); QPROCESS_VERIFY(sink, waitForFinished());