@@ -21,14 +21,12 @@ import (
21
21
"io"
22
22
"net"
23
23
"strings"
24
- "sync"
25
24
"time"
26
25
27
26
"github.com/arduino/arduino-cli/cli/globals"
28
27
"github.com/arduino/arduino-cli/executils"
29
28
"github.com/arduino/arduino-cli/i18n"
30
29
rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
31
- "github.com/pkg/errors"
32
30
"github.com/sirupsen/logrus"
33
31
)
34
32
@@ -50,11 +48,10 @@ type PluggableMonitor struct {
50
48
outgoingCommandsPipe io.Writer
51
49
incomingMessagesChan <- chan * monitorMessage
52
50
supportedProtocol string
51
+ log * logrus.Entry
53
52
54
53
// All the following fields are guarded by statusMutex
55
- statusMutex sync.Mutex
56
54
incomingMessagesError error
57
- state int
58
55
}
59
56
60
57
type monitorMessage struct {
@@ -101,7 +98,7 @@ func New(id string, args ...string) *PluggableMonitor {
101
98
return & PluggableMonitor {
102
99
id : id ,
103
100
processArgs : args ,
104
- state : Dead ,
101
+ log : logrus . WithField ( "monitor" , id ) ,
105
102
}
106
103
}
107
104
@@ -116,54 +113,54 @@ func (mon *PluggableMonitor) String() string {
116
113
117
114
func (mon * PluggableMonitor ) jsonDecodeLoop (in io.Reader , outChan chan <- * monitorMessage ) {
118
115
decoder := json .NewDecoder (in )
119
- closeAndReportError := func (err error ) {
120
- mon .statusMutex .Lock ()
121
- mon .state = Dead
122
- mon .incomingMessagesError = err
123
- close (outChan )
124
- mon .statusMutex .Unlock ()
125
- logrus .Errorf ("stopped monitor %s decode loop" , mon .id )
126
- }
127
116
128
117
for {
129
118
var msg monitorMessage
130
119
if err := decoder .Decode (& msg ); err != nil {
131
- closeAndReportError (err )
120
+ mon .incomingMessagesError = err
121
+ close (outChan )
122
+ mon .log .Errorf ("stopped decode loop" )
132
123
return
133
124
}
134
- logrus .Infof ("from monitor %s received message %s" , mon .id , msg )
125
+ mon .log .
126
+ WithField ("event_type" , msg .EventType ).
127
+ WithField ("message" , msg .Message ).
128
+ WithField ("error" , msg .Error ).
129
+ Infof ("received message" )
135
130
if msg .EventType == "port_closed" {
136
- mon .statusMutex .Lock ()
137
- mon .state = Idle
138
- mon .statusMutex .Unlock ()
131
+ mon .log .Infof ("monitor port has been closed externally" )
139
132
} else {
140
133
outChan <- & msg
141
134
}
142
135
}
143
136
}
144
137
145
- // State returns the current state of this PluggableMonitor
146
- func (mon * PluggableMonitor ) State () int {
147
- mon .statusMutex .Lock ()
148
- defer mon .statusMutex .Unlock ()
149
- return mon .state
150
- }
151
-
152
- func (mon * PluggableMonitor ) waitMessage (timeout time.Duration ) (* monitorMessage , error ) {
138
+ func (mon * PluggableMonitor ) waitMessage (timeout time.Duration , expectedEvt string ) (* monitorMessage , error ) {
139
+ var msg * monitorMessage
153
140
select {
154
- case msg : = <- mon .incomingMessagesChan :
141
+ case msg = <- mon .incomingMessagesChan :
155
142
if msg == nil {
156
143
// channel has been closed
157
144
return nil , mon .incomingMessagesError
158
145
}
159
- return msg , nil
160
146
case <- time .After (timeout ):
161
- return nil , fmt .Errorf (tr ("timeout waiting for message from monitor %s" ), mon .id )
147
+ return nil , fmt .Errorf (tr ("timeout waiting for message" ))
148
+ }
149
+ if expectedEvt == "" {
150
+ // No message processing required for this call
151
+ return msg , nil
152
+ }
153
+ if msg .EventType != expectedEvt {
154
+ return msg , fmt .Errorf (tr ("communication out of sync, expected '%[1]s', received '%[2]s'" ), expectedEvt , msg .EventType )
155
+ }
156
+ if msg .Message != "OK" || msg .Error {
157
+ return msg , fmt .Errorf (tr ("command '%[1]s' failed: %[2]s" ), expectedEvt , msg .Message )
162
158
}
159
+ return msg , nil
163
160
}
164
161
165
162
func (mon * PluggableMonitor ) sendCommand (command string ) error {
166
- logrus . Infof ( "sending command %s to monitor %s " , strings .TrimSpace (command ), mon )
163
+ mon . log . WithField ( " command" , strings .TrimSpace (command )). Infof ( "sending command" )
167
164
data := []byte (command )
168
165
for {
169
166
n , err := mon .outgoingCommandsPipe .Write (data )
@@ -178,7 +175,7 @@ func (mon *PluggableMonitor) sendCommand(command string) error {
178
175
}
179
176
180
177
func (mon * PluggableMonitor ) runProcess () error {
181
- logrus . Infof ("starting monitor %s process" , mon . id )
178
+ mon . log . Infof ("Starting monitor process" )
182
179
proc , err := executils .NewProcess (mon .processArgs ... )
183
180
if err != nil {
184
181
return err
@@ -194,32 +191,27 @@ func (mon *PluggableMonitor) runProcess() error {
194
191
mon .outgoingCommandsPipe = stdin
195
192
mon .process = proc
196
193
194
+ if err := mon .process .Start (); err != nil {
195
+ return err
196
+ }
197
+
197
198
messageChan := make (chan * monitorMessage )
198
199
mon .incomingMessagesChan = messageChan
199
200
go mon .jsonDecodeLoop (stdout , messageChan )
200
201
201
- if err := mon .process .Start (); err != nil {
202
- return err
203
- }
204
- mon .statusMutex .Lock ()
205
- defer mon .statusMutex .Unlock ()
206
- mon .state = Alive
207
- logrus .Infof ("started monitor %s process" , mon .id )
202
+ mon .log .Infof ("Monitor process started successfully!" )
208
203
return nil
209
204
}
210
205
211
206
func (mon * PluggableMonitor ) killProcess () error {
212
- logrus . Infof ("killing monitor %s process" , mon . id )
207
+ mon . log . Infof ("Killing monitor process" )
213
208
if err := mon .process .Kill (); err != nil {
214
209
return err
215
210
}
216
211
if err := mon .process .Wait (); err != nil {
217
212
return err
218
213
}
219
- mon .statusMutex .Lock ()
220
- defer mon .statusMutex .Unlock ()
221
- mon .state = Dead
222
- logrus .Infof ("killed monitor %s process" , mon .id )
214
+ mon .log .Infof ("Monitor process killed successfully!" )
223
215
return nil
224
216
}
225
217
@@ -241,25 +233,18 @@ func (mon *PluggableMonitor) Run() (err error) {
241
233
if killErr := mon .killProcess (); killErr != nil {
242
234
// Log failure to kill the process, ideally that should never happen
243
235
// but it's best to know it if it does
244
- logrus . Errorf ("Killing monitor %s after unsuccessful start: %s" , mon . id , killErr )
236
+ mon . log . Errorf ("Killing monitor after unsuccessful start: %s" , killErr )
245
237
}
246
238
}()
247
239
248
240
if err = mon .sendCommand ("HELLO 1 \" arduino-cli " + globals .VersionInfo .VersionString + "\" \n " ); err != nil {
249
241
return err
250
242
}
251
- if msg , err := mon .waitMessage (time .Second * 10 ); err != nil {
252
- return fmt .Errorf (tr ("calling %[1]s: %[2]w" ), "HELLO" , err )
253
- } else if msg .EventType != "hello" {
254
- return errors .Errorf (tr ("communication out of sync, expected 'hello', received '%s'" ), msg .EventType )
255
- } else if msg .Message != "OK" || msg .Error {
256
- return errors .Errorf (tr ("command failed: %s" ), msg .Message )
243
+ if msg , err := mon .waitMessage (time .Second * 10 , "hello" ); err != nil {
244
+ return err
257
245
} else if msg .ProtocolVersion > 1 {
258
- return errors .Errorf (tr ("protocol version not supported: requested 1 , got %d" ), msg .ProtocolVersion )
246
+ return fmt .Errorf (tr ("protocol version not supported: requested %[1]d , got %[2] d" ), 1 , msg .ProtocolVersion )
259
247
}
260
- mon .statusMutex .Lock ()
261
- defer mon .statusMutex .Unlock ()
262
- mon .state = Idle
263
248
return nil
264
249
}
265
250
@@ -268,45 +253,25 @@ func (mon *PluggableMonitor) Describe() (*PortDescriptor, error) {
268
253
if err := mon .sendCommand ("DESCRIBE\n " ); err != nil {
269
254
return nil , err
270
255
}
271
- if msg , err := mon .waitMessage (time .Second * 10 ); err != nil {
272
- return nil , fmt .Errorf ("calling %s: %w" , "" , err )
273
- } else if msg .EventType != "describe" {
274
- return nil , errors .Errorf (tr ("communication out of sync, expected 'describe', received '%s'" ), msg .EventType )
275
- } else if msg .Message != "OK" || msg .Error {
276
- return nil , errors .Errorf (tr ("command failed: %s" ), msg .Message )
277
- } else {
278
- mon .supportedProtocol = msg .PortDescription .Protocol
279
- return msg .PortDescription , nil
256
+ msg , err := mon .waitMessage (time .Second * 10 , "describe" )
257
+ if err != nil {
258
+ return nil , err
280
259
}
260
+ mon .supportedProtocol = msg .PortDescription .Protocol
261
+ return msg .PortDescription , nil
281
262
}
282
263
283
264
// Configure sets a port configuration parameter.
284
265
func (mon * PluggableMonitor ) Configure (param , value string ) error {
285
266
if err := mon .sendCommand (fmt .Sprintf ("CONFIGURE %s %s\n " , param , value )); err != nil {
286
267
return err
287
268
}
288
- if msg , err := mon .waitMessage (time .Second * 10 ); err != nil {
289
- return fmt .Errorf ("calling %s: %w" , "" , err )
290
- } else if msg .EventType != "configure" {
291
- return errors .Errorf (tr ("communication out of sync, expected 'configure', received '%s'" ), msg .EventType )
292
- } else if msg .Message != "OK" || msg .Error {
293
- return errors .Errorf (tr ("configure failed: %s" ), msg .Message )
294
- } else {
295
- return nil
296
- }
269
+ _ , err := mon .waitMessage (time .Second * 10 , "configure" )
270
+ return err
297
271
}
298
272
299
273
// Open connects to the given Port. A communication channel is opened
300
274
func (mon * PluggableMonitor ) Open (port * rpc.Port ) (io.ReadWriter , error ) {
301
- mon .statusMutex .Lock ()
302
- defer mon .statusMutex .Unlock ()
303
-
304
- if mon .state == Opened {
305
- return nil , fmt .Errorf ("a port is already opened" )
306
- }
307
- if mon .state != Idle {
308
- return nil , fmt .Errorf ("the monitor is not started" )
309
- }
310
275
if port .Protocol != mon .supportedProtocol {
311
276
return nil , fmt .Errorf ("invalid monitor protocol '%s': only '%s' is accepted" , port .Protocol , mon .supportedProtocol )
312
277
}
@@ -321,58 +286,36 @@ func (mon *PluggableMonitor) Open(port *rpc.Port) (io.ReadWriter, error) {
321
286
if err := mon .sendCommand (fmt .Sprintf ("OPEN 127.0.0.1:%d %s\n " , tcpListenerPort , port .Address )); err != nil {
322
287
return nil , err
323
288
}
324
- if msg , err := mon .waitMessage (time .Second * 10 ); err != nil {
325
- return nil , fmt .Errorf ("calling %s: %w" , "" , err )
326
- } else if msg .EventType != "open" {
327
- return nil , errors .Errorf (tr ("communication out of sync, expected 'open', received '%s'" ), msg .EventType )
328
- } else if msg .Message != "OK" || msg .Error {
329
- return nil , errors .Errorf (tr ("open failed: %s" ), msg .Message )
289
+ if _ , err := mon .waitMessage (time .Second * 10 , "open" ); err != nil {
290
+ return nil , err
330
291
}
331
292
332
293
conn , err := tcpListener .Accept ()
333
294
if err != nil {
334
295
return nil , err // TODO
335
296
}
336
-
337
- mon .state = Opened
338
297
return conn , nil
339
298
}
340
299
341
300
// Close the communication port with the board.
342
301
func (mon * PluggableMonitor ) Close () error {
343
- mon .statusMutex .Lock ()
344
- defer mon .statusMutex .Unlock ()
345
-
346
- if mon .state != Opened {
347
- return fmt .Errorf ("monitor port already closed" )
348
- }
349
302
if err := mon .sendCommand ("CLOSE\n " ); err != nil {
350
303
return err
351
304
}
352
- if msg , err := mon .waitMessage (time .Second * 10 ); err != nil {
353
- return fmt .Errorf ("calling %s: %w" , "" , err )
354
- } else if msg .EventType != "close" {
355
- return errors .Errorf (tr ("communication out of sync, expected 'close', received '%s'" ), msg .EventType )
356
- } else if msg .Message != "OK" || msg .Error {
357
- return errors .Errorf (tr ("command failed: %s" ), msg .Message )
358
- } else {
359
- mon .state = Idle
360
- return nil
361
- }
305
+ _ , err := mon .waitMessage (time .Second * 10 , "close" )
306
+ return err
362
307
}
363
308
364
309
// Quit terminates the monitor. No more commands can be accepted by the monitor.
365
310
func (mon * PluggableMonitor ) Quit () error {
366
311
if err := mon .sendCommand ("QUIT\n " ); err != nil {
367
312
return err
368
313
}
369
- if msg , err := mon .waitMessage (time .Second * 10 ); err != nil {
370
- return fmt .Errorf (tr ("calling %[1]s: %[2]w" ), "QUIT" , err )
371
- } else if msg .EventType != "quit" {
372
- return errors .Errorf (tr ("communication out of sync, expected 'quit', received '%s'" ), msg .EventType )
373
- } else if msg .Message != "OK" || msg .Error {
374
- return errors .Errorf (tr ("command failed: %s" ), msg .Message )
314
+ if _ , err := mon .waitMessage (time .Second * 10 , "quit" ); err != nil {
315
+ return err
316
+ }
317
+ if err := mon .killProcess (); err != nil {
318
+ mon .log .WithError (err ).Info ("error killing monitor process" )
375
319
}
376
- mon .killProcess ()
377
320
return nil
378
321
}
0 commit comments