From 7b46046af6823cbde53779ac911838f2ea8a4677 Mon Sep 17 00:00:00 2001 From: geeksville Date: Sat, 18 Jul 2020 14:23:58 -0700 Subject: [PATCH] cancel all jobs when we shutdown interface (an autobug) --- .../geeksville/mesh/service/BluetoothInterface.kt | 5 +++-- .../mesh/service/RadioInterfaceService.kt | 13 ++++++++++--- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/geeksville/mesh/service/BluetoothInterface.kt b/app/src/main/java/com/geeksville/mesh/service/BluetoothInterface.kt index 8cdb4d2d8..3be7ecf51 100644 --- a/app/src/main/java/com/geeksville/mesh/service/BluetoothInterface.kt +++ b/app/src/main/java/com/geeksville/mesh/service/BluetoothInterface.kt @@ -353,6 +353,8 @@ class BluetoothInterface(val service: RadioInterfaceService, val address: String } } catch (ex: CancellationException) { warn("retryDueToException was cancelled") + } finally { + reconnectJob = null } /// We only try to set MTU once, because some buggy implementations fail @@ -417,7 +419,7 @@ class BluetoothInterface(val service: RadioInterfaceService, val address: String if (needForceRefresh) { // Our ESP32 code doesn't properly generate "service changed" indications. Therefore we need to force a refresh on initial start //needForceRefresh = false // In fact, because of tearing down BLE in sleep on the ESP32, our handle # assignments are not stable across sleep - so we much refetch every time forceServiceRefresh() // this article says android should not be caching, but it does on some phones: https://punchthrough.com/attribute-caching-in-ble-advantages-and-pitfalls/ - + delay(500) // From looking at the android C code it seems that we need to give some time for the refresh message to reach that worked _before_ we try to set mtu/get services // 200ms was not enough on an Amazon Fire } @@ -447,7 +449,6 @@ class BluetoothInterface(val service: RadioInterfaceService, val address: String override fun close() { reconnectJob?.cancel() // Cancel any queued reconnect attempts - reconnectJob = null if (safe != null) { info("Closing BluetoothInterface") diff --git a/app/src/main/java/com/geeksville/mesh/service/RadioInterfaceService.kt b/app/src/main/java/com/geeksville/mesh/service/RadioInterfaceService.kt index acf156a17..7fd73e7c9 100644 --- a/app/src/main/java/com/geeksville/mesh/service/RadioInterfaceService.kt +++ b/app/src/main/java/com/geeksville/mesh/service/RadioInterfaceService.kt @@ -18,6 +18,7 @@ import com.geeksville.util.toRemoteExceptions import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job +import kotlinx.coroutines.cancel class RadioNotConnectedException(message: String = "Not connected to radio") : @@ -121,8 +122,10 @@ class RadioInterfaceService : Service(), Logging { private lateinit var sentPacketsLog: BinaryLogFile // inited in onCreate private lateinit var receivedPacketsLog: BinaryLogFile - private val serviceJob = Job() - val serviceScope = CoroutineScope(Dispatchers.IO + serviceJob) + /** + * We recreate this scope each time we stop an interface + */ + var serviceScope = CoroutineScope(Dispatchers.IO + Job()) private val nopIf = NopInterface() private var radioIf: IRadioInterface = nopIf @@ -198,7 +201,7 @@ class RadioInterfaceService : Service(), Logging { override fun onDestroy() { unregisterReceiver(bluetoothStateReceiver) stopInterface() - serviceJob.cancel() + serviceScope.cancel("Destroying RadioInterface") runningService = null super.onDestroy() } @@ -248,6 +251,10 @@ class RadioInterfaceService : Service(), Logging { radioIf = nopIf r.close() + // cancel any old jobs and get ready for the new ones + serviceScope.cancel("stopping interface") + serviceScope = CoroutineScope(Dispatchers.IO + Job()) + if (logSends) sentPacketsLog.close() if (logReceives)