combov2: Wait for coroutines to finish in onStop()

This commit is contained in:
Carlos Rafael Giani 2023-03-08 22:19:50 +01:00
parent 2cdc4c45ea
commit fe1235dbe1

View file

@ -134,8 +134,8 @@ class ComboV2Plugin @Inject constructor (
// Coroutine scope and the associated job. All coroutines
// that are started in this plugin are part of this scope.
private val pumpCoroutineMainJob = SupervisorJob()
private val pumpCoroutineScope = CoroutineScope(Dispatchers.Default + pumpCoroutineMainJob)
private var pumpCoroutineScopeJob = SupervisorJob()
private var pumpCoroutineScope = CoroutineScope(Dispatchers.Default + pumpCoroutineScopeJob)
private val _pumpDescription = PumpDescription()
@ -255,6 +255,8 @@ class ComboV2Plugin @Inject constructor (
}
override fun onStart() {
aapsLogger.info(LTag.PUMP, "Starting combov2 driver")
super.onStart()
updateComboCtlLogLevel()
@ -290,11 +292,14 @@ class ComboV2Plugin @Inject constructor (
aapsLogger.debug(LTag.PUMP, "Creating bluetooth interface")
bluetoothInterface = AndroidBluetoothInterface(context)
aapsLogger.info(LTag.PUMP, "Continuing combov2 driver start in coroutine")
// Continue initialization in a separate coroutine. This allows us to call
// runWithPermissionCheck(), which will keep trying to run the code block
// until either the necessary Bluetooth permissions are granted, or the
// coroutine is cancelled (see onStop() below).
pumpCoroutineScope.launch {
try {
runWithPermissionCheck(
context, config, aapsLogger, androidPermission,
permissionsToCheckFor = listOf("android.permission.BLUETOOTH_CONNECT")
@ -321,18 +326,29 @@ class ComboV2Plugin @Inject constructor (
setDriverState(DriverState.Disconnected)
aapsLogger.info(LTag.PUMP, "combov2 driver start complete")
// NOTE: EventInitializationChanged is sent in getPumpStatus() .
}
} catch (e: CancellationException) {
aapsLogger.info(LTag.PUMP, "combov2 driver start cancelled")
throw e
}
}
}
override fun onStop() {
// Cancel any ongoing background coroutines. This includes an ongoing
// unfinished initialization that still waits for the user to grant
// Bluetooth permissions.
pumpCoroutineScope.cancel()
aapsLogger.info(LTag.PUMP, "Stopping combov2 driver")
runBlocking {
// Cancel any ongoing background coroutines. This includes an ongoing
// unfinished initialization that still waits for the user to grant
// Bluetooth permissions. Also join to wait for the coroutines to
// finish. Otherwise, race conditions can occur, for example, when
// a coroutine tries to access bluetoothInterface right after it
// was torn down below.
pumpCoroutineScopeJob.cancelAndJoin()
// Normally this should not happen, but to be safe,
// make sure any running pump instance is disconnected.
pump?.disconnect()
@ -353,7 +369,13 @@ class ComboV2Plugin @Inject constructor (
rxBus.send(EventInitializationChanged())
initializationChangedEventSent = false
// The old job and scope were completed. We need new ones.
pumpCoroutineScopeJob = SupervisorJob()
pumpCoroutineScope = CoroutineScope(Dispatchers.Default + pumpCoroutineScopeJob)
super.onStop()
aapsLogger.info(LTag.PUMP, "combov2 driver stopped")
}
override fun preprocessPreferences(preferenceFragment: PreferenceFragmentCompat) {