From 845de5c178472adb87895b6843be3cffdf2af567 Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Wed, 28 Jun 2023 11:34:04 -0300 Subject: [PATCH] Fix race when stopping Tor --- .../org/onionshare/android/ShareManager.kt | 3 +-- .../org/onionshare/android/tor/TorManager.kt | 22 ++++++++++++------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/org/onionshare/android/ShareManager.kt b/app/src/main/java/org/onionshare/android/ShareManager.kt index d46af9d7..39830383 100644 --- a/app/src/main/java/org/onionshare/android/ShareManager.kt +++ b/app/src/main/java/org/onionshare/android/ShareManager.kt @@ -163,8 +163,7 @@ class ShareManager @Inject constructor( } startSharingJob = null - val torState = torManager.state.value - if (torState !is TorState.Stopped && torState !is TorState.Stopping) torManager.stop() + torManager.stop() if (webserverManager.state.value !is WebServerState.Stopped) webserverManager.stop() fileManager.stop() notificationManager.onStopped() diff --git a/app/src/main/java/org/onionshare/android/tor/TorManager.kt b/app/src/main/java/org/onionshare/android/tor/TorManager.kt index 8c46874f..03d356c9 100644 --- a/app/src/main/java/org/onionshare/android/tor/TorManager.kt +++ b/app/src/main/java/org/onionshare/android/tor/TorManager.kt @@ -58,7 +58,10 @@ class TorManager @Inject constructor( /** * Updates the [_state] with the given new [state] preventing concurrent modifications. * The state only gets updated when [_state] was in [expectedState]. - * @return true if the state was updated and false if not. + * + * Note that the underlying [MutableStateFlow] may reject updates that are equal to the previous state. + * + * @return true if the expected state was either null or matched the previous state. */ @Synchronized private fun updateTorState(expectedState: KClass<*>?, newState: TorState, warn: Boolean = true): Boolean { @@ -104,13 +107,16 @@ class TorManager @Inject constructor( } fun stop() { - LOG.info("Stopping...") - updateTorState(null, TorState.Stopping) - startCheckJob?.cancel() - startCheckJob = null - tor.stop() - Intent(app, ShareService::class.java).also { intent -> - app.stopService(intent) + if (updateTorState(TorState.Stopping::class, TorState.Stopping, warn = false)) { + LOG.info("Was already stopping. Not stopping again.") + } else { + LOG.info("Stopping...") + startCheckJob?.cancel() + startCheckJob = null + tor.stop() + Intent(app, ShareService::class.java).also { intent -> + app.stopService(intent) + } } }