diff options
author | Denis Shienkov <denis.shienkov@gmail.com> | 2015-10-01 15:53:09 +0300 |
---|---|---|
committer | Denis Shienkov <denis.shienkov@gmail.com> | 2015-10-01 13:20:36 +0000 |
commit | 23c89518d1404a4db570fe41f3cc04451703e16f (patch) | |
tree | d5b8c0bc5543f5a9683f46f416c8cd90e342bfb2 | |
parent | a1655d6ccf3f82508286b471819cc5e5cb64ff44 (diff) | |
download | qtserialport-23c89518d1404a4db570fe41f3cc04451703e16f.tar.gz |
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.
Change-Id: I723253fb153a1144009579141fa0ce1aca93b648
Reviewed-by: Sergey Belyashov <Sergey.Belyashov@gmail.com>
Reviewed-by: Denis Shienkov <denis.shienkov@gmail.com>
-rw-r--r-- | src/serialport/qserialport.cpp | 8 | ||||
-rw-r--r-- | src/serialport/qserialport_unix.cpp | 1 | ||||
-rw-r--r-- | tests/auto/qserialport/tst_qserialport.cpp | 45 |
3 files changed, 53 insertions, 1 deletions
diff --git a/src/serialport/qserialport.cpp b/src/serialport/qserialport.cpp index 690eb65..369be62 100644 --- a/src/serialport/qserialport.cpp +++ b/src/serialport/qserialport.cpp @@ -1409,7 +1409,7 @@ qint64 QSerialPort::readData(char *data, qint64 maxSize) Q_UNUSED(data); Q_UNUSED(maxSize); -#ifdef Q_OS_WIN32 +#if defined(Q_OS_WIN32) // We need try to start async reading to read a remainder from a driver's queue // in case we have a limited read buffer size. Because the read notification can // be stalled since Windows do not re-triggered an EV_RXCHAR event if a driver's @@ -1417,6 +1417,12 @@ qint64 QSerialPort::readData(char *data, qint64 maxSize) Q_D(QSerialPort); if (d->readBufferMaxSize || d->flowControl == QSerialPort::HardwareControl) d->startAsyncRead(); +#elif defined(Q_OS_UNIX) + // 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. + Q_D(QSerialPort); + if (d->readBufferMaxSize && !d->isReadNotificationEnabled()) + d->setReadNotificationEnabled(true); #endif // return 0 indicating there may be more data in the future diff --git a/src/serialport/qserialport_unix.cpp b/src/serialport/qserialport_unix.cpp index 4659a18..c243319 100644 --- a/src/serialport/qserialport_unix.cpp +++ b/src/serialport/qserialport_unix.cpp @@ -727,6 +727,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 d50afe9..3a62bfa 100644 --- a/tests/auto/qserialport/tst_qserialport.cpp +++ b/tests/auto/qserialport/tst_qserialport.cpp @@ -120,6 +120,8 @@ private slots: void asynchronousWriteByTimer_data(); void asynchronousWriteByTimer(); + void asyncReadWithLimitedReadBufferSize(); + void readBufferOverflow(); void readAfterInputClear(); void synchronousReadWriteAfterAsynchronousReadWrite(); @@ -808,6 +810,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, &QSerialPort::readyRead, this, &AsyncReader2::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); |