diff options
author | Juha Vuolle <juha.vuolle@insta.fi> | 2022-03-09 11:44:27 +0200 |
---|---|---|
committer | Juha Vuolle <juha.vuolle@insta.fi> | 2022-03-21 08:17:39 +0200 |
commit | b5ff4334a4cd3232f74d8dd67133fadce73eca1f (patch) | |
tree | c2ea036ce48a6cc943ee200e5a04f5b6361d76d4 | |
parent | 2b3b5c899ebdb0fc11273af7370804f5f03ad9e8 (diff) |
Fix Android bluetooth server assert when disposed of quickly
If one initiates a QBluetoothServer::listen() and then quickly destroys
the server, the internal ServerAcceptanceThread asserts in it's
destructor because isRunning() is still true. This happens in spite of
a close() call, which may have been called manually or by the server
destructor.
This seems to happen when the Java-side run() is in the middle of
synchronous "listenUsing*RfcommWithServiceRecord()" call
and therefore the interruption and stop is not immediate but will
happen only after that function returns.
This commit waits for the thread to finish (with a timeout limit).
Fixes: QTBUG-101586
Change-Id: I59f9657ff5be1893ec8ab3757a626446769e8cad
Reviewed-by: Alex Blasche <alexander.blasche@qt.io>
(cherry picked from commit ac0dca699f833225ae9bf767ee350092faa6069c)
Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
-rw-r--r-- | src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothSocketServer.java | 25 |
1 files changed, 24 insertions, 1 deletions
diff --git a/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothSocketServer.java b/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothSocketServer.java index d2917f1a..ef446301 100644 --- a/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothSocketServer.java +++ b/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothSocketServer.java @@ -106,6 +106,9 @@ public class QtBluetoothSocketServer extends Thread return; } + if (isInterrupted()) // close() may have been called + return; + BluetoothSocket s; if (m_serverSocket != null) { try { @@ -131,6 +134,24 @@ public class QtBluetoothSocketServer extends Thread Log.d(TAG, "Leaving server socket thread."); } + // This function closes the socket server + // + // A note on threading behavior + // 1. This function is called from Qt thread which is different from the Java thread (run()) + // 2. The caller of this function expects the Java thread to be finished upon return + // + // First we mark the Java thread as interrupted, then call close() on the + // listening socket if it had been created, and lastly wait for the thread to finish. + // The close() method of the socket is intended to be used to abort the accept() from + // another thread, as per the accept() documentation. + // + // If the Java thread was in the middle of creating a socket with the non-blocking + // listen* call, the run() will notice after the returning from the listen* that it has + // been interrupted and returns early from the run(). + // + // If the Java thread was in the middle of the blocking accept() call, it will get + // interrupated by the close() call on the socket. After returning the run() will + // notice it has been interrupted and return from the run() public void close() { if (!isAlive()) @@ -143,7 +164,9 @@ public class QtBluetoothSocketServer extends Thread //interrupts accept() call above if (m_serverSocket != null) m_serverSocket.close(); - } catch (IOException ex) { + // Wait for the thread to finish + join(20); // Maximum wait in ms, typically takes < 1ms + } catch (Exception ex) { Log.d(TAG, "Closing server socket close() failed:" + ex.toString()); ex.printStackTrace(); } |