From ad598e5020a1448ce8567a999fa7f39feafed985 Mon Sep 17 00:00:00 2001 From: Davide N Date: Thu, 16 Jan 2025 17:03:59 +0100 Subject: [PATCH 1/2] fix: add mutex for thread-safe access in serialport isClosing --- serialport.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/serialport.go b/serialport.go index a11483f6..8fbf6d61 100755 --- a/serialport.go +++ b/serialport.go @@ -20,6 +20,7 @@ import ( "encoding/base64" "io" "strconv" + "sync" "time" "unicode/utf8" @@ -45,6 +46,8 @@ type serport struct { // just so we don't show scary error messages isClosing bool + mu sync.Mutex + isClosingDueToError bool // buffered channel containing up to 25600 outbound messages. @@ -84,6 +87,7 @@ func (p *serport) reader(buftype string) { n, err := p.portIo.Read(serialBuffer) bufferPart := serialBuffer[:n] + p.mu.Lock() //if we detect that port is closing, break out of this for{} loop. if p.isClosing { strmsg := "Shutting down reader on " + p.portConf.Name @@ -91,6 +95,7 @@ func (p *serport) reader(buftype string) { h.broadcastSys <- []byte(strmsg) break } + p.mu.Unlock() // read can return legitimate bytes as well as an error // so process the n bytes red, if n > 0 @@ -348,7 +353,10 @@ func spHandlerOpen(portname string, baud int, buftype string) { } func (p *serport) Close() { + p.mu.Lock() p.isClosing = true + p.mu.Unlock() + p.bufferwatcher.Close() p.portIo.Close() serialPorts.MarkPortAsClosed(p.portName) From 567c86591f68e0e7dc98c60e1675ece281fdf2da Mon Sep 17 00:00:00 2001 From: Davide N Date: Mon, 20 Jan 2025 10:11:34 +0100 Subject: [PATCH 2/2] refactor: replace mutex with atomic boolean for thread-safe isClosing flag --- serialport.go | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/serialport.go b/serialport.go index 8fbf6d61..0d386bbf 100755 --- a/serialport.go +++ b/serialport.go @@ -20,7 +20,7 @@ import ( "encoding/base64" "io" "strconv" - "sync" + "sync/atomic" "time" "unicode/utf8" @@ -44,9 +44,7 @@ type serport struct { // Keep track of whether we're being actively closed // just so we don't show scary error messages - isClosing bool - - mu sync.Mutex + isClosing atomic.Bool isClosingDueToError bool @@ -87,15 +85,13 @@ func (p *serport) reader(buftype string) { n, err := p.portIo.Read(serialBuffer) bufferPart := serialBuffer[:n] - p.mu.Lock() //if we detect that port is closing, break out of this for{} loop. - if p.isClosing { + if p.isClosing.Load() { strmsg := "Shutting down reader on " + p.portConf.Name log.Println(strmsg) h.broadcastSys <- []byte(strmsg) break } - p.mu.Unlock() // read can return legitimate bytes as well as an error // so process the n bytes red, if n > 0 @@ -353,9 +349,7 @@ func spHandlerOpen(portname string, baud int, buftype string) { } func (p *serport) Close() { - p.mu.Lock() - p.isClosing = true - p.mu.Unlock() + p.isClosing.Store(true) p.bufferwatcher.Close() p.portIo.Close()