Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit e7ea376

Browse filesBrowse files
authored
fix: Serial Monitor corrupted output in some rare cases (#1032)
* Synchronize multiple open commands coming together. * Allow re-opening of already opened ports * Renamed mutex var and added comment * Error out if baudrate and buftype of already opened port do not match
1 parent b717430 commit e7ea376
Copy full SHA for e7ea376

File tree

2 files changed

+27
-23
lines changed
Filter options

2 files changed

+27
-23
lines changed

‎serial.go

Copy file name to clipboardExpand all lines: serial.go
+6-13Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import (
3131

3232
type serialhub struct {
3333
// Opened serial ports.
34-
ports map[*serport]bool
34+
ports map[string]*serport
3535

3636
mu sync.Mutex
3737
}
@@ -60,15 +60,15 @@ type SpPortItem struct {
6060
var serialPorts SerialPortList
6161

6262
var sh = serialhub{
63-
ports: make(map[*serport]bool),
63+
ports: make(map[string]*serport),
6464
}
6565

6666
// Register serial ports from the connections.
6767
func (sh *serialhub) Register(port *serport) {
6868
sh.mu.Lock()
6969
//log.Print("Registering a port: ", p.portConf.Name)
7070
h.broadcastSys <- []byte("{\"Cmd\":\"Open\",\"Desc\":\"Got register/open on port.\",\"Port\":\"" + port.portConf.Name + "\",\"Baud\":" + strconv.Itoa(port.portConf.Baud) + ",\"BufferType\":\"" + port.BufferType + "\"}")
71-
sh.ports[port] = true
71+
sh.ports[port.portName] = port
7272
sh.mu.Unlock()
7373
}
7474

@@ -77,7 +77,7 @@ func (sh *serialhub) Unregister(port *serport) {
7777
sh.mu.Lock()
7878
//log.Print("Unregistering a port: ", p.portConf.Name)
7979
h.broadcastSys <- []byte("{\"Cmd\":\"Close\",\"Desc\":\"Got unregister/close on port.\",\"Port\":\"" + port.portConf.Name + "\",\"Baud\":" + strconv.Itoa(port.portConf.Baud) + "}")
80-
delete(sh.ports, port)
80+
delete(sh.ports, port.portName)
8181
close(port.sendBuffered)
8282
close(port.sendNoBuf)
8383
sh.mu.Unlock()
@@ -86,15 +86,8 @@ func (sh *serialhub) Unregister(port *serport) {
8686
func (sh *serialhub) FindPortByName(portname string) (*serport, bool) {
8787
sh.mu.Lock()
8888
defer sh.mu.Unlock()
89-
90-
for port := range sh.ports {
91-
if strings.EqualFold(port.portConf.Name, portname) {
92-
// we found our port
93-
//spHandlerClose(port)
94-
return port, true
95-
}
96-
}
97-
return nil, false
89+
port, ok := sh.ports[portname]
90+
return port, ok
9891
}
9992

10093
// List broadcasts a Json representation of the ports found

‎serialport.go

Copy file name to clipboardExpand all lines: serialport.go
+21-10Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"encoding/base64"
2121
"io"
2222
"strconv"
23+
"sync"
2324
"sync/atomic"
2425
"time"
2526
"unicode/utf8"
@@ -273,7 +274,13 @@ func (p *serport) writerRaw() {
273274
h.broadcastSys <- []byte(msgstr)
274275
}
275276

277+
// This lock is used to prevent multiple threads from trying to open the same port at the same time.
278+
// It presents issues with the serial port driver on some OS's: https://github.com/arduino/arduino-create-agent/issues/1031
279+
var spHandlerOpenLock sync.Mutex
280+
276281
func spHandlerOpen(portname string, baud int, buftype string) {
282+
spHandlerOpenLock.Lock()
283+
defer spHandlerOpenLock.Unlock()
277284

278285
log.Print("Inside spHandler")
279286

@@ -295,11 +302,14 @@ func spHandlerOpen(portname string, baud int, buftype string) {
295302
sp, err := serial.Open(portname, mode)
296303
log.Print("Just tried to open port")
297304
if err != nil {
298-
//log.Fatal(err)
299-
log.Print("Error opening port " + err.Error())
300-
//h.broadcastSys <- []byte("Error opening port. " + err.Error())
301-
h.broadcastSys <- []byte("{\"Cmd\":\"OpenFail\",\"Desc\":\"Error opening port. " + err.Error() + "\",\"Port\":\"" + conf.Name + "\",\"Baud\":" + strconv.Itoa(conf.Baud) + "}")
302-
305+
existingPort, ok := sh.FindPortByName(portname)
306+
if ok && existingPort.portConf.Baud == baud && existingPort.BufferType == buftype {
307+
log.Print("Port already opened")
308+
h.broadcastSys <- []byte("{\"Cmd\":\"Open\",\"Desc\":\"Port already opened.\",\"Port\":\"" + existingPort.portConf.Name + "\",\"Baud\":" + strconv.Itoa(existingPort.portConf.Baud) + ",\"BufferType\":\"" + existingPort.BufferType + "\"}")
309+
} else {
310+
log.Print("Error opening port " + err.Error())
311+
h.broadcastSys <- []byte("{\"Cmd\":\"OpenFail\",\"Desc\":\"Error opening port. " + err.Error() + "\",\"Port\":\"" + conf.Name + "\",\"Baud\":" + strconv.Itoa(conf.Baud) + "}")
312+
}
303313
return
304314
}
305315
log.Print("Opened port successfully")
@@ -331,7 +341,6 @@ func spHandlerOpen(portname string, baud int, buftype string) {
331341
p.bufferwatcher = bw
332342

333343
sh.Register(p)
334-
defer sh.Unregister(p)
335344

336345
serialPorts.MarkPortAsOpened(portname)
337346
serialPorts.List()
@@ -342,10 +351,12 @@ func spHandlerOpen(portname string, baud int, buftype string) {
342351
go p.writerNoBuf()
343352
// this is thread to send to serial port but with base64 decoding
344353
go p.writerRaw()
345-
346-
p.reader(buftype)
347-
348-
serialPorts.List()
354+
// this is the thread that reads from the serial port
355+
go func() {
356+
p.reader(buftype)
357+
serialPorts.List()
358+
sh.Unregister(p)
359+
}()
349360
}
350361

351362
func (p *serport) Close() {

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.