Skip to content

Commit 716e7aa

Browse files
cmaglieumbynos
andauthored
bugfix: serial enumerator failures in some rare circumstances (#830)
* Use io.Discard instead of custom nullWriter * Renamed and slightly refactored port enumerators * Useless code beautify * Updated go.bug.st/serial lib to 1.6.0 * Empty port list if the enumerator fails * Synchronize multiple serial-port update request * Upgraded go-serial to 1.6.1 * Update serial.go Co-authored-by: Umberto Baldi <[email protected]> --------- Co-authored-by: Umberto Baldi <[email protected]>
1 parent b2bceb6 commit 716e7aa

File tree

10 files changed

+89
-111
lines changed

10 files changed

+89
-111
lines changed

.licenses/arduino-create-agent/go/go.bug.st/serial.dep.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
name: go.bug.st/serial
3-
version: v1.4.1
3+
version: v1.6.1
44
type: go
55
summary: Package serial is a cross-platform serial library for the go language.
66
homepage: https://pkg.go.dev/go.bug.st/serial
@@ -9,7 +9,7 @@ licenses:
99
- sources: LICENSE
1010
text: |2+
1111
12-
Copyright (c) 2014-2021, Cristian Maglie.
12+
Copyright (c) 2014-2023, Cristian Maglie.
1313
All rights reserved.
1414
1515
Redistribution and use in source and binary forms, with or without

.licenses/arduino-create-agent/go/go.bug.st/serial/enumerator.dep.yml

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
---
22
name: go.bug.st/serial/enumerator
3-
version: v1.4.1
3+
version: v1.6.1
44
type: go
55
summary: Package enumerator is a golang cross-platform library for USB serial port
66
discovery.
77
homepage: https://pkg.go.dev/go.bug.st/serial/enumerator
88
license: bsd-3-clause
99
licenses:
10-
- sources: serial@v1.4.1/LICENSE
10+
- sources: serial@v1.6.1/LICENSE
1111
text: |2+
1212
13-
Copyright (c) 2014-2021, Cristian Maglie.
13+
Copyright (c) 2014-2023, Cristian Maglie.
1414
All rights reserved.
1515
1616
Redistribution and use in source and binary forms, with or without
@@ -42,7 +42,7 @@ licenses:
4242
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
4343
POSSIBILITY OF SUCH DAMAGE.
4444
45-
- sources: serial@v1.4.1/README.md
45+
- sources: serial@v1.6.1/README.md
4646
text: |-
4747
The software is release under a [BSD 3-clause license]
4848

.licenses/arduino-create-agent/go/go.bug.st/serial/unixutils.dep.yml

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
---
22
name: go.bug.st/serial/unixutils
3-
version: v1.4.1
3+
version: v1.6.1
44
type: go
55
summary:
66
homepage: https://pkg.go.dev/go.bug.st/serial/unixutils
77
license: bsd-3-clause
88
licenses:
9-
- sources: serial@v1.4.1/LICENSE
9+
- sources: serial@v1.6.1/LICENSE
1010
text: |2+
1111
12-
Copyright (c) 2014-2021, Cristian Maglie.
12+
Copyright (c) 2014-2023, Cristian Maglie.
1313
All rights reserved.
1414
1515
Redistribution and use in source and binary forms, with or without
@@ -41,7 +41,7 @@ licenses:
4141
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
4242
POSSIBILITY OF SUCH DAMAGE.
4343
44-
- sources: serial@v1.4.1/README.md
44+
- sources: serial@v1.6.1/README.md
4545
text: |-
4646
The software is release under a [BSD 3-clause license]
4747

discovery.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,10 @@ const timeoutConst = 2
4242
// SavedNetworkPorts contains the ports which we know are already connected
4343
var SavedNetworkPorts []OsSerialPort
4444

45-
// GetNetworkList returns a list of Network Ports
45+
// enumerateNetworkPorts returns a list of Network Ports
4646
// The research of network ports is articulated in two phases. First we add new ports coming from
4747
// the bonjour module, then we prune the boards who don't respond to a ping
48-
func GetNetworkList() ([]OsSerialPort, error) {
48+
func enumerateNetworkPorts() ([]OsSerialPort, error) {
4949
newPorts, err := getPorts()
5050
if err != nil {
5151
return nil, err

go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ require (
2222
github.com/stretchr/testify v1.8.4
2323
github.com/xrash/smetrics v0.0.0-20170218160415-a3153f7040e9
2424
go.bug.st/downloader/v2 v2.1.1
25-
go.bug.st/serial v1.4.1
25+
go.bug.st/serial v1.6.1
2626
goa.design/goa/v3 v3.12.4
2727
golang.org/x/crypto v0.12.0
2828
golang.org/x/sys v0.11.0

go.sum

+2-2
Original file line numberDiff line numberDiff line change
@@ -165,8 +165,8 @@ github.com/xrash/smetrics v0.0.0-20170218160415-a3153f7040e9 h1:w8V9v0qVympSF6Gj
165165
github.com/xrash/smetrics v0.0.0-20170218160415-a3153f7040e9/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
166166
go.bug.st/downloader/v2 v2.1.1 h1:nyqbUizo3E2IxCCm4YFac4FtSqqFpqWP+Aae5GCMuw4=
167167
go.bug.st/downloader/v2 v2.1.1/go.mod h1:VZW2V1iGKV8rJL2ZEGIDzzBeKowYv34AedJz13RzVII=
168-
go.bug.st/serial v1.4.1 h1:AwYUNixVf90XymNeJaUkMrPp+GZQe3RMFQmpVdHIUK8=
169-
go.bug.st/serial v1.4.1/go.mod h1:z8CesKorE90Qr/oRSJiEuvzYRKol9r/anJZEb5kt304=
168+
go.bug.st/serial v1.6.1 h1:VSSWmUxlj1T/YlRo2J104Zv3wJFrjHIl/T3NeruWAHY=
169+
go.bug.st/serial v1.6.1/go.mod h1:UABfsluHAiaNI+La2iESysd9Vetq7VRdpxvjx7CmmOE=
170170
goa.design/goa/v3 v3.12.4 h1:g3G8yHLk+jyUDNRL2sNg+ZcoQ62zY83rpgagAQ5VmTA=
171171
goa.design/goa/v3 v3.12.4/go.mod h1:h1vjyGQ+rqWK+VvnqN8oLcpqaHrKIyuY1Vx+jhKodpg=
172172
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU=

main.go

+3-6
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
_ "embed"
2323
"encoding/json"
2424
"flag"
25+
"io"
2526
"os"
2627
"os/exec"
2728
"runtime"
@@ -99,10 +100,6 @@ var (
99100
Systray systray.Systray
100101
)
101102

102-
type nullWriter int
103-
104-
func (nullWriter) Write([]byte) (int, error) { return 0, nil }
105-
106103
type logWriter struct{}
107104

108105
func (u *logWriter) Write(p []byte) (n int, err error) {
@@ -310,7 +307,7 @@ func loop() {
310307
}
311308

312309
// list serial ports
313-
portList, _ := GetList(false)
310+
portList, _ := enumerateSerialPorts()
314311
log.Println("Your serial ports:")
315312
if len(portList) == 0 {
316313
log.Println("\tThere are no serial ports to list.")
@@ -322,7 +319,7 @@ func loop() {
322319

323320
if !*verbose {
324321
log.Println("You can enter verbose mode to see all logging by starting with the -v command line switch.")
325-
log.SetOutput(new(nullWriter)) //route all logging to nullwriter
322+
log.SetOutput(io.Discard)
326323
}
327324

328325
// save crashreport to file

serial.go

+58-77
Original file line numberDiff line numberDiff line change
@@ -71,11 +71,11 @@ type SpPortItem struct {
7171
ProductID string
7272
}
7373

74-
// SerialPorts contains the ports attached to the machine
75-
var SerialPorts SpPortList
74+
// serialPorts contains the ports attached to the machine
75+
var serialPorts SpPortList
7676

77-
// NetworkPorts contains the ports on the network
78-
var NetworkPorts SpPortList
77+
// networkPorts contains the ports on the network
78+
var networkPorts SpPortList
7979

8080
var sh = serialhub{
8181
//write: make(chan *serport, chan []byte),
@@ -130,13 +130,13 @@ func spList(network bool) {
130130
var ls []byte
131131
var err error
132132
if network {
133-
NetworkPorts.Mu.Lock()
134-
ls, err = json.MarshalIndent(&NetworkPorts, "", "\t")
135-
NetworkPorts.Mu.Unlock()
133+
networkPorts.Mu.Lock()
134+
ls, err = json.MarshalIndent(&networkPorts, "", "\t")
135+
networkPorts.Mu.Unlock()
136136
} else {
137-
SerialPorts.Mu.Lock()
138-
ls, err = json.MarshalIndent(&SerialPorts, "", "\t")
139-
SerialPorts.Mu.Unlock()
137+
serialPorts.Mu.Lock()
138+
ls, err = json.MarshalIndent(&serialPorts, "", "\t")
139+
serialPorts.Mu.Unlock()
140140
}
141141
if err != nil {
142142
//log.Println(err)
@@ -149,81 +149,73 @@ func spList(network bool) {
149149

150150
// discoverLoop periodically update the list of ports found
151151
func discoverLoop() {
152-
SerialPorts.Mu.Lock()
153-
SerialPorts.Network = false
154-
SerialPorts.Ports = make([]SpPortItem, 0)
155-
SerialPorts.Mu.Unlock()
156-
NetworkPorts.Mu.Lock()
157-
NetworkPorts.Network = true
158-
NetworkPorts.Ports = make([]SpPortItem, 0)
159-
NetworkPorts.Mu.Unlock()
152+
serialPorts.Mu.Lock()
153+
serialPorts.Network = false
154+
serialPorts.Ports = make([]SpPortItem, 0)
155+
serialPorts.Mu.Unlock()
156+
networkPorts.Mu.Lock()
157+
networkPorts.Network = true
158+
networkPorts.Ports = make([]SpPortItem, 0)
159+
networkPorts.Mu.Unlock()
160160

161161
go func() {
162162
for {
163163
if !upload.Busy {
164-
spListDual(false)
164+
updateSerialPortList()
165165
}
166166
time.Sleep(2 * time.Second)
167167
}
168168
}()
169169
go func() {
170170
for {
171-
spListDual(true)
171+
updateNetworkPortList()
172172
time.Sleep(2 * time.Second)
173173
}
174174
}()
175175
}
176176

177-
func spListDual(network bool) {
177+
var serialEnumeratorLock sync.Mutex
178178

179-
// call our os specific implementation of getting the serial list
180-
list, err := GetList(network)
179+
func updateSerialPortList() {
180+
if !serialEnumeratorLock.TryLock() {
181+
return
182+
}
183+
defer serialEnumeratorLock.Unlock()
184+
ports, err := enumerateSerialPorts()
185+
if err != nil {
186+
// TODO: report error?
181187

182-
//log.Println(list)
183-
//log.Println(err)
188+
// Empty port list if they can not be detected
189+
ports = []OsSerialPort{}
190+
}
191+
list := spListDual(ports)
192+
serialPorts.Mu.Lock()
193+
serialPorts.Ports = list
194+
serialPorts.Mu.Unlock()
195+
}
184196

197+
func updateNetworkPortList() {
198+
ports, err := enumerateNetworkPorts()
185199
if err != nil {
186-
// avoid reporting dummy data if an error occurred
187-
return
188-
}
200+
// TODO: report error?
189201

190-
// do a quick loop to see if any of our open ports
191-
// did not end up in the list port list. this can
192-
// happen on windows in a fallback scenario where an
193-
// open port can't be identified because it is locked,
194-
// so just solve that by manually inserting
195-
// if network {
196-
// for port := range sh.ports {
197-
198-
// isFound := false
199-
// for _, item := range list {
200-
// if strings.ToLower(port.portConf.Name) == strings.ToLower(item.Name) {
201-
// isFound = true
202-
// }
203-
// }
204-
205-
// if !isFound {
206-
// // artificially push to front of port list
207-
// log.Println(fmt.Sprintf("Did not find an open port in the serial port list. We are going to artificially push it onto the list. port:%v", port.portConf.Name))
208-
// var ossp OsSerialPort
209-
// ossp.Name = port.portConf.Name
210-
// ossp.FriendlyName = port.portConf.Name
211-
// list = append([]OsSerialPort{ossp}, list...)
212-
// }
213-
// }
214-
// }
202+
// Empty port list if they can not be detected
203+
ports = []OsSerialPort{}
204+
}
205+
list := spListDual(ports)
206+
networkPorts.Mu.Lock()
207+
networkPorts.Ports = list
208+
networkPorts.Mu.Unlock()
209+
}
215210

211+
func spListDual(list []OsSerialPort) []SpPortItem {
216212
// we have a full clean list of ports now. iterate thru them
217213
// to append the open/close state, baud rates, etc to make
218214
// a super clean nice list to send back to browser
219-
n := len(list)
220-
spl := make([]SpPortItem, n)
221-
222-
ctr := 0
215+
spl := []SpPortItem{}
223216

224217
for _, item := range list {
225-
226-
spl[ctr] = SpPortItem{
218+
port := SpPortItem{
227219
Name: item.Name,
228220
SerialNumber: item.ISerial,
229221
DeviceClass: item.DeviceClass,
@@ -238,26 +230,15 @@ func spListDual(network bool) {
238230
}
239231

240232
// figure out if port is open
241-
myport, isFound := findPortByName(item.Name)
242-
243-
if isFound {
244-
// we found our port
245-
spl[ctr].IsOpen = true
246-
spl[ctr].Baud = myport.portConf.Baud
247-
spl[ctr].BufferAlgorithm = myport.BufferType
233+
if myport, isFound := findPortByName(item.Name); isFound {
234+
// and update data with the open port parameters
235+
port.IsOpen = true
236+
port.Baud = myport.portConf.Baud
237+
port.BufferAlgorithm = myport.BufferType
248238
}
249-
ctr++
250-
}
251-
252-
if network {
253-
NetworkPorts.Mu.Lock()
254-
NetworkPorts.Ports = spl
255-
NetworkPorts.Mu.Unlock()
256-
} else {
257-
SerialPorts.Mu.Lock()
258-
SerialPorts.Ports = spl
259-
SerialPorts.Mu.Unlock()
239+
spl = append(spl, port)
260240
}
241+
return spl
261242
}
262243

263244
func spErr(err string) {

seriallist.go

+2-8
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,8 @@ type OsSerialPort struct {
3838
NetworkPort bool
3939
}
4040

41-
// GetList will return the OS serial port
42-
func GetList(network bool) ([]OsSerialPort, error) {
43-
44-
if network {
45-
netportList, err := GetNetworkList()
46-
return netportList, err
47-
}
48-
41+
// enumerateSerialPorts will return the OS serial port
42+
func enumerateSerialPorts() ([]OsSerialPort, error) {
4943
// will timeout in 2 seconds
5044
arrPorts := []OsSerialPort{}
5145
ports, err := enumerator.GetDetailedPortsList()

0 commit comments

Comments
 (0)