Skip to content

Commit 5d3bbb7

Browse files
committed
Fix gRPC BoardListWatch crashing when installing/uninstalling a core/lib
1 parent 9f160e8 commit 5d3bbb7

File tree

6 files changed

+71
-41
lines changed

6 files changed

+71
-41
lines changed

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

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
}

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.

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

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
msgid "calling %[1]s: %[2]w"
23982398
msgstr "calling %[1]s: %[2]w"
23992399

@@ -2440,36 +2440,36 @@ msgstr "cleaning build path"
24402440
msgid "command"
24412441
msgstr "command"
24422442

2443-
#: arduino/discovery/discovery.go:301
2444-
#: arduino/discovery/discovery.go:322
2445-
#: arduino/discovery/discovery.go:342
2446-
#: arduino/discovery/discovery.go:365
2447-
#: arduino/discovery/discovery.go:388
2448-
#: arduino/discovery/discovery.go:411
2443+
#: arduino/discovery/discovery.go:304
2444+
#: arduino/discovery/discovery.go:325
2445+
#: arduino/discovery/discovery.go:345
2446+
#: arduino/discovery/discovery.go:368
2447+
#: arduino/discovery/discovery.go:391
2448+
#: arduino/discovery/discovery.go:414
24492449
msgid "command failed: %s"
24502450
msgstr "command failed: %s"
24512451

2452-
#: arduino/discovery/discovery.go:299
2452+
#: arduino/discovery/discovery.go:302
24532453
msgid "communication out of sync, expected 'hello', received '%s'"
24542454
msgstr "communication out of sync, expected 'hello', received '%s'"
24552455

2456-
#: arduino/discovery/discovery.go:386
2456+
#: arduino/discovery/discovery.go:389
24572457
msgid "communication out of sync, expected 'list', received '%s'"
24582458
msgstr "communication out of sync, expected 'list', received '%s'"
24592459

2460-
#: arduino/discovery/discovery.go:363
2460+
#: arduino/discovery/discovery.go:366
24612461
msgid "communication out of sync, expected 'quit', received '%s'"
24622462
msgstr "communication out of sync, expected 'quit', received '%s'"
24632463

2464-
#: arduino/discovery/discovery.go:320
2464+
#: arduino/discovery/discovery.go:323
24652465
msgid "communication out of sync, expected 'start', received '%s'"
24662466
msgstr "communication out of sync, expected 'start', received '%s'"
24672467

2468-
#: arduino/discovery/discovery.go:409
2468+
#: arduino/discovery/discovery.go:412
24692469
msgid "communication out of sync, expected 'start_sync', received '%s'"
24702470
msgstr "communication out of sync, expected 'start_sync', received '%s'"
24712471

2472-
#: arduino/discovery/discovery.go:340
2472+
#: arduino/discovery/discovery.go:343
24732473
msgid "communication out of sync, expected 'stop', received '%s'"
24742474
msgstr "communication out of sync, expected 'stop', received '%s'"
24752475

@@ -2683,11 +2683,11 @@ msgstr "installing %[1]s tool: %[2]s"
26832683
msgid "installing platform %[1]s: %[2]s"
26842684
msgstr "installing platform %[1]s: %[2]s"
26852685

2686-
#: arduino/discovery/discovery.go:184
2686+
#: arduino/discovery/discovery.go:190
26872687
msgid "invalid 'add' message: missing port"
26882688
msgstr "invalid 'add' message: missing port"
26892689

2690-
#: arduino/discovery/discovery.go:195
2690+
#: arduino/discovery/discovery.go:201
26912691
msgid "invalid 'remove' message: missing port"
26922692
msgstr "invalid 'remove' message: missing port"
26932693

@@ -2817,7 +2817,7 @@ msgstr "library is not valid: missing header file \"%s\""
28172817
msgid "library path does not exist: %s"
28182818
msgstr "library path does not exist: %s"
28192819

2820-
#: arduino/discovery/discoverymanager/discoverymanager.go:222
2820+
#: arduino/discovery/discoverymanager/discoverymanager.go:225
28212821
msgid "listing ports from discovery %[1]s: %[2]w"
28222822
msgstr "listing ports from discovery %[1]s: %[2]w"
28232823

@@ -2915,7 +2915,7 @@ msgstr "no compatible version of %s tools found for the current os"
29152915
msgid "no executable specified"
29162916
msgstr "no executable specified"
29172917

2918-
#: commands/daemon/daemon.go:94
2918+
#: commands/daemon/daemon.go:96
29192919
msgid "no instance specified"
29202920
msgstr "no instance specified"
29212921

@@ -3027,7 +3027,7 @@ msgstr "port"
30273027
msgid "port not found: %[1]s %[2]s"
30283028
msgstr "port not found: %[1]s %[2]s"
30293029

3030-
#: arduino/discovery/discovery.go:303
3030+
#: arduino/discovery/discovery.go:306
30313031
msgid "protocol version not supported: requested 1, got %d"
30323032
msgstr "protocol version not supported: requested 1, got %d"
30333033

@@ -3173,7 +3173,7 @@ msgstr "start syncing discovery %[1]s: %[2]w"
31733173
msgid "starting discovery %[1]s: %[2]w"
31743174
msgstr "starting discovery %[1]s: %[2]w"
31753175

3176-
#: commands/board/list.go:283
3176+
#: commands/board/list.go:302
31773177
msgid "stopping discoveries: %s"
31783178
msgstr "stopping discoveries: %s"
31793179

@@ -3209,7 +3209,7 @@ msgstr "the platform has no releases"
32093209
msgid "the server responded with status %s"
32103210
msgstr "the server responded with status %s"
32113211

3212-
#: arduino/discovery/discovery.go:228
3212+
#: arduino/discovery/discovery.go:231
32133213
msgid "timeout waiting for message from %s"
32143214
msgstr "timeout waiting for message from %s"
32153215

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)