Skip to content

Commit 4bbacd3

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

File tree

6 files changed

+92
-56
lines changed

6 files changed

+92
-56
lines changed

arduino/discovery/discovery.go

Lines changed: 9 additions & 6 deletions
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

arduino/discovery/discoverymanager/discoverymanager.go

Lines changed: 3 additions & 0 deletions
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
}

commands/board/list.go

Lines changed: 30 additions & 5 deletions
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.

commands/daemon/daemon.go

Lines changed: 5 additions & 0 deletions
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

i18n/data/en.po

Lines changed: 38 additions & 38 deletions
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

i18n/rice-box.go

Lines changed: 7 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy