@@ -34,6 +34,7 @@ import (
34
34
"regexp"
35
35
"strconv"
36
36
"strings"
37
+ "sync"
37
38
38
39
"github.com/arduino/go-properties-orderedmap"
39
40
)
@@ -86,6 +87,7 @@ type ErrorCallback func(err string)
86
87
type Server struct {
87
88
impl Discovery
88
89
outputChan chan * message
90
+ outputWaiter sync.WaitGroup
89
91
userAgent string
90
92
reqProtocolVersion int
91
93
initialized bool
@@ -111,8 +113,7 @@ func NewServer(impl Discovery) *Server {
111
113
// the input stream is closed. In case of IO error the error is
112
114
// returned.
113
115
func (d * Server ) Run (in io.Reader , out io.Writer ) error {
114
- go d .outputProcessor (out )
115
- defer close (d .outputChan )
116
+ d .startOutputProcessor (out )
116
117
reader := bufio .NewReader (in )
117
118
for {
118
119
fullCmd , err := reader .ReadString ('\n' )
@@ -141,8 +142,7 @@ func (d *Server) Run(in io.Reader, out io.Writer) error {
141
142
case "STOP" :
142
143
d .stop ()
143
144
case "QUIT" :
144
- d .impl .Quit ()
145
- d .outputChan <- messageOk ("quit" )
145
+ d .quit ()
146
146
return nil
147
147
default :
148
148
d .outputChan <- messageError ("command_error" , fmt .Sprintf ("Command %s not supported" , cmd ))
@@ -276,12 +276,26 @@ func (d *Server) syncEvent(event string, port *Port) {
276
276
}
277
277
}
278
278
279
+ func (d * Server ) quit () {
280
+ d .impl .Quit ()
281
+ d .outputChan <- messageOk ("quit" )
282
+ close (d .outputChan )
283
+ // If we don't wait for all messages
284
+ // to be consumed by the output processor
285
+ // we risk not printing the "quit" message.
286
+ // This may cause issues to consumers of
287
+ // the discovery since they expect a message
288
+ // that is never sent.
289
+ d .outputWaiter .Wait ()
290
+ }
291
+
279
292
func (d * Server ) errorEvent (msg string ) {
280
293
d .outputChan <- messageError ("start_sync" , msg )
281
294
}
282
295
283
- func (d * Server ) outputProcessor (outWriter io.Writer ) {
296
+ func (d * Server ) startOutputProcessor (outWriter io.Writer ) {
284
297
// Start go routine to serialize messages printing
298
+ d .outputWaiter .Add (1 )
285
299
go func () {
286
300
for msg := range d .outputChan {
287
301
data , err := json .MarshalIndent (msg , "" , " " )
@@ -292,5 +306,8 @@ func (d *Server) outputProcessor(outWriter io.Writer) {
292
306
}
293
307
fmt .Fprintln (outWriter , string (data ))
294
308
}
309
+ // We finished consuming all messages, now
310
+ // we can exit for real
311
+ d .outputWaiter .Done ()
295
312
}()
296
313
}
0 commit comments