@@ -35,9 +35,62 @@ import (
35
35
dbg "github.com/arduino/arduino-cli/rpc/debug"
36
36
)
37
37
38
- // Debug FIXMEDOC
38
+ // Debug command launches a debug tool for a sketch.
39
+ // It also implements streams routing:
40
+ // gRPC In -> tool stdIn
41
+ // grpc Out <- tool stdOut
42
+ // grpc Out <- tool stdErr
43
+ // It also implements tool process lifecycle management
39
44
func Debug (ctx context.Context , req * dbg.DebugConfigReq , inStream io.Reader , out io.Writer ) (* dbg.DebugResp , error ) {
40
45
46
+ // get tool commandLine from core recipe
47
+ commandLine , err := getCommandLine (req )
48
+ if err != nil {
49
+ return nil , fmt .Errorf ("cannot get command line for tool: %s" , err )
50
+ }
51
+
52
+ // Run Tool
53
+ cmd , err := executils .Command (commandLine )
54
+ if err != nil {
55
+ return nil , fmt .Errorf ("cannot execute debug tool: %s" , err )
56
+ }
57
+
58
+ // Get stdIn pipe from tool
59
+ in , err := cmd .StdinPipe ()
60
+ if err != nil {
61
+ fmt .Printf ("%v\n " , err )
62
+ return & dbg.DebugResp {Error : err .Error ()}, nil
63
+ }
64
+ defer in .Close ()
65
+
66
+ // Merge tool StdOut and StdErr to stream them in the io.Writer passed stream
67
+ cmd .Stdout = out
68
+ cmd .Stderr = out
69
+
70
+ // Start the debug command
71
+ if err := cmd .Start (); err != nil {
72
+ fmt .Printf ("%v\n " , err )
73
+ return & dbg.DebugResp {Error : err .Error ()}, nil
74
+ }
75
+
76
+ go func () {
77
+ // copy data from passed inStream into command stdIn
78
+ io .Copy (in , inStream )
79
+ // In any case, try process termination after a second to avoid leaving
80
+ // zombie process.
81
+ time .Sleep (time .Second )
82
+ cmd .Process .Kill ()
83
+ }()
84
+
85
+ // Wait for process to finish
86
+ if err := cmd .Wait (); err != nil {
87
+ return & dbg.DebugResp {Error : err .Error ()}, nil
88
+ }
89
+ return & dbg.DebugResp {}, nil
90
+ }
91
+
92
+ // getCommandLine compose a debug command represented by a core recipe
93
+ func getCommandLine (req * dbg.DebugConfigReq ) ([]string , error ) {
41
94
// TODO: make a generic function to extract sketch from request
42
95
// and remove duplication in commands/compile.go
43
96
if req .GetSketchPath () == "" {
@@ -52,7 +105,7 @@ func Debug(ctx context.Context, req *dbg.DebugConfigReq, inStream io.Reader, out
52
105
// FIXME: make a specification on how a port is specified via command line
53
106
port := req .GetPort ()
54
107
if port == "" {
55
- return nil , fmt .Errorf ("no upload port provided" )
108
+ return nil , fmt .Errorf ("no debug port provided" )
56
109
}
57
110
58
111
fqbnIn := req .GetFqbn ()
@@ -98,7 +151,7 @@ func Debug(ctx context.Context, req *dbg.DebugConfigReq, inStream io.Reader, out
98
151
}
99
152
}
100
153
101
- // Build configuration for upload
154
+ // Build configuration for debug
102
155
toolProperties := properties .NewMap ()
103
156
if referencedPlatformRelease != nil {
104
157
toolProperties .Merge (referencedPlatformRelease .Properties )
@@ -109,26 +162,13 @@ func Debug(ctx context.Context, req *dbg.DebugConfigReq, inStream io.Reader, out
109
162
110
163
requestedToolProperties := toolProperties .SubTree ("tools." + toolName )
111
164
toolProperties .Merge (requestedToolProperties )
112
-
113
165
if requiredTools , err := pm .FindToolsRequiredForBoard (board ); err == nil {
114
166
for _ , requiredTool := range requiredTools {
115
- logrus .WithField ("tool" , requiredTool ).Info ("Tool required for upload " )
167
+ logrus .WithField ("tool" , requiredTool ).Info ("Tool required for debug " )
116
168
toolProperties .Merge (requiredTool .RuntimeProperties ())
117
169
}
118
170
}
119
171
120
- // Set properties for verbose upload
121
- verbose := req .GetVerbose ()
122
- if verbose {
123
- if v , ok := toolProperties .GetOk ("debug.params.verbose" ); ok {
124
- toolProperties .Set ("debug.verbose" , v )
125
- }
126
- } else {
127
- if v , ok := toolProperties .GetOk ("debug.params.quiet" ); ok {
128
- toolProperties .Set ("debug.verbose" , v )
129
- }
130
- }
131
-
132
172
// Set path to compiled binary
133
173
// Make the filename without the FQBN configs part
134
174
fqbn .Configs = properties .NewMap ()
@@ -179,44 +219,5 @@ func Debug(ctx context.Context, req *dbg.DebugConfigReq, inStream io.Reader, out
179
219
if err != nil {
180
220
return nil , fmt .Errorf ("invalid recipe '%s': %s" , recipe , err )
181
221
}
182
-
183
- // for _, arg := range cmdArgs {
184
- // fmt.Println(">>", arg)
185
- // }
186
- // time.Sleep(time.Hour)
187
-
188
- // Run Tool
189
- cmd , err := executils .Command (cmdArgs )
190
- if err != nil {
191
- return nil , fmt .Errorf ("cannot execute upload tool: %s" , err )
192
- }
193
-
194
- in , err := cmd .StdinPipe ()
195
- if err != nil {
196
- fmt .Printf ("%v\n " , err )
197
- return & dbg.DebugResp {Error : err .Error ()}, nil
198
- }
199
- defer in .Close ()
200
-
201
- cmd .Stdout = out
202
- cmd .Stderr = out
203
-
204
- if err := cmd .Start (); err != nil {
205
- fmt .Printf ("%v\n " , err )
206
- return & dbg.DebugResp {Error : err .Error ()}, nil
207
- }
208
-
209
- // now we can read the other commands and re-route to the Debug Client...
210
- go func () {
211
- io .Copy (in , inStream )
212
- // In any case, try process termination after a second to avoid leaving
213
- // zombie process.
214
- time .Sleep (time .Second )
215
- cmd .Process .Kill ()
216
- }()
217
-
218
- if err := cmd .Wait (); err != nil {
219
- return & dbg.DebugResp {Error : err .Error ()}, nil
220
- }
221
- return & dbg.DebugResp {}, nil
222
+ return cmdArgs , nil
222
223
}
0 commit comments