Skip to content

Commit 4bbacd3

Browse files
committed
Fix gRPC BoardListWatch crashing when installing/uninstalling a core/lib (#1460)
1 parent 56419ec commit 4bbacd3

File tree

6 files changed

+92
-56
lines changed

6 files changed

+92
-56
lines changed

Diff for: arduino/discovery/discovery.go

+9-6
Original file line numberDiff line numberDiff line change
@@ -168,13 +168,19 @@ func (disc *PluggableDiscovery) jsonDecodeLoop(in io.Reader, outChan chan<- *dis
168168
disc.incomingMessagesError = err
169169
disc.statusMutex.Unlock()
170170
close(outChan)
171-
logrus.Errorf("stopped discovery %s decode loop", disc.id)
172-
// TODO: Try restarting process some times before closing it completely
171+
logrus.Errorf("stopped discovery %s decode loop: %v", disc.id, err)
173172
}
174173

175174
for {
176175
var msg discoveryMessage
177-
if err := decoder.Decode(&msg); err != nil {
176+
if err := decoder.Decode(&msg); err == io.EOF {
177+
// This is fine, we exit gracefully
178+
disc.statusMutex.Lock()
179+
disc.state = Dead
180+
disc.statusMutex.Unlock()
181+
close(outChan)
182+
return
183+
} else if err != nil {
178184
closeAndReportError(err)
179185
return
180186
}
@@ -218,9 +224,6 @@ func (disc *PluggableDiscovery) waitMessage(timeout time.Duration) (*discoveryMe
218224
select {
219225
case msg := <-disc.incomingMessagesChan:
220226
if msg == nil {
221-
// channel has been closed
222-
disc.statusMutex.Lock()
223-
defer disc.statusMutex.Unlock()
224227
return nil, disc.incomingMessagesError
225228
}
226229
return msg, nil

Diff for: arduino/discovery/discoverymanager/discoverymanager.go

+3
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,9 @@ func (dm *DiscoveryManager) QuitAll() []error {
192192
// Close the global channel only if there were no errors
193193
// quitting all alive discoveries
194194
if len(errs) == 0 && dm.globalEventCh != nil {
195+
// Let events consumers that discoveries are quitting no more events
196+
// will be sent on this channel
197+
dm.globalEventCh <- &discovery.Event{Type: "quit"}
195198
close(dm.globalEventCh)
196199
dm.globalEventCh = nil
197200
}

Diff for: commands/board/list.go

+30-5
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,15 @@ import (
3535
"github.com/sirupsen/logrus"
3636
)
3737

38+
type boardNotFoundError struct{}
39+
40+
func (e *boardNotFoundError) Error() string {
41+
return tr("board not found")
42+
}
43+
3844
var (
3945
// ErrNotFound is returned when the API returns 404
40-
ErrNotFound = errors.New(tr("board not found"))
46+
ErrNotFound = &boardNotFoundError{}
4147
vidPidURL = "https://builder.arduino.cc/v3/boards/byVidPid"
4248
validVidPid = regexp.MustCompile(`0[xX][a-fA-F\d]{4}`)
4349
)
@@ -132,7 +138,7 @@ func identify(pm *packagemanager.PackageManager, port *discovery.Port) ([]*rpc.B
132138
// the builder API if the board is a USB device port
133139
if len(boards) == 0 {
134140
items, err := identifyViaCloudAPI(port)
135-
if err == ErrNotFound {
141+
if errors.Is(err, ErrNotFound) {
136142
// the board couldn't be detected, print a warning
137143
logrus.Debug("Board not recognized")
138144
} else if err != nil {
@@ -252,6 +258,25 @@ func Watch(instanceID int32, interrupt <-chan bool) (<-chan *rpc.BoardListWatchR
252258
for {
253259
select {
254260
case event := <-eventsChan:
261+
if event.Type == "quit" {
262+
// The discovery manager has closed its event channel because it's
263+
// quitting all the discovery processes that are running, this
264+
// means that the events channel we're listening from won't receive any
265+
// more events.
266+
// Handling this case is necessary when the board watcher is running and
267+
// the instance being used is reinitialized since that quits all the
268+
// discovery processes and reset the discovery manager. That would leave
269+
// this goroutine listening forever on a "dead" channel and might even
270+
// cause panics.
271+
// This message avoid all this issues.
272+
// It will be the client's task restarting the board watcher if necessary,
273+
// this host won't attempt restarting it.
274+
outChan <- &rpc.BoardListWatchResponse{
275+
EventType: event.Type,
276+
}
277+
return
278+
}
279+
255280
port := &rpc.DetectedPort{
256281
Port: event.Port.ToRPC(),
257282
}
@@ -270,11 +295,11 @@ func Watch(instanceID int32, interrupt <-chan bool) (<-chan *rpc.BoardListWatchR
270295
Error: boardsError,
271296
}
272297
case <-interrupt:
273-
err := pm.DiscoveryManager().StopAll()
274-
if err != nil {
298+
errs := dm.StopAll()
299+
if len(errs) > 0 {
275300
outChan <- &rpc.BoardListWatchResponse{
276301
EventType: "error",
277-
Error: fmt.Sprintf(tr("stopping discoveries: %s"), err),
302+
Error: tr("stopping discoveries: %s", errs),
278303
}
279304
// Don't close the channel if quitting all discoveries
280305
// failed, otherwise some processes might be left running.

Diff for: commands/daemon/daemon.go

+5
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ import (
3131
"github.com/arduino/arduino-cli/i18n"
3232
rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
3333
"github.com/sirupsen/logrus"
34+
"google.golang.org/grpc/codes"
35+
"google.golang.org/grpc/status"
3436
)
3537

3638
// ArduinoCoreServerImpl FIXMEDOC
@@ -109,6 +111,9 @@ func (s *ArduinoCoreServerImpl) BoardListWatch(stream rpc.ArduinoCoreService_Boa
109111
logrus.Info("boards watcher stream closed")
110112
interrupt <- true
111113
return
114+
} else if st, ok := status.FromError(err); ok && st.Code() == codes.Canceled {
115+
logrus.Info("boards watcher interrupted by host")
116+
return
112117
} else if err != nil {
113118
logrus.Infof("interrupting boards watcher: %v", err)
114119
interrupt <- true

Diff for: i18n/data/en.po

+38-38
Original file line numberDiff line numberDiff line change
@@ -768,11 +768,11 @@ msgstr "Error getting absolute path of sketch archive"
768768
msgid "Error getting board details: %v"
769769
msgstr "Error getting board details: %v"
770770

771-
#: commands/board/list.go:140
771+
#: commands/board/list.go:146
772772
msgid "Error getting board info from Arduino Cloud"
773773
msgstr "Error getting board info from Arduino Cloud"
774774

775-
#: commands/board/list.go:205
775+
#: commands/board/list.go:211
776776
msgid "Error getting board list"
777777
msgstr "Error getting board list"
778778

@@ -897,9 +897,9 @@ msgstr "Error searching for platforms: %v"
897897
msgid "Error serializing compilation database: %s"
898898
msgstr "Error serializing compilation database: %s"
899899

900-
#: commands/board/list.go:190
901-
#: commands/board/list.go:193
902-
#: commands/board/list.go:234
900+
#: commands/board/list.go:196
901+
#: commands/board/list.go:199
902+
#: commands/board/list.go:240
903903
msgid "Error starting board discoveries"
904904
msgstr "Error starting board discoveries"
905905

@@ -1281,7 +1281,7 @@ msgstr "Invalid package index in %s"
12811281
msgid "Invalid parameter %s: version not allowed"
12821282
msgstr "Invalid parameter %s: version not allowed"
12831283

1284-
#: commands/board/list.go:51
1284+
#: commands/board/list.go:57
12851285
msgid "Invalid pid value: '%s'"
12861286
msgstr "Invalid pid value: '%s'"
12871287

@@ -1293,7 +1293,7 @@ msgstr "Invalid size regexp: %s"
12931293
msgid "Invalid version"
12941294
msgstr "Invalid version"
12951295

1296-
#: commands/board/list.go:48
1296+
#: commands/board/list.go:54
12971297
msgid "Invalid vid value: '%s'"
12981298
msgstr "Invalid vid value: '%s'"
12991299

@@ -2421,7 +2421,7 @@ msgstr "binary file not found in %s"
24212421
msgid "board %s:%s not found"
24222422
msgstr "board %s:%s not found"
24232423

2424-
#: commands/board/list.go:40
2424+
#: commands/board/list.go:41
24252425
msgid "board not found"
24262426
msgstr "board not found"
24272427

@@ -2430,12 +2430,12 @@ msgstr "board not found"
24302430
msgid "boardname"
24312431
msgstr "boardname"
24322432

2433-
#: arduino/discovery/discovery.go:297
2434-
#: arduino/discovery/discovery.go:318
2435-
#: arduino/discovery/discovery.go:338
2436-
#: arduino/discovery/discovery.go:361
2437-
#: arduino/discovery/discovery.go:384
2438-
#: arduino/discovery/discovery.go:407
2433+
#: arduino/discovery/discovery.go:300
2434+
#: arduino/discovery/discovery.go:321
2435+
#: arduino/discovery/discovery.go:341
2436+
#: arduino/discovery/discovery.go:364
2437+
#: arduino/discovery/discovery.go:387
2438+
#: arduino/discovery/discovery.go:410
24392439
msgid "calling %[1]s: %[2]w"
24402440
msgstr "calling %[1]s: %[2]w"
24412441

@@ -2477,36 +2477,36 @@ msgstr "cleaning build path"
24772477
msgid "command"
24782478
msgstr "command"
24792479

2480-
#: arduino/discovery/discovery.go:301
2481-
#: arduino/discovery/discovery.go:322
2482-
#: arduino/discovery/discovery.go:342
2483-
#: arduino/discovery/discovery.go:365
2484-
#: arduino/discovery/discovery.go:388
2485-
#: arduino/discovery/discovery.go:411
2480+
#: arduino/discovery/discovery.go:304
2481+
#: arduino/discovery/discovery.go:325
2482+
#: arduino/discovery/discovery.go:345
2483+
#: arduino/discovery/discovery.go:368
2484+
#: arduino/discovery/discovery.go:391
2485+
#: arduino/discovery/discovery.go:414
24862486
msgid "command failed: %s"
24872487
msgstr "command failed: %s"
24882488

2489-
#: arduino/discovery/discovery.go:299
2489+
#: arduino/discovery/discovery.go:302
24902490
msgid "communication out of sync, expected 'hello', received '%s'"
24912491
msgstr "communication out of sync, expected 'hello', received '%s'"
24922492

2493-
#: arduino/discovery/discovery.go:386
2493+
#: arduino/discovery/discovery.go:389
24942494
msgid "communication out of sync, expected 'list', received '%s'"
24952495
msgstr "communication out of sync, expected 'list', received '%s'"
24962496

2497-
#: arduino/discovery/discovery.go:363
2497+
#: arduino/discovery/discovery.go:366
24982498
msgid "communication out of sync, expected 'quit', received '%s'"
24992499
msgstr "communication out of sync, expected 'quit', received '%s'"
25002500

2501-
#: arduino/discovery/discovery.go:320
2501+
#: arduino/discovery/discovery.go:323
25022502
msgid "communication out of sync, expected 'start', received '%s'"
25032503
msgstr "communication out of sync, expected 'start', received '%s'"
25042504

2505-
#: arduino/discovery/discovery.go:409
2505+
#: arduino/discovery/discovery.go:412
25062506
msgid "communication out of sync, expected 'start_sync', received '%s'"
25072507
msgstr "communication out of sync, expected 'start_sync', received '%s'"
25082508

2509-
#: arduino/discovery/discovery.go:340
2509+
#: arduino/discovery/discovery.go:343
25102510
msgid "communication out of sync, expected 'stop', received '%s'"
25112511
msgstr "communication out of sync, expected 'stop', received '%s'"
25122512

@@ -2599,11 +2599,11 @@ msgstr "error opening serial monitor"
25992599
msgid "error parsing value: %v"
26002600
msgstr "error parsing value: %v"
26012601

2602-
#: commands/board/list.go:81
2602+
#: commands/board/list.go:87
26032603
msgid "error processing response from server"
26042604
msgstr "error processing response from server"
26052605

2606-
#: commands/board/list.go:96
2606+
#: commands/board/list.go:102
26072607
msgid "error querying Arduino Cloud Api"
26082608
msgstr "error querying Arduino Cloud Api"
26092609

@@ -2623,7 +2623,7 @@ msgstr "extracting archive: %w"
26232623
msgid "failed to compute hash of file \"%s\""
26242624
msgstr "failed to compute hash of file \"%s\""
26252625

2626-
#: commands/board/list.go:64
2626+
#: commands/board/list.go:70
26272627
msgid "failed to initialize http client"
26282628
msgstr "failed to initialize http client"
26292629

@@ -2726,11 +2726,11 @@ msgstr "installing %[1]s tool: %[2]s"
27262726
msgid "installing platform %[1]s: %[2]s"
27272727
msgstr "installing platform %[1]s: %[2]s"
27282728

2729-
#: arduino/discovery/discovery.go:184
2729+
#: arduino/discovery/discovery.go:190
27302730
msgid "invalid 'add' message: missing port"
27312731
msgstr "invalid 'add' message: missing port"
27322732

2733-
#: arduino/discovery/discovery.go:195
2733+
#: arduino/discovery/discovery.go:201
27342734
msgid "invalid 'remove' message: missing port"
27352735
msgstr "invalid 'remove' message: missing port"
27362736

@@ -2860,7 +2860,7 @@ msgstr "library is not valid: missing header file \"%s\""
28602860
msgid "library path does not exist: %s"
28612861
msgstr "library path does not exist: %s"
28622862

2863-
#: arduino/discovery/discoverymanager/discoverymanager.go:222
2863+
#: arduino/discovery/discoverymanager/discoverymanager.go:225
28642864
msgid "listing ports from discovery %[1]s: %[2]w"
28652865
msgstr "listing ports from discovery %[1]s: %[2]w"
28662866

@@ -2954,7 +2954,7 @@ msgstr "no compatible version of %s tools found for the current os"
29542954
msgid "no executable specified"
29552955
msgstr "no executable specified"
29562956

2957-
#: commands/daemon/daemon.go:94
2957+
#: commands/daemon/daemon.go:96
29582958
msgid "no instance specified"
29592959
msgstr "no instance specified"
29602960

@@ -3065,7 +3065,7 @@ msgstr "port"
30653065
msgid "port not found: %[1]s %[2]s"
30663066
msgstr "port not found: %[1]s %[2]s"
30673067

3068-
#: arduino/discovery/discovery.go:303
3068+
#: arduino/discovery/discovery.go:306
30693069
msgid "protocol version not supported: requested 1, got %d"
30703070
msgstr "protocol version not supported: requested 1, got %d"
30713071

@@ -3210,7 +3210,7 @@ msgstr "start syncing discovery %[1]s: %[2]w"
32103210
msgid "starting discovery %[1]s: %[2]w"
32113211
msgstr "starting discovery %[1]s: %[2]w"
32123212

3213-
#: commands/board/list.go:277
3213+
#: commands/board/list.go:302
32143214
msgid "stopping discoveries: %s"
32153215
msgstr "stopping discoveries: %s"
32163216

@@ -3246,11 +3246,11 @@ msgstr "the library name is different from the set (%[1]s != %[2]s)"
32463246
msgid "the platform has no releases"
32473247
msgstr "the platform has no releases"
32483248

3249-
#: commands/board/list.go:72
3249+
#: commands/board/list.go:78
32503250
msgid "the server responded with status %s"
32513251
msgstr "the server responded with status %s"
32523252

3253-
#: arduino/discovery/discovery.go:228
3253+
#: arduino/discovery/discovery.go:231
32543254
msgid "timeout waiting for message from %s"
32553255
msgstr "timeout waiting for message from %s"
32563256

@@ -3367,7 +3367,7 @@ msgstr "uploading error: %s"
33673367
msgid "writing sketch metadata %[1]s: %[2]s"
33683368
msgstr "writing sketch metadata %[1]s: %[2]s"
33693369

3370-
#: commands/board/list.go:88
3370+
#: commands/board/list.go:94
33713371
msgid "wrong format in server response"
33723372
msgstr "wrong format in server response"
33733373

Diff for: i18n/rice-box.go

+7-7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)