fix: watchdog을 별도 Thread로 분리 (handler 블로킹 방지)
기존: handler.postDelayed로 watchdog 실행 → BLE 스택이 handler를 블로킹하면 watchdog도 멈춤 (좀비 상태 감지 불가) 변경: 별도 daemon Thread에서 5초마다 lastRxTimestamp 체크 → BLE handler가 블로킹되어도 독립적으로 15초 타임아웃 감지 → 감지 시 handler.post로 메인 스레드에서 forceDisconnectAndReconnect 실행 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -352,31 +352,39 @@ class BleManager private constructor(private val context: Context) {
|
|||||||
batteryTimer = null
|
batteryTimer = null
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Watchdog (zombie connection detection) ──
|
// ── Watchdog (zombie connection detection, runs on separate thread) ──
|
||||||
|
|
||||||
|
private var watchdogJob: Thread? = null
|
||||||
|
@Volatile private var watchdogRunning = false
|
||||||
|
|
||||||
private fun startWatchdog() {
|
private fun startWatchdog() {
|
||||||
stopWatchdog()
|
stopWatchdog()
|
||||||
lastRxTimestamp = System.currentTimeMillis()
|
lastRxTimestamp = System.currentTimeMillis()
|
||||||
val check = object : Runnable {
|
watchdogRunning = true
|
||||||
override fun run() {
|
|
||||||
if (!isConnected.value) return
|
watchdogJob = Thread({
|
||||||
|
while (watchdogRunning) {
|
||||||
|
try { Thread.sleep(5000) } catch (_: InterruptedException) { break }
|
||||||
|
if (!watchdogRunning) break
|
||||||
|
if (!isConnected.value) continue
|
||||||
|
|
||||||
val silenceMs = System.currentTimeMillis() - lastRxTimestamp
|
val silenceMs = System.currentTimeMillis() - lastRxTimestamp
|
||||||
if (silenceMs > watchdogTimeoutMs) {
|
if (silenceMs > watchdogTimeoutMs) {
|
||||||
logw { "Watchdog: no RX for ${silenceMs}ms — forcing disconnect + reconnect" }
|
handler.post {
|
||||||
debugLogger.error("WATCHDOG_TIMEOUT silence=${silenceMs}ms — forcing reconnect")
|
logw { "Watchdog: no RX for ${silenceMs}ms — forcing disconnect + reconnect" }
|
||||||
forceDisconnectAndReconnect()
|
debugLogger.error("WATCHDOG_TIMEOUT silence=${silenceMs}ms — forcing reconnect")
|
||||||
return
|
forceDisconnectAndReconnect()
|
||||||
|
}
|
||||||
|
break
|
||||||
}
|
}
|
||||||
handler.postDelayed(this, 5000)
|
|
||||||
}
|
}
|
||||||
}
|
}, "BLE-Watchdog").also { it.isDaemon = true; it.start() }
|
||||||
watchdogTimer = check
|
|
||||||
handler.postDelayed(check, 5000)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun stopWatchdog() {
|
private fun stopWatchdog() {
|
||||||
watchdogTimer?.let { handler.removeCallbacks(it) }
|
watchdogRunning = false
|
||||||
watchdogTimer = null
|
watchdogJob?.interrupt()
|
||||||
|
watchdogJob = null
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun forceDisconnectAndReconnect() {
|
private fun forceDisconnectAndReconnect() {
|
||||||
|
|||||||
Reference in New Issue
Block a user