summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Shienkov <denis.shienkov@gmail.com>2015-10-01 15:53:09 +0300
committerDenis Shienkov <denis.shienkov@gmail.com>2015-10-01 13:20:36 +0000
commit23c89518d1404a4db570fe41f3cc04451703e16f (patch)
treed5b8c0bc5543f5a9683f46f416c8cd90e342bfb2
parenta1655d6ccf3f82508286b471819cc5e5cb64ff44 (diff)
downloadqtserialport-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.cpp8
-rw-r--r--src/serialport/qserialport_unix.cpp1
-rw-r--r--tests/auto/qserialport/tst_qserialport.cpp45
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);