Subprocess Timeout Runner
Run a child process under a context deadline, capture stdout and stderr together, and report a clear timeout error.
Code
package main
import (
"bytes"
"context"
"errors"
"flag"
"fmt"
"os"
"os/exec"
"time"
)
func RunWithTimeout(ctx context.Context, timeout time.Duration, name string, args ...string) (string, error) {
runCtx, cancel := context.WithTimeout(ctx, timeout)
defer cancel()
command := exec.CommandContext(runCtx, name, args...)
var output bytes.Buffer
command.Stdout = &output
command.Stderr = &output
err := command.Run()
if errors.Is(runCtx.Err(), context.DeadlineExceeded) {
return output.String(), fmt.Errorf("%s timed out after %s", name, timeout)
}
if err != nil {
return output.String(), fmt.Errorf("%s failed: %w: %s", name, err, output.String())
}
return output.String(), nil
}
func main() {
child := flag.Bool("child", false, "run as the slow child process")
flag.Parse()
if *child {
time.Sleep(2 * time.Second)
fmt.Println("child finished")
return
}
output, err := RunWithTimeout(context.Background(), 300*time.Millisecond, os.Args[0], "-child")
fmt.Printf("output=%q err=%v\n", output, err)
}Report a problem with this exampleOpens a pre-filled issue on GitHub.