From 99203a0a0379d98d63eb43f9615feb96e93f7869 Mon Sep 17 00:00:00 2001 From: Adam Shiervani Date: Sat, 28 Mar 2026 22:11:52 +0100 Subject: [PATCH] fix: remove goroutine from HID message handler to prevent leak and disconnect race (#1336) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: buffer HID response channel and reduce timeout to prevent goroutine leaks (#1154) * fix: remove goroutine from HID message handler to prevent leak and disconnect race (#1154) The goroutine+select pattern in onHidMessage leaked permanently when timeouts fired (unbuffered channel, no reader). On the single-core RV1106, boot-time CPU contention cascaded these leaks, causing persistent mouse latency until reboot. Processing synchronously is safe — every path in handleHidRPCMessage is already bounded (10ms HID write deadline, cancellable macros, non-blocking DataChannel sends). This also eliminates a race where timed-out goroutines could overwrite the all-keys-up report on session disconnect. --------- Co-authored-by: Adam Shiervani --- hidrpc.go | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/hidrpc.go b/hidrpc.go index f4fbceb4..8c107626 100644 --- a/hidrpc.go +++ b/hidrpc.go @@ -89,17 +89,13 @@ func onHidMessage(msg hidQueueMessage, session *Session) { } t := time.Now() + handleHidRPCMessage(message, session) + d := time.Since(t) - r := make(chan interface{}) - go func() { - handleHidRPCMessage(message, session) - r <- nil - }() - select { - case <-time.After(1 * time.Second): - scopedLogger.Warn().Msg("HID RPC message timed out") - case <-r: - scopedLogger.Debug().Dur("duration", time.Since(t)).Msg("HID RPC message handled") + if d > 200*time.Millisecond { + scopedLogger.Warn().Dur("duration", d).Msg("HID RPC message slow") + } else { + scopedLogger.Debug().Dur("duration", d).Msg("HID RPC message handled") } }