|
8 | 8 | "io" |
9 | 9 | "os" |
10 | 10 | "os/exec" |
| 11 | + "time" |
11 | 12 | ) |
12 | 13 |
|
13 | 14 | // Stdio implements the Transport interface by executing a command |
@@ -73,17 +74,30 @@ func (t *Stdio) Execute(method string, params any) (map[string]any, error) { |
73 | 74 | return nil, err |
74 | 75 | } |
75 | 76 |
|
76 | | - waitErr := cmd.Wait() |
| 77 | + // Wait for the command to finish with a timeout to prevent zombie processes |
| 78 | + done := make(chan error, 1) |
| 79 | + go func() { |
| 80 | + done <- cmd.Wait() |
| 81 | + }() |
77 | 82 |
|
78 | | - if t.debug { |
79 | | - fmt.Fprintf(os.Stderr, "DEBUG: Command completed with err: %v\n", waitErr) |
80 | | - if stderrBuf.Len() > 0 { |
81 | | - fmt.Fprintf(os.Stderr, "DEBUG: stderr output:\n%s\n", stderrBuf.String()) |
| 83 | + select { |
| 84 | + case waitErr := <-done: |
| 85 | + if t.debug { |
| 86 | + fmt.Fprintf(os.Stderr, "DEBUG: Command completed with err: %v\n", waitErr) |
| 87 | + if stderrBuf.Len() > 0 { |
| 88 | + fmt.Fprintf(os.Stderr, "DEBUG: stderr output:\n%s\n", stderrBuf.String()) |
| 89 | + } |
82 | 90 | } |
83 | | - } |
84 | 91 |
|
85 | | - if waitErr != nil && stderrBuf.Len() > 0 { |
86 | | - return nil, fmt.Errorf("command error: %w, stderr: %s", waitErr, stderrBuf.String()) |
| 92 | + if waitErr != nil && stderrBuf.Len() > 0 { |
| 93 | + return nil, fmt.Errorf("command error: %w, stderr: %s", waitErr, stderrBuf.String()) |
| 94 | + } |
| 95 | + case <-time.After(1 * time.Second): |
| 96 | + if t.debug { |
| 97 | + fmt.Fprintf(os.Stderr, "DEBUG: Command timed out after 1 seconds\n") |
| 98 | + } |
| 99 | + // Kill the process if it times out |
| 100 | + _ = cmd.Process.Kill() |
87 | 101 | } |
88 | 102 |
|
89 | 103 | return response.Result, nil |
|
0 commit comments