From ba204a95e6650a6992510530c1fa5a4dac2b5da8 Mon Sep 17 00:00:00 2001 From: Denis Shienkov Date: Thu, 1 Oct 2015 15:53:09 +0300 Subject: Fix stalling of reading with the limited buffer size on *nix When the read buffer with a limited size is used, the read notifier becomes disabled when the buffer completely is filled. The notifier should be enabled again when several bytes were read from the read buffer. (cherry-picked from 23c89518d1404a4db570fe41f3cc04451703e16f) Change-Id: I723253fb153a1144009579141fa0ce1aca93b648 Reviewed-by: Denis Shienkov --- src/serialport/qserialport_unix.cpp | 8 +++++- tests/auto/qserialport/tst_qserialport.cpp | 45 ++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/src/serialport/qserialport_unix.cpp b/src/serialport/qserialport_unix.cpp index 7c18d08..df8e9cb 100644 --- a/src/serialport/qserialport_unix.cpp +++ b/src/serialport/qserialport_unix.cpp @@ -395,7 +395,12 @@ bool QSerialPortPrivate::setBreakEnabled(bool set) qint64 QSerialPortPrivate::readData(char *data, qint64 maxSize) { - return readBuffer.read(data, maxSize); + const qint64 result = readBuffer.read(data, maxSize); + // We need try to re-trigger the read notification to read a remainder from a + // driver's queue in case we have a limited read buffer size. + if (d->readBufferMaxSize && result > 0 && !d->isReadNotificationEnabled()) + d->setReadNotificationEnabled(true); + return result; } bool QSerialPortPrivate::waitForReadyRead(int msecs) @@ -744,6 +749,7 @@ bool QSerialPortPrivate::readNotification() if (bytesToRead == 0) { // Buffer is full. User must read data from the buffer // before we can read more from the port. + setReadNotificationEnabled(false); return false; } } diff --git a/tests/auto/qserialport/tst_qserialport.cpp b/tests/auto/qserialport/tst_qserialport.cpp index 74eec3d..134c7d7 100644 --- a/tests/auto/qserialport/tst_qserialport.cpp +++ b/tests/auto/qserialport/tst_qserialport.cpp @@ -129,6 +129,8 @@ private slots: void asynchronousWriteByTimer_data(); void asynchronousWriteByTimer(); + void asyncReadWithLimitedReadBufferSize(); + void readBufferOverflow(); void readAfterInputClear(); void synchronousReadWriteAfterAsynchronousReadWrite(); @@ -807,6 +809,49 @@ void tst_QSerialPort::asynchronousWriteByTimer() QCOMPARE(receiverPort.readAll(), alphabetArray); } +class AsyncReader2 : public QObject +{ + Q_OBJECT +public: + explicit AsyncReader2(QSerialPort &port, const QByteArray &expectedData) + : serialPort(port), expectedData(expectedData) + { + connect(&serialPort, SIGNAL(readyRead()), this, SLOT(receive())); + } + +private slots: + void receive() + { + receivedData.append(serialPort.readAll()); + if (receivedData == expectedData) + tst_QSerialPort::exitLoop(); + } + +private: + QSerialPort &serialPort; + const QByteArray expectedData; + QByteArray receivedData; +}; + +void tst_QSerialPort::asyncReadWithLimitedReadBufferSize() +{ + QSerialPort senderPort(m_senderPortName); + QVERIFY(senderPort.open(QSerialPort::WriteOnly)); + + QSerialPort receiverPort(m_receiverPortName); + QVERIFY(receiverPort.open(QSerialPort::ReadOnly)); + + receiverPort.setReadBufferSize(1); + QCOMPARE(receiverPort.readBufferSize(), qint64(1)); + + AsyncReader2 reader(receiverPort, alphabetArray); + + QCOMPARE(senderPort.write(alphabetArray), qint64(alphabetArray.size())); + + enterLoop(1); + QVERIFY2(!timeout(), "Timed out when waiting for the read or write."); +} + void tst_QSerialPort::readBufferOverflow() { QSerialPort senderPort(m_senderPortName); -- cgit v1.2.1