mirror of
https://github.com/permissionlesstech/bitchat-android.git
synced 2026-08-15 06:56:30 +00:00
fix: test the hotspot hold under the lock that publishes Aware
The previous recheck narrowed the race without closing it. Testing
hotspotHold outside lifecycleLock left this interleaving:
1. the recheck passes, hold not yet set
2. holdForHotspot() sets the flag and calls stop(), which takes the
lock, finds nothing published, and returns having stopped nothing
3. this block takes the lock and publishes the service anyway
Aware ends up running while the hotspot believes it owns the radio,
which is the original failure.
The hold is now tested inside the same synchronized block that
publishes, so the check and the publication are one step against
stop(). Ordering holds because holdForHotspot() sets the flag before
calling stop(): either the publisher observes the flag and abandons,
or stop() observes the published service and tears it down. There is
no interleaving that leaves a service published with the hold set.
stopServices() stays outside the lock since it can block.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
05896f354d
commit
b5fd346437
@ -190,36 +190,39 @@ object WifiAwareController {
|
||||
}
|
||||
startedService.startServices()
|
||||
|
||||
// The hotspot can claim the radio at any point during the work above.
|
||||
// Committing the service now would resurrect NAN behind its back and
|
||||
// leave every P2P attempt answering BUSY, so drop what we just started.
|
||||
if (hotspotHold.get()) {
|
||||
Log.i(TAG, "Hotspot claimed the radio while starting; abandoning Wi-Fi Aware start")
|
||||
try { startedService.stopServices() } catch (_: Exception) { }
|
||||
synchronized(lifecycleLock) {
|
||||
// Test the hold inside the same lock that publishes the service, and that
|
||||
// stop() takes. Testing it outside leaves a window where holdForHotspot()
|
||||
// sets the flag and stop() finds nothing published yet, and this block then
|
||||
// publishes anyway — resurrecting NAN while the hotspot owns the radio.
|
||||
// Ordering holds because holdForHotspot() sets the flag before calling
|
||||
// stop(): either we see the flag here, or stop() sees our published service.
|
||||
val published = synchronized(lifecycleLock) {
|
||||
val canPublish = !hotspotHold.get() && startedService.isRunning()
|
||||
if (canPublish) {
|
||||
service = startedService
|
||||
_running.value = true
|
||||
} else {
|
||||
if (service === startedService) service = null
|
||||
_running.value = false
|
||||
}
|
||||
return
|
||||
canPublish
|
||||
}
|
||||
|
||||
if (startedService.isRunning()) {
|
||||
synchronized(lifecycleLock) {
|
||||
service = startedService
|
||||
_running.value = true
|
||||
}
|
||||
if (published) {
|
||||
try { com.bitchat.android.service.MeshServiceHolder.unifiedMeshService?.refreshDelegates() } catch (_: Exception) { }
|
||||
clearBlockedDebugMessage()
|
||||
try { com.bitchat.android.ui.debug.DebugSettingsManager.getInstance().addDebugMessage(com.bitchat.android.ui.debug.DebugMessage.SystemMessage("Wi‑Fi Aware started")) } catch (_: Exception) {}
|
||||
} else {
|
||||
if (reusableService == null) {
|
||||
// stopServices() can block, so keep it out of the lock.
|
||||
val heldForHotspot = hotspotHold.get()
|
||||
if (heldForHotspot || reusableService == null) {
|
||||
try { startedService.stopServices() } catch (_: Exception) { }
|
||||
}
|
||||
synchronized(lifecycleLock) {
|
||||
if (service === startedService) service = null
|
||||
_running.value = false
|
||||
if (heldForHotspot) {
|
||||
Log.i(TAG, "Abandoned Wi-Fi Aware start: hotspot claimed the radio")
|
||||
}
|
||||
try { com.bitchat.android.ui.debug.DebugSettingsManager.getInstance().addDebugMessage(com.bitchat.android.ui.debug.DebugMessage.SystemMessage("Wi‑Fi Aware did not start")) } catch (_: Exception) {}
|
||||
val detail = if (heldForHotspot) "held down for the hotspot" else "did not start"
|
||||
try { com.bitchat.android.ui.debug.DebugSettingsManager.getInstance().addDebugMessage(com.bitchat.android.ui.debug.DebugMessage.SystemMessage("Wi‑Fi Aware $detail")) } catch (_: Exception) {}
|
||||
}
|
||||
} catch (e: Throwable) {
|
||||
Log.e(TAG, "Failed to start WifiAwareMeshService", e)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user