@@ -20,6 +20,7 @@ import (
2020 "errors"
2121 "fmt"
2222 "io"
23+ "sync/atomic"
2324
2425 "github.com/arduino/arduino-cli/commands"
2526 "github.com/arduino/arduino-cli/commands/board"
@@ -490,6 +491,10 @@ func (s *ArduinoCoreServerImpl) Monitor(stream rpc.ArduinoCoreService_MonitorSer
490491 _ = syncSend .Send (& rpc.MonitorResponse {Success : true })
491492
492493 cancelCtx , cancel := context .WithCancel (stream .Context ())
494+ gracefulCloseInitiated := & atomic.Bool {}
495+ gracefuleCloseCtx , gracefulCloseCancel := context .WithCancel (context .Background ())
496+
497+ // gRPC stream receiver (gRPC data -> monitor, config, close)
493498 go func () {
494499 defer cancel ()
495500 for {
@@ -509,9 +514,11 @@ func (s *ArduinoCoreServerImpl) Monitor(stream rpc.ArduinoCoreService_MonitorSer
509514 }
510515 }
511516 if closeMsg := msg .GetClose (); closeMsg {
517+ gracefulCloseInitiated .Store (true )
512518 if err := portProxy .Close (); err != nil {
513519 logrus .WithError (err ).Debug ("Error closing monitor port" )
514520 }
521+ gracefulCloseCancel ()
515522 }
516523 tx := msg .GetTxData ()
517524 for len (tx ) > 0 {
@@ -528,8 +535,9 @@ func (s *ArduinoCoreServerImpl) Monitor(stream rpc.ArduinoCoreService_MonitorSer
528535 }
529536 }()
530537
538+ // gRPC stream sender (monitor -> gRPC)
531539 go func () {
532- defer cancel ()
540+ defer cancel () // unlock the receiver
533541 buff := make ([]byte , 4096 )
534542 for {
535543 n , err := portProxy .Read (buff )
@@ -547,6 +555,11 @@ func (s *ArduinoCoreServerImpl) Monitor(stream rpc.ArduinoCoreService_MonitorSer
547555 }()
548556
549557 <- cancelCtx .Done ()
550- portProxy .Close ()
558+ if gracefulCloseInitiated .Load () {
559+ // Port closing has been initiated in the receiver
560+ <- gracefuleCloseCtx .Done ()
561+ } else {
562+ portProxy .Close ()
563+ }
551564 return nil
552565}
0 commit comments