@@ -34,6 +34,7 @@ import (
3434 "regexp"
3535 "strconv"
3636 "strings"
37+ "sync"
3738
3839 "github.com/arduino/go-properties-orderedmap"
3940)
@@ -86,6 +87,7 @@ type ErrorCallback func(err string)
8687type Server struct {
8788 impl Discovery
8889 outputChan chan * message
90+ outputWaiter sync.WaitGroup
8991 userAgent string
9092 reqProtocolVersion int
9193 initialized bool
@@ -111,8 +113,7 @@ func NewServer(impl Discovery) *Server {
111113// the input stream is closed. In case of IO error the error is
112114// returned.
113115func (d * Server ) Run (in io.Reader , out io.Writer ) error {
114- go d .outputProcessor (out )
115- defer close (d .outputChan )
116+ d .startOutputProcessor (out )
116117 reader := bufio .NewReader (in )
117118 for {
118119 fullCmd , err := reader .ReadString ('\n' )
@@ -141,8 +142,7 @@ func (d *Server) Run(in io.Reader, out io.Writer) error {
141142 case "STOP" :
142143 d .stop ()
143144 case "QUIT" :
144- d .impl .Quit ()
145- d .outputChan <- messageOk ("quit" )
145+ d .quit ()
146146 return nil
147147 default :
148148 d .outputChan <- messageError ("command_error" , fmt .Sprintf ("Command %s not supported" , cmd ))
@@ -276,12 +276,26 @@ func (d *Server) syncEvent(event string, port *Port) {
276276 }
277277}
278278
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+
279292func (d * Server ) errorEvent (msg string ) {
280293 d .outputChan <- messageError ("start_sync" , msg )
281294}
282295
283- func (d * Server ) outputProcessor (outWriter io.Writer ) {
296+ func (d * Server ) startOutputProcessor (outWriter io.Writer ) {
284297 // Start go routine to serialize messages printing
298+ d .outputWaiter .Add (1 )
285299 go func () {
286300 for msg := range d .outputChan {
287301 data , err := json .MarshalIndent (msg , "" , " " )
@@ -292,5 +306,8 @@ func (d *Server) outputProcessor(outWriter io.Writer) {
292306 }
293307 fmt .Fprintln (outWriter , string (data ))
294308 }
309+ // We finished consuming all messages, now
310+ // we can exit for real
311+ d .outputWaiter .Done ()
295312 }()
296313}
0 commit comments