Skip to content

Commit c63092f

Browse files
committed
Inlined function
1 parent bb5f8cd commit c63092f

File tree

2 files changed

+71
-112
lines changed

2 files changed

+71
-112
lines changed

commands/service_debug.go

+71-18
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,30 @@ import (
2121

2222
"github.com/arduino/arduino-cli/internal/i18n"
2323
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"
2433
)
2534

2635
// Debug returns a stream response that can be used to fetch data from the
2736
// target. The first message passed through the `Debug` request must
2837
// contain DebugRequest configuration params, not data.
2938
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+
3048
// Grab the first message
3149
msg, err := stream.Recv()
3250
if err != nil {
@@ -42,24 +60,59 @@ func (s *arduinoCoreServerImpl) Debug(stream rpc.ArduinoCoreService_DebugServer)
4260
// Launch debug recipe attaching stdin and out to grpc streaming
4361
signalChan := make(chan os.Signal)
4462
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
4971
})
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()})
63116
}
64-
return stream.Send(resp)
117+
return sendResult(&rpc.DebugResponse_Result{})
65118
}

commands/service_debug_run.go

-94
Original file line numberDiff line numberDiff line change
@@ -16,111 +16,17 @@
1616
package commands
1717

1818
import (
19-
"context"
2019
"fmt"
21-
"io"
22-
"os"
2320
"path/filepath"
2421
"runtime"
25-
"time"
2622

2723
"github.com/arduino/arduino-cli/commands/cmderrors"
28-
"github.com/arduino/arduino-cli/commands/internal/instances"
2924
"github.com/arduino/arduino-cli/internal/arduino/cores/packagemanager"
3025
"github.com/arduino/arduino-cli/internal/i18n"
3126
rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
3227
"github.com/arduino/go-paths-helper"
33-
"github.com/sirupsen/logrus"
3428
)
3529

36-
// Debug command launches a debug tool for a sketch.
37-
// It also implements streams routing:
38-
// gRPC In -> tool stdIn
39-
// grpc Out <- tool stdOut
40-
// grpc Out <- tool stdErr
41-
// It also implements tool process lifecycle management
42-
func Debug(ctx context.Context, req *rpc.GetDebugConfigRequest, inStream io.Reader, out io.Writer, interrupt <-chan os.Signal) (*rpc.DebugResponse, error) {
43-
44-
// Get debugging command line to run debugger
45-
pme, release, err := instances.GetPackageManagerExplorer(req.GetInstance())
46-
if err != nil {
47-
return nil, err
48-
}
49-
defer release()
50-
51-
commandLine, err := getCommandLine(req, pme)
52-
if err != nil {
53-
return nil, err
54-
}
55-
56-
for i, arg := range commandLine {
57-
fmt.Printf("%2d: %s\n", i, arg)
58-
}
59-
60-
// Run Tool
61-
entry := logrus.NewEntry(logrus.StandardLogger())
62-
for i, param := range commandLine {
63-
entry = entry.WithField(fmt.Sprintf("param%d", i), param)
64-
}
65-
entry.Debug("Executing debugger")
66-
67-
cmd, err := paths.NewProcess(pme.GetEnvVarsForSpawnedProcess(), commandLine...)
68-
if err != nil {
69-
return nil, &cmderrors.FailedDebugError{Message: i18n.Tr("Cannot execute debug tool"), Cause: err}
70-
}
71-
72-
// Get stdIn pipe from tool
73-
in, err := cmd.StdinPipe()
74-
if err != nil {
75-
return &rpc.DebugResponse{Message: &rpc.DebugResponse_Result_{
76-
Result: &rpc.DebugResponse_Result{Error: err.Error()},
77-
}}, nil
78-
}
79-
defer in.Close()
80-
81-
// Merge tool StdOut and StdErr to stream them in the io.Writer passed stream
82-
cmd.RedirectStdoutTo(out)
83-
cmd.RedirectStderrTo(out)
84-
85-
// Start the debug command
86-
if err := cmd.Start(); err != nil {
87-
return &rpc.DebugResponse{Message: &rpc.DebugResponse_Result_{
88-
Result: &rpc.DebugResponse_Result{Error: err.Error()},
89-
}}, nil
90-
}
91-
92-
if interrupt != nil {
93-
go func() {
94-
for {
95-
sig, ok := <-interrupt
96-
if !ok {
97-
break
98-
}
99-
cmd.Signal(sig)
100-
}
101-
}()
102-
}
103-
104-
go func() {
105-
// Copy data from passed inStream into command stdIn
106-
io.Copy(in, inStream)
107-
// In any case, try process termination after a second to avoid leaving
108-
// zombie process.
109-
time.Sleep(time.Second)
110-
cmd.Kill()
111-
}()
112-
113-
// Wait for process to finish
114-
if err := cmd.Wait(); err != nil {
115-
return &rpc.DebugResponse{Message: &rpc.DebugResponse_Result_{
116-
Result: &rpc.DebugResponse_Result{Error: err.Error()},
117-
}}, nil
118-
}
119-
return &rpc.DebugResponse{Message: &rpc.DebugResponse_Result_{
120-
Result: &rpc.DebugResponse_Result{},
121-
}}, nil
122-
}
123-
12430
// getCommandLine compose a debug command represented by a core recipe
12531
func getCommandLine(req *rpc.GetDebugConfigRequest, pme *packagemanager.Explorer) ([]string, error) {
12632
debugInfo, err := getDebugProperties(req, pme, false)

0 commit comments

Comments
 (0)