@@ -21,12 +21,30 @@ import (
21
21
22
22
"github.com/arduino/arduino-cli/internal/i18n"
23
23
rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
24
+
25
+ "fmt"
26
+ "io"
27
+ "time"
28
+
29
+ "github.com/arduino/arduino-cli/commands/cmderrors"
30
+ "github.com/arduino/arduino-cli/commands/internal/instances"
31
+ paths "github.com/arduino/go-paths-helper"
32
+ "github.com/sirupsen/logrus"
24
33
)
25
34
26
35
// Debug returns a stream response that can be used to fetch data from the
27
36
// target. The first message passed through the `Debug` request must
28
37
// contain DebugRequest configuration params, not data.
29
38
func (s * arduinoCoreServerImpl ) Debug (stream rpc.ArduinoCoreService_DebugServer ) error {
39
+ // Utility functions
40
+ syncSend := NewSynchronizedSend (stream .Send )
41
+ sendResult := func (res * rpc.DebugResponse_Result ) error {
42
+ return syncSend .Send (& rpc.DebugResponse {Message : & rpc.DebugResponse_Result_ {Result : res }})
43
+ }
44
+ sendData := func (data []byte ) {
45
+ _ = syncSend .Send (& rpc.DebugResponse {Message : & rpc.DebugResponse_Data {Data : data }})
46
+ }
47
+
30
48
// Grab the first message
31
49
msg , err := stream .Recv ()
32
50
if err != nil {
@@ -42,24 +60,59 @@ func (s *arduinoCoreServerImpl) Debug(stream rpc.ArduinoCoreService_DebugServer)
42
60
// Launch debug recipe attaching stdin and out to grpc streaming
43
61
signalChan := make (chan os.Signal )
44
62
defer close (signalChan )
45
- outStream := feedStreamTo (func (data []byte ) {
46
- stream .Send (& rpc.DebugResponse {Message : & rpc.DebugResponse_Data {
47
- Data : data ,
48
- }})
63
+ outStream := feedStreamTo (sendData )
64
+ defer outStream .Close ()
65
+ inStream := consumeStreamFrom (func () ([]byte , error ) {
66
+ command , err := stream .Recv ()
67
+ if command .GetSendInterrupt () {
68
+ signalChan <- os .Interrupt
69
+ }
70
+ return command .GetData (), err
49
71
})
50
- resp , debugErr := Debug (stream .Context (), req ,
51
- consumeStreamFrom (func () ([]byte , error ) {
52
- command , err := stream .Recv ()
53
- if command .GetSendInterrupt () {
54
- signalChan <- os .Interrupt
55
- }
56
- return command .GetData (), err
57
- }),
58
- outStream ,
59
- signalChan )
60
- outStream .Close ()
61
- if debugErr != nil {
62
- return debugErr
72
+
73
+ pme , release , err := instances .GetPackageManagerExplorer (req .GetInstance ())
74
+ if err != nil {
75
+ return err
76
+ }
77
+ defer release ()
78
+
79
+ // Exec debugger
80
+ commandLine , err := getCommandLine (req , pme )
81
+ if err != nil {
82
+ return err
83
+ }
84
+ entry := logrus .NewEntry (logrus .StandardLogger ())
85
+ for i , param := range commandLine {
86
+ entry = entry .WithField (fmt .Sprintf ("param%d" , i ), param )
87
+ }
88
+ entry .Debug ("Executing debugger" )
89
+ cmd , err := paths .NewProcess (pme .GetEnvVarsForSpawnedProcess (), commandLine ... )
90
+ if err != nil {
91
+ return & cmderrors.FailedDebugError {Message : i18n .Tr ("Cannot execute debug tool" ), Cause : err }
92
+ }
93
+ in , err := cmd .StdinPipe ()
94
+ if err != nil {
95
+ return sendResult (& rpc.DebugResponse_Result {Error : err .Error ()})
96
+ }
97
+ defer in .Close ()
98
+ cmd .RedirectStdoutTo (io .Writer (outStream ))
99
+ cmd .RedirectStderrTo (io .Writer (outStream ))
100
+ if err := cmd .Start (); err != nil {
101
+ return sendResult (& rpc.DebugResponse_Result {Error : err .Error ()})
102
+ }
103
+
104
+ go func () {
105
+ for sig := range signalChan {
106
+ cmd .Signal (sig )
107
+ }
108
+ }()
109
+ go func () {
110
+ io .Copy (in , inStream )
111
+ time .Sleep (time .Second )
112
+ cmd .Kill ()
113
+ }()
114
+ if err := cmd .Wait (); err != nil {
115
+ return sendResult (& rpc.DebugResponse_Result {Error : err .Error ()})
63
116
}
64
- return stream . Send ( resp )
117
+ return sendResult ( & rpc. DebugResponse_Result {} )
65
118
}
0 commit comments