Use exec.CommandContext insead of manually killing process
diff --git a/backend/server.go b/backend/server.go
index 2208cc0..e2487cd 100644
--- a/backend/server.go
+++ b/backend/server.go
@@ -10,7 +10,6 @@
 	"encoding/json"
 	"fmt"
 	"io/ioutil"
-	"log"
 	"os"
 	"os/exec"
 	"path/filepath"
@@ -497,32 +496,19 @@
 // TODO: Consider returning a string and error here, and letting the top-level
 // handlers produce responses instead.
 func (p program) run(ctx context.Context, arg ...string) Response {
-	// TODO: use exec.CommandContext!
-	cmd := exec.Command(p.path, arg...)
+	cmd := exec.CommandContext(ctx, p.path, arg...)
 	var out bytes.Buffer
 	cmd.Stdout = &out
 	cmd.Stderr = &out
-	if err := cmd.Start(); err != nil {
-		msg := fmt.Sprintf("Failed to execute %s", filepath.Base(p.path))
-		return Response{Ok: false, Content: msg}
-	}
-	result := make(chan error, 1)
-	go func() {
-		result <- cmd.Wait()
-	}()
-	select {
-	case <-ctx.Done():
-		if err := cmd.Process.Kill(); err != nil {
-			log.Printf("Failed to kill process %s with pid %d", p.path, cmd.Process.Pid)
-		}
-		// The response doesn't matter, since http.TimeoutHandler will respond
-		// with 503 Service Unavailable after cancelling ctx.
-		return Response{Ok: false}
-	case err := <-result:
+	switch err := cmd.Run().(type) {
+	case nil, *exec.ExitError:
 		return Response{
 			Ok:      err == nil,
 			Content: out.String(),
 		}
+	default:
+		msg := fmt.Sprintf("Failed to execute %s", filepath.Base(p.path))
+		return Response{Ok: false, Content: msg}
 	}
 }