Skip to content

Commit 2a60321

Browse files
committed
Fix gRPC BoardListWatch crashing when installing/uninstalling a core/lib
1 parent 1a3250b commit 2a60321

File tree

6 files changed

+71
-41
lines changed

6 files changed

+71
-41
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

+22-3
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,25 @@ func Watch(instanceID int32, interrupt <-chan bool) (<-chan *rpc.BoardListWatchR
258258
for {
259259
select {
260260
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+
261280
port := &rpc.DetectedPort{
262281
Port: event.Port.ToRPC(),
263282
}
@@ -276,11 +295,11 @@ func Watch(instanceID int32, interrupt <-chan bool) (<-chan *rpc.BoardListWatchR
276295
Error: boardsError,
277296
}
278297
case <-interrupt:
279-
err := pm.DiscoveryManager().StopAll()
280-
if err != nil {
298+
errs := dm.StopAll()
299+
if len(errs) > 0 {
281300
outChan <- &rpc.BoardListWatchResponse{
282301
EventType: "error",
283-
Error: tr("stopping discoveries: %s", err),
302+
Error: tr("stopping discoveries: %s", errs),
284303
}
285304
// Don't close the channel if quitting all discoveries
286305
// 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

+25-25
Original file line numberDiff line numberDiff line change
@@ -2388,12 +2388,12 @@ msgstr "board not found"
23882388
msgid "boardname"
23892389
msgstr "boardname"
23902390

2391-
#: arduino/discovery/discovery.go:297
2392-
#: arduino/discovery/discovery.go:318
2393-
#: arduino/discovery/discovery.go:338
2394-
#: arduino/discovery/discovery.go:361
2395-
#: arduino/discovery/discovery.go:384
2396-
#: arduino/discovery/discovery.go:407
2391+
#: arduino/discovery/discovery.go:300
2392+
#: arduino/discovery/discovery.go:321
2393+
#: arduino/discovery/discovery.go:341
2394+
#: arduino/discovery/discovery.go:364
2395+
#: arduino/discovery/discovery.go:387
2396+
#: arduino/discovery/discovery.go:410
23972397
#: arduino/monitor/monitor.go:246
23982398
msgid "calling %[1]s: %[2]w"
23992399
msgstr "calling %[1]s: %[2]w"
@@ -2441,12 +2441,12 @@ msgstr "cleaning build path"
24412441
msgid "command"
24422442
msgstr "command"
24432443

2444-
#: arduino/discovery/discovery.go:301
2445-
#: arduino/discovery/discovery.go:322
2446-
#: arduino/discovery/discovery.go:342
2447-
#: arduino/discovery/discovery.go:365
2448-
#: arduino/discovery/discovery.go:388
2449-
#: arduino/discovery/discovery.go:411
2444+
#: arduino/discovery/discovery.go:304
2445+
#: arduino/discovery/discovery.go:325
2446+
#: arduino/discovery/discovery.go:345
2447+
#: arduino/discovery/discovery.go:368
2448+
#: arduino/discovery/discovery.go:391
2449+
#: arduino/discovery/discovery.go:414
24502450
#: arduino/monitor/monitor.go:250
24512451
#: arduino/monitor/monitor.go:270
24522452
#: arduino/monitor/monitor.go:287
@@ -2467,32 +2467,32 @@ msgstr "communication out of sync, expected 'configure', received '%s'"
24672467
msgid "communication out of sync, expected 'describe', received '%s'"
24682468
msgstr "communication out of sync, expected 'describe', received '%s'"
24692469

2470-
#: arduino/discovery/discovery.go:299
2470+
#: arduino/discovery/discovery.go:302
24712471
#: arduino/monitor/monitor.go:248
24722472
msgid "communication out of sync, expected 'hello', received '%s'"
24732473
msgstr "communication out of sync, expected 'hello', received '%s'"
24742474

2475-
#: arduino/discovery/discovery.go:386
2475+
#: arduino/discovery/discovery.go:389
24762476
msgid "communication out of sync, expected 'list', received '%s'"
24772477
msgstr "communication out of sync, expected 'list', received '%s'"
24782478

24792479
#: arduino/monitor/monitor.go:321
24802480
msgid "communication out of sync, expected 'open', received '%s'"
24812481
msgstr "communication out of sync, expected 'open', received '%s'"
24822482

2483-
#: arduino/discovery/discovery.go:363
2483+
#: arduino/discovery/discovery.go:366
24842484
msgid "communication out of sync, expected 'quit', received '%s'"
24852485
msgstr "communication out of sync, expected 'quit', received '%s'"
24862486

2487-
#: arduino/discovery/discovery.go:320
2487+
#: arduino/discovery/discovery.go:323
24882488
msgid "communication out of sync, expected 'start', received '%s'"
24892489
msgstr "communication out of sync, expected 'start', received '%s'"
24902490

2491-
#: arduino/discovery/discovery.go:409
2491+
#: arduino/discovery/discovery.go:412
24922492
msgid "communication out of sync, expected 'start_sync', received '%s'"
24932493
msgstr "communication out of sync, expected 'start_sync', received '%s'"
24942494

2495-
#: arduino/discovery/discovery.go:340
2495+
#: arduino/discovery/discovery.go:343
24962496
msgid "communication out of sync, expected 'stop', received '%s'"
24972497
msgstr "communication out of sync, expected 'stop', received '%s'"
24982498

@@ -2706,11 +2706,11 @@ msgstr "installing %[1]s tool: %[2]s"
27062706
msgid "installing platform %[1]s: %[2]s"
27072707
msgstr "installing platform %[1]s: %[2]s"
27082708

2709-
#: arduino/discovery/discovery.go:184
2709+
#: arduino/discovery/discovery.go:190
27102710
msgid "invalid 'add' message: missing port"
27112711
msgstr "invalid 'add' message: missing port"
27122712

2713-
#: arduino/discovery/discovery.go:195
2713+
#: arduino/discovery/discovery.go:201
27142714
msgid "invalid 'remove' message: missing port"
27152715
msgstr "invalid 'remove' message: missing port"
27162716

@@ -2840,7 +2840,7 @@ msgstr "library is not valid: missing header file \"%s\""
28402840
msgid "library path does not exist: %s"
28412841
msgstr "library path does not exist: %s"
28422842

2843-
#: arduino/discovery/discoverymanager/discoverymanager.go:222
2843+
#: arduino/discovery/discoverymanager/discoverymanager.go:225
28442844
msgid "listing ports from discovery %[1]s: %[2]w"
28452845
msgstr "listing ports from discovery %[1]s: %[2]w"
28462846

@@ -2938,7 +2938,7 @@ msgstr "no compatible version of %s tools found for the current os"
29382938
msgid "no executable specified"
29392939
msgstr "no executable specified"
29402940

2941-
#: commands/daemon/daemon.go:94
2941+
#: commands/daemon/daemon.go:96
29422942
msgid "no instance specified"
29432943
msgstr "no instance specified"
29442944

@@ -3050,7 +3050,7 @@ msgstr "port"
30503050
msgid "port not found: %[1]s %[2]s"
30513051
msgstr "port not found: %[1]s %[2]s"
30523052

3053-
#: arduino/discovery/discovery.go:303
3053+
#: arduino/discovery/discovery.go:306
30543054
#: arduino/monitor/monitor.go:252
30553055
msgid "protocol version not supported: requested 1, got %d"
30563056
msgstr "protocol version not supported: requested 1, got %d"
@@ -3197,7 +3197,7 @@ msgstr "start syncing discovery %[1]s: %[2]w"
31973197
msgid "starting discovery %[1]s: %[2]w"
31983198
msgstr "starting discovery %[1]s: %[2]w"
31993199

3200-
#: commands/board/list.go:283
3200+
#: commands/board/list.go:302
32013201
msgid "stopping discoveries: %s"
32023202
msgstr "stopping discoveries: %s"
32033203

@@ -3233,7 +3233,7 @@ msgstr "the platform has no releases"
32333233
msgid "the server responded with status %s"
32343234
msgstr "the server responded with status %s"
32353235

3236-
#: arduino/discovery/discovery.go:228
3236+
#: arduino/discovery/discovery.go:231
32373237
msgid "timeout waiting for message from %s"
32383238
msgstr "timeout waiting for message from %s"
32393239

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)