ensure git processes are cleaned up with request after timeout
2 files changed, 14 insertions(+), 6 deletions(-)
changed files
M git/service/service.go → git/service/service.go
@@ -2,6 +2,7 @@ package service import ( "bytes" + "context" "errors" "fmt" "io"@@ -10,8 +11,11 @@ "net/http" "os/exec" "strings" "syscall" + "time" ) +const timeout = 1 * time.Minute + // Mostly from charmbracelet/soft-serve and sosedoff/gitkit. type ServiceCommand struct {@@ -20,8 +24,10 @@ Stdin io.Reader Stdout http.ResponseWriter } -func (c *ServiceCommand) InfoRefs() error { - cmd := exec.Command("git", []string{ +func (c *ServiceCommand) InfoRefs(ctx context.Context) error { + ctx, cancel := context.WithTimeout(ctx, timeout) + defer cancel() + cmd := exec.CommandContext(ctx, "git", []string{ "upload-pack", "--stateless-rpc", "--advertise-refs",@@ -73,8 +79,10 @@ return nil } -func (c *ServiceCommand) UploadPack() (err error) { - cmd := exec.Command("git", []string{ +func (c *ServiceCommand) UploadPack(ctx context.Context) (err error) { + ctx, cancel := context.WithTimeout(ctx, timeout) + defer cancel() + cmd := exec.CommandContext(ctx, "git", []string{ "-c", "uploadpack.allowFilter=true", "upload-pack", "--stateless-rpc",
M routes/git.go → routes/git.go
@@ -29,7 +29,7 @@ Dir: repo, Stdout: w, } - if err := cmd.InfoRefs(); err != nil { + if err := cmd.InfoRefs(r.Context()); err != nil { http.Error(w, err.Error(), 500) log.Printf("git: failed to execute git-upload-pack (info/refs) %s", err)@@ -78,7 +78,7 @@ }() } cmd.Stdin = reader - if err := cmd.UploadPack(); err != nil { + if err := cmd.UploadPack(r.Context()); err != nil { http.Error(w, err.Error(), 500) log.Printf("git: failed to execute git-upload-pack %s", err)