summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Blasche <alexander.blasche@theqtcompany.com>2016-07-18 13:39:10 +0200
committerTimur Pocheptsov <timur.pocheptsov@theqtcompany.com>2016-07-19 07:26:17 +0000
commitb00651a9e6ca00c31dd0601d3cdbe1db623c6204 (patch)
treefc63e96f26c683fbc058823263f82405884ca32f
parentd20e2e84ec2edd770c830fe2c399b4c76321d187 (diff)
Improve failed ::write() handling in QBluetoothSocket
When the Bluetooth connection is flooded with information, EAGAIN is returned. So far this was considered an unrecoverable error which is not consistent with the meaning of EAGAIN. In buffered mode we'll put the data back into the buffer and in unbuffered mode the QIODevice::write() call returns 0 which leaves the developer the option to retry. At the same time this patch ensures that write() calls always return the actual number of written bytes and not the amount of bytes the caller asked for to be written. Partial writes in buffered mode are returned to the buffer too. Task-number: QTBUG-54475 Change-Id: Iffc7980d2477e1fc0b45808431af6b7fecd38ded Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> Reviewed-by: Timur Pocheptsov <timur.pocheptsov@theqtcompany.com>
-rw-r--r--src/bluetooth/qbluetoothsocket_bluez.cpp50
1 files changed, 37 insertions, 13 deletions
diff --git a/src/bluetooth/qbluetoothsocket_bluez.cpp b/src/bluetooth/qbluetoothsocket_bluez.cpp
index cfcba8af..803df6df 100644
--- a/src/bluetooth/qbluetoothsocket_bluez.cpp
+++ b/src/bluetooth/qbluetoothsocket_bluez.cpp
@@ -48,6 +48,7 @@
#include "bluez/bluez_data_p.h"
#include <qplatformdefs.h>
+#include <QtCore/private/qcore_unix_p.h>
#include <QtCore/QLoggingCategory>
@@ -241,13 +242,28 @@ void QBluetoothSocketPrivate::_q_writeNotify()
char buf[1024];
int size = txBuffer.read(buf, 1024);
-
- if (::write(socket, buf, size) != size) {
- errorString = QBluetoothSocket::tr("Network Error");
- q->setSocketError(QBluetoothSocket::NetworkError);
- }
- else {
- emit q->bytesWritten(size);
+ int writtenBytes = qt_safe_write(socket, buf, size);
+ if (writtenBytes < 0) {
+ switch (errno) {
+ case EAGAIN:
+ writtenBytes = 0;
+ txBuffer.ungetBlock(buf, size);
+ break;
+ default:
+ // every other case returns error
+ errorString = QBluetoothSocket::tr("Network Error: %1");
+ errorString.arg(qt_error_string(errno));
+ q->setSocketError(QBluetoothSocket::NetworkError);
+ break;
+ }
+ } else {
+ if (writtenBytes < size) {
+ // add remainder back to buffer
+ char* remainder = buf + writtenBytes;
+ txBuffer.ungetBlock(remainder, size - writtenBytes);
+ }
+ if (writtenBytes > 0)
+ emit q->bytesWritten(writtenBytes);
}
if (txBuffer.size()) {
@@ -484,15 +500,23 @@ qint64 QBluetoothSocketPrivate::writeData(const char *data, qint64 maxSize)
}
if (q->openMode() & QIODevice::Unbuffered) {
- if (::write(socket, data, maxSize) != maxSize) {
- errorString = QBluetoothSocket::tr("Network Error");
- q->setSocketError(QBluetoothSocket::NetworkError);
- return -1;
+ int sz = ::qt_safe_write(socket, data, maxSize);
+ if (sz < 0) {
+ switch (errno) {
+ case EAGAIN:
+ sz = 0;
+ break;
+ default:
+ errorString = QBluetoothSocket::tr("Network Error: %1");
+ errorString.arg(qt_error_string(errno));
+ q->setSocketError(QBluetoothSocket::NetworkError);
+ }
}
- emit q->bytesWritten(maxSize);
+ if (sz > 0)
+ emit q->bytesWritten(sz);
- return maxSize;
+ return sz;
}
else {