diff --git a/commands/service_monitor.go b/commands/service_monitor.go index 7c47e201ada..8c3402681b7 100644 --- a/commands/service_monitor.go +++ b/commands/service_monitor.go @@ -125,8 +125,8 @@ func (s *arduinoCoreServerImpl) Monitor(stream rpc.ArduinoCoreService_MonitorSer if err != nil { return err } - defer release() monitor, boardSettings, err := findMonitorAndSettingsForProtocolAndBoard(pme, openReq.GetPort().GetProtocol(), openReq.GetFqbn()) + release() if err != nil { return err } diff --git a/internal/cli/daemon/daemon.go b/internal/cli/daemon/daemon.go index 3139a66bdde..839738b8999 100644 --- a/internal/cli/daemon/daemon.go +++ b/internal/cli/daemon/daemon.go @@ -35,7 +35,6 @@ import ( ) var ( - tr = i18n.Tr daemonize bool debug bool debugFile string diff --git a/internal/integrationtest/daemon/daemon_concurrency_test.go b/internal/integrationtest/daemon/daemon_concurrency_test.go index 733fe54504a..c3541efbf4d 100644 --- a/internal/integrationtest/daemon/daemon_concurrency_test.go +++ b/internal/integrationtest/daemon/daemon_concurrency_test.go @@ -20,6 +20,7 @@ import ( "errors" "fmt" "io" + "sync" "testing" "time" @@ -76,3 +77,56 @@ func TestArduinoCliDaemonCompileWithLotOfOutput(t *testing.T) { testCompile() testCompile() } + +func TestInitAndMonitorConcurrency(t *testing.T) { + // See: https://github.com/arduino/arduino-cli/issues/2719 + + env, cli := integrationtest.CreateEnvForDaemon(t) + defer env.CleanUp() + + _, _, err := cli.Run("core", "install", "arduino:avr") + require.NoError(t, err) + + grpcInst := cli.Create() + require.NoError(t, grpcInst.Init("", "", func(ir *commands.InitResponse) { + fmt.Printf("INIT> %v\n", ir.GetMessage()) + })) + + cli.InstallMockedSerialMonitor(t) + + // Open the serial monitor for 5 seconds + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + mon, err := grpcInst.Monitor(ctx, &commands.Port{ + Address: "/dev/test", + Protocol: "serial", + }) + require.NoError(t, err) + var monitorCompleted sync.WaitGroup + monitorCompleted.Add(1) + go func() { + for { + msg, err := mon.Recv() + if err != nil { + break + } + fmt.Println("MON> ", msg) + } + fmt.Println("MON CLOSED") + monitorCompleted.Done() + }() + + // Check that Init completes without blocking when the monitor is open + start := time.Now() + require.NoError(t, grpcInst.Init("", "", func(ir *commands.InitResponse) { + fmt.Printf("INIT> %v\n", ir.GetMessage()) + })) + require.LessOrEqual(t, time.Since(start), 4*time.Second) + cancel() + monitorCompleted.Wait() + + // Allow some time for the mocked-monitor process to terminate (otherwise the + // test will fail on Windows when the cleanup function tries to remove the + // executable). + time.Sleep(2 * time.Second) +} pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy