diff options
author | Alex Blasche <alexander.blasche@theqtcompany.com> | 2016-07-18 13:39:10 +0200 |
---|---|---|
committer | Timur Pocheptsov <timur.pocheptsov@theqtcompany.com> | 2016-07-19 07:26:17 +0000 |
commit | b00651a9e6ca00c31dd0601d3cdbe1db623c6204 (patch) | |
tree | fc63e96f26c683fbc058823263f82405884ca32f /src | |
parent | d20e2e84ec2edd770c830fe2c399b4c76321d187 (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>
Diffstat (limited to 'src')
-rw-r--r-- | src/bluetooth/qbluetoothsocket_bluez.cpp | 50 |
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 { |