Skip to content

Commit 549b0fb

Browse files
author
Massimiliano Pippi
authored
rewrite the list logic (arduino#382)
1 parent c67e23a commit 549b0fb

File tree

2 files changed

+54
-85
lines changed

2 files changed

+54
-85
lines changed

commands/board/list.go

+1-6
Original file line numberDiff line numberDiff line change
@@ -83,12 +83,7 @@ func List(instanceID int32) ([]*rpc.DetectedPort, error) {
8383
return nil, errors.New("invalid instance")
8484
}
8585

86-
serialDiscovery, err := commands.NewBuiltinSerialDiscovery(pm)
87-
if err != nil {
88-
return nil, errors.Wrap(err, "unable to instance serial-discovery")
89-
}
90-
91-
ports, err := serialDiscovery.List()
86+
ports, err := commands.ListBoards(pm)
9287
if err != nil {
9388
return nil, errors.Wrap(err, "error getting port list from serial-discovery")
9489
}

commands/bundled_tools_serial_discovery.go

+53-79
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,6 @@ package commands
2020
import (
2121
"encoding/json"
2222
"fmt"
23-
"io"
24-
"os/exec"
25-
"strings"
2623
"sync"
2724
"time"
2825

@@ -36,6 +33,7 @@ import (
3633
)
3734

3835
var (
36+
mutex = sync.Mutex{}
3937
sdVersion = semver.ParseRelaxed("1.0.0")
4038
flavors = []*cores.Flavor{
4139
{
@@ -101,16 +99,6 @@ var (
10199
}
102100
)
103101

104-
// SerialDiscovery is an instance of a discovery tool
105-
type SerialDiscovery struct {
106-
sync.Mutex
107-
ID string
108-
in io.WriteCloser
109-
out io.ReadCloser
110-
outJSON *json.Decoder
111-
cmd *exec.Cmd
112-
}
113-
114102
// BoardPort is a generic port descriptor
115103
type BoardPort struct {
116104
Address string `json:"address"`
@@ -126,100 +114,86 @@ type eventJSON struct {
126114
Ports []*BoardPort `json:"ports"`
127115
}
128116

129-
// NewBuiltinSerialDiscovery returns a wrapper to control the serial-discovery program
130-
func NewBuiltinSerialDiscovery(pm *packagemanager.PackageManager) (*SerialDiscovery, error) {
117+
// ListBoards foo
118+
func ListBoards(pm *packagemanager.PackageManager) ([]*BoardPort, error) {
119+
// ensure the connection to the discoverer is unique to avoid messing up
120+
// the messages exchanged
121+
mutex.Lock()
122+
defer mutex.Unlock()
123+
124+
// get the bundled tool
131125
t, err := getBuiltinSerialDiscoveryTool(pm)
132126
if err != nil {
133127
return nil, err
134128
}
135129

130+
// determine if it's installed
136131
if !t.IsInstalled() {
137132
return nil, fmt.Errorf("missing serial-discovery tool")
138133
}
139134

140-
cmdArgs := []string{
141-
t.InstallDir.Join("serial-discovery").String(),
142-
}
143-
144-
cmd, err := executils.Command(cmdArgs)
135+
// build the command to be executed
136+
args := []string{t.InstallDir.Join("serial-discovery").String()}
137+
cmd, err := executils.Command(args)
145138
if err != nil {
146139
return nil, errors.Wrap(err, "creating discovery process")
147140
}
148141

149-
return &SerialDiscovery{
150-
ID: strings.Join(cmdArgs, " "),
151-
cmd: cmd,
152-
}, nil
153-
}
154-
155-
// Start starts the specified discovery
156-
func (d *SerialDiscovery) start() error {
157-
if in, err := d.cmd.StdinPipe(); err == nil {
158-
d.in = in
159-
} else {
160-
return fmt.Errorf("creating stdin pipe for discovery: %s", err)
161-
}
162-
163-
if out, err := d.cmd.StdoutPipe(); err == nil {
164-
d.out = out
165-
d.outJSON = json.NewDecoder(d.out)
166-
} else {
167-
return fmt.Errorf("creating stdout pipe for discovery: %s", err)
142+
// attach in/out pipes to the process
143+
in, err := cmd.StdinPipe()
144+
if err != nil {
145+
return nil, fmt.Errorf("creating stdin pipe for discovery: %s", err)
168146
}
169147

170-
if err := d.cmd.Start(); err != nil {
171-
return fmt.Errorf("starting discovery process: %s", err)
148+
out, err := cmd.StdoutPipe()
149+
if err != nil {
150+
return nil, fmt.Errorf("creating stdout pipe for discovery: %s", err)
172151
}
152+
outJSON := json.NewDecoder(out)
173153

174-
return nil
175-
}
176-
177-
// List retrieve the port list from this discovery
178-
func (d *SerialDiscovery) List() ([]*BoardPort, error) {
179-
// ensure the connection to the discoverer is unique to avoid messing up
180-
// the messages exchanged
181-
d.Lock()
182-
defer d.Unlock()
183-
184-
if err := d.start(); err != nil {
185-
return nil, fmt.Errorf("discovery hasn't started: %v", err)
154+
// start the process
155+
if err := cmd.Start(); err != nil {
156+
return nil, fmt.Errorf("starting discovery process: %s", err)
186157
}
187158

188-
if _, err := d.in.Write([]byte("LIST\n")); err != nil {
159+
// send the LIST command
160+
if _, err := in.Write([]byte("LIST\n")); err != nil {
189161
return nil, fmt.Errorf("sending LIST command to discovery: %s", err)
190162
}
163+
164+
// read the response from the pipe
165+
decodeResult := make(chan error)
191166
var event eventJSON
192-
done := make(chan bool)
193-
timeout := false
194167
go func() {
195-
select {
196-
case <-done:
197-
case <-time.After(10 * time.Second):
198-
timeout = true
199-
d.close()
200-
}
168+
decodeResult <- outJSON.Decode(&event)
201169
}()
202-
if err := d.outJSON.Decode(&event); err != nil {
203-
if timeout {
204-
return nil, fmt.Errorf("decoding LIST command: timeout")
170+
171+
var finalError error
172+
var retVal []*BoardPort
173+
174+
// wait for the response
175+
select {
176+
case err := <-decodeResult:
177+
if err == nil {
178+
retVal = event.Ports
179+
} else {
180+
finalError = err
205181
}
206-
return nil, fmt.Errorf("decoding LIST command: %s", err)
182+
case <-time.After(10 * time.Second):
183+
finalError = fmt.Errorf("decoding LIST command: timeout")
207184
}
208-
done <- true
209-
return event.Ports, d.close()
210-
}
211185

212-
// Close stops the Discovery and free the resources
213-
func (d *SerialDiscovery) close() error {
214-
_, _ = d.in.Write([]byte("QUIT\n"))
215-
_ = d.in.Close()
216-
_ = d.out.Close()
217-
timer := time.AfterFunc(time.Second, func() {
218-
_ = d.cmd.Process.Kill()
186+
// tell the process to quit
187+
in.Write([]byte("QUIT\n"))
188+
in.Close()
189+
out.Close()
190+
// kill the process if it takes too long to quit
191+
time.AfterFunc(time.Second, func() {
192+
cmd.Process.Kill()
219193
})
220-
err := d.cmd.Wait()
221-
_ = timer.Stop()
222-
return err
194+
cmd.Wait()
195+
196+
return retVal, finalError
223197
}
224198

225199
func getBuiltinSerialDiscoveryTool(pm *packagemanager.PackageManager) (*cores.ToolRelease, error) {

0 commit comments

Comments
 (0)