Close socket descriptor when QBluetoothSocketBluez is destroyed

There are two private QBluetoothSocket backends on Linux:
- QBluetoothSocketBluez is native linux socket implementation
  It is always used by the linux QBluetoothServer, and by
  QBluetoothSocket if Bluez version is < 5.46
- QBluetoothSocketBluezDbus used by QBluetoothSocket when
  Bluez >= 5.46

Leaving the native socket unclosed leaks the resource and eventually
we may run out of descriptors. This is reproducible by creating and
destroying QBluetoothServer instances in a loop.

As a related drive-by:
- Fix bluetooth socket autotest version check. DBus socket is used
  with bluez 5.46+ (for clarity: DBus lowenergycontroller
  is used with bluez 5.42+). This is needed for the test to pass
  with Bluez < 5.46
- Add a clarifying comment on socket close()

Fixes: QTBUG-103067
Change-Id: Idc38c743be09e559ea82bf09c2f9e44e4b80d666
Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
Reviewed-by: Alex Blasche <alexander.blasche@qt.io>
(cherry picked from commit 3aafe9d5ce)
This commit is contained in:
Juha Vuolle 2022-05-13 07:48:40 +03:00
parent ca96a42035
commit 336bd4ff9e
3 changed files with 10 additions and 2 deletions

View File

@ -791,6 +791,9 @@ void QBluetoothSocket::close()
Set the socket to use \a socketDescriptor with a type of \a socketType,
which is in state, \a socketState, and mode, \a openMode.
The set socket descriptor is considered owned by the QBluetoothSocket
and may be e.g. closed once finished.
Returns true on success
*/

View File

@ -75,6 +75,10 @@ QBluetoothSocketPrivateBluez::~QBluetoothSocketPrivateBluez()
readNotifier = nullptr;
delete connectWriteNotifier;
connectWriteNotifier = nullptr;
// If the socket wasn't closed/aborted make sure we free the socket file descriptor
if (socket != -1)
QT_CLOSE(socket);
}
bool QBluetoothSocketPrivateBluez::ensureNativeSocket(QBluetoothServiceInfo::Protocol type)
@ -658,6 +662,8 @@ qint64 QBluetoothSocketPrivateBluez::readData(char *data, qint64 maxSize)
void QBluetoothSocketPrivateBluez::close()
{
// If we have pending data on the write buffer, wait until it has been written,
// after which this close() will be called again
if (txBuffer.size() > 0)
connectWriteNotifier->setEnabled(true);
else

View File

@ -511,7 +511,7 @@ void tst_QBluetoothSocket::tst_preferredSecurityFlags()
#elif QT_CONFIG(bluez)
// The bluezdbus socket uses "NoSecurity" by default, whereas the non-dbus bluez
// socket uses "Authorization" by default
if (bluetoothdVersion() >= QVersionNumber(5, 42))
if (bluetoothdVersion() >= QVersionNumber(5, 46))
QCOMPARE(socket.preferredSecurityFlags(), QBluetooth::Security::NoSecurity);
else
QCOMPARE(socket.preferredSecurityFlags(), QBluetooth::Security::Authorization);
@ -577,4 +577,3 @@ void tst_QBluetoothSocket::tst_unsupportedProtocolError()
QTEST_MAIN(tst_QBluetoothSocket)
#include "tst_qbluetoothsocket.moc"