MCPcopy Index your code
hub / github.com/docker/docker-agent / runNativeCommand

Method runNativeCommand

pkg/tools/builtin/shell/shell.go:278–328  ·  view source on GitHub ↗
(timeoutCtx, ctx context.Context, command, cwd string, timeout time.Duration)

Source from the content-addressed store, hash-verified

276const waitDelayAfterShellExit = 500 * time.Millisecond
277
278func (h *shellHandler) runNativeCommand(timeoutCtx, ctx context.Context, command, cwd string, timeout time.Duration) *tools.ToolCallResult {
279 // Cancellation is handled manually below (timeoutCtx + Process.Kill +
280 // process group + WaitDelay), so we use exec.Command rather than
281 // exec.CommandContext to keep that flow in one place.
282 command, cmdEnv := h.applyAskpass(ctx, command)
283 cmd := exec.Command(h.shell, append(h.shellArgsPrefix, command)...) //nolint:noctx // see comment above
284 cmd.Env = cmdEnv
285 cmd.Dir = cwd
286 cmd.SysProcAttr = platformSpecificSysProcAttr()
287 cmd.WaitDelay = waitDelayAfterShellExit
288
289 output := newCommandOutput(ctx)
290 cmd.Stdout = output
291 cmd.Stderr = output
292
293 if err := cmd.Start(); err != nil {
294 return tools.ResultError(fmt.Sprintf("Error starting command: %s", err))
295 }
296
297 pg, err := createProcessGroup(cmd.Process)
298 if err != nil {
299 // Successfully started the child but couldn't install it in its own
300 // process group: clean it up before bailing out.
301 reapSpawnedChild(cmd, pg)
302 return tools.ResultError(fmt.Sprintf("Error creating process group: %s", err))
303 }
304
305 done := make(chan error, 1)
306 go func() {
307 done <- cmd.Wait()
308 }()
309
310 var cmdErr error
311 select {
312 case <-timeoutCtx.Done():
313 _ = kill(cmd.Process, pg)
314 // Wait for cmd.Wait() to complete so that the internal pipe-copy
315 // goroutines finish writing to output before we read it.
316 // Use a grace period: if SIGTERM is ignored, escalate to SIGKILL.
317 select {
318 case <-done:
319 case <-time.After(3 * time.Second):
320 _ = cmd.Process.Kill()
321 <-done
322 }
323 case cmdErr = <-done:
324 }
325
326 formattedOutput := formatCommandOutput(timeoutCtx, ctx, cmdErr, output.String(), timeout)
327 return tools.ResultSuccess(formattedOutput)
328}
329
330func (h *shellHandler) RunShellBackground(ctx context.Context, params RunShellBackgroundArgs) (*tools.ToolCallResult, error) {
331 if strings.TrimSpace(params.Cmd) == "" {

Callers 1

RunShellMethod · 0.95

Calls 12

applyAskpassMethod · 0.95
ResultErrorFunction · 0.92
ResultSuccessFunction · 0.92
newCommandOutputFunction · 0.85
reapSpawnedChildFunction · 0.85
formatCommandOutputFunction · 0.85
createProcessGroupFunction · 0.70
killFunction · 0.70
StartMethod · 0.65
WaitMethod · 0.65
StringMethod · 0.45

Tested by

no test coverage detected