From 4b9928ca8359f58d1cbd1b36b16369974e2ce07e Mon Sep 17 00:00:00 2001 From: captv89 Date: Tue, 6 May 2025 01:01:50 +0200 Subject: [PATCH] fix: correct mutex handling in NMEA 2000 TCP server Fixed race condition in TCP2000Server.SendPGN by properly separating read and write lock operations. This resolves the "unlock of unlocked RWMutex" error that occurred when removing failed clients. --- pkg/network/tcp2000.go | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/pkg/network/tcp2000.go b/pkg/network/tcp2000.go index 1314798..ccd073b 100644 --- a/pkg/network/tcp2000.go +++ b/pkg/network/tcp2000.go @@ -60,28 +60,29 @@ func (s *TCP2000Server) Stop() error { // SendPGN sends a NMEA 2000 message to all connected clients func (s *TCP2000Server) SendPGN(msg pgn.Message) error { - s.Mu.RLock() - defer s.Mu.RUnlock() - frame := formatPGNMessage(msg) - var failedClients []net.Conn + + // Read lock for iterating + s.Mu.RLock() for client := range s.clients { _, err := client.Write([]byte(frame)) if err != nil { - // Collect failed client failedClients = append(failedClients, client) } } - - // Remove failed clients s.Mu.RUnlock() - s.Mu.Lock() - for _, client := range failedClients { - delete(s.clients, client) - client.Close() + + // Write lock for removing failed clients + if len(failedClients) > 0 { + s.Mu.Lock() + for _, client := range failedClients { + delete(s.clients, client) + client.Close() + } + s.Mu.Unlock() } - s.Mu.Unlock() + return nil }