@@ -20,6 +20,7 @@ import (
2020 "errors"
2121 "fmt"
2222 "io"
23+ "sync/atomic"
2324
2425 "github.com/arduino/arduino-cli/arduino"
2526 "github.com/arduino/arduino-cli/commands"
@@ -451,6 +452,10 @@ func (s *ArduinoCoreServerImpl) Monitor(stream rpc.ArduinoCoreService_MonitorSer
451452 _ = syncSend .Send (& rpc.MonitorResponse {Success : true })
452453
453454 cancelCtx , cancel := context .WithCancel (stream .Context ())
455+ gracefulCloseInitiated := & atomic.Bool {}
456+ gracefuleCloseCtx , gracefulCloseCancel := context .WithCancel (context .Background ())
457+
458+ // gRPC stream receiver (gRPC data -> monitor, config, close)
454459 go func () {
455460 defer cancel ()
456461 for {
@@ -470,9 +475,11 @@ func (s *ArduinoCoreServerImpl) Monitor(stream rpc.ArduinoCoreService_MonitorSer
470475 }
471476 }
472477 if closeMsg := msg .GetClose (); closeMsg {
478+ gracefulCloseInitiated .Store (true )
473479 if err := portProxy .Close (); err != nil {
474480 logrus .WithError (err ).Debug ("Error closing monitor port" )
475481 }
482+ gracefulCloseCancel ()
476483 }
477484 tx := msg .GetTxData ()
478485 for len (tx ) > 0 {
@@ -489,8 +496,9 @@ func (s *ArduinoCoreServerImpl) Monitor(stream rpc.ArduinoCoreService_MonitorSer
489496 }
490497 }()
491498
499+ // gRPC stream sender (monitor -> gRPC)
492500 go func () {
493- defer cancel ()
501+ defer cancel () // unlock the receiver
494502 buff := make ([]byte , 4096 )
495503 for {
496504 n , err := portProxy .Read (buff )
@@ -508,6 +516,11 @@ func (s *ArduinoCoreServerImpl) Monitor(stream rpc.ArduinoCoreService_MonitorSer
508516 }()
509517
510518 <- cancelCtx .Done ()
511- portProxy .Close ()
519+ if gracefulCloseInitiated .Load () {
520+ // Port closing has been initiated in the receiver
521+ <- gracefuleCloseCtx .Done ()
522+ } else {
523+ portProxy .Close ()
524+ }
512525 return nil
513526}
0 commit comments