playground: bound compilation time too We already limited execution time. Change-Id: I4cdf0178e08632ad25e4a7c5d6d63a9a00131e31 Reviewed-on: https://go-review.googlesource.com/c/playground/+/194601 Reviewed-by: Ian Lance Taylor <iant@golang.org> Reviewed-by: Filippo Valsorda <filippo@golang.org>
diff --git a/README.md b/README.md index fe6ac19..5ee85f9 100644 --- a/README.md +++ b/README.md
@@ -13,7 +13,7 @@ ## Running ```bash -docker run --name=play --rm -d -p 8080:8080 playground +docker run --name=play --rm -p 8080:8080 golang/playground & # run some Go code cat /path/to/code.go | go run client.go | curl -s --upload-file - localhost:8080/compile ```
diff --git a/sandbox.go b/sandbox.go index f43eb07..7b6909f 100644 --- a/sandbox.go +++ b/sandbox.go
@@ -34,16 +34,23 @@ ) const ( - maxRunTime = 2 * time.Second + maxCompileTime = 5 * time.Second + maxRunTime = 2 * time.Second // progName is the implicit program name written to the temp // dir and used in compiler and vet errors. progName = "prog.go" ) +const goBuildTimeoutError = "timeout running go build" + // Responses that contain these strings will not be cached due to // their non-deterministic nature. -var nonCachingErrors = []string{"out of memory", "cannot allocate memory"} +var nonCachingErrors = []string{ + "out of memory", + "cannot allocate memory", + goBuildTimeoutError, +} type request struct { Body string @@ -363,7 +370,10 @@ exe := filepath.Join(tmpDir, "a.out") goCache := filepath.Join(tmpDir, "gocache") - cmd := exec.Command("go", "build", "-o", exe, buildPkgArg) + + ctx, cancel := context.WithTimeout(context.Background(), maxCompileTime) + defer cancel() + cmd := exec.CommandContext(ctx, "go", "build", "-o", exe, buildPkgArg) cmd.Dir = tmpDir var goPath string cmd.Env = []string{"GOOS=nacl", "GOARCH=amd64p32", "GOCACHE=" + goCache} @@ -381,7 +391,12 @@ cmd.Env = append(cmd.Env, "GO111MODULE=off") // in case it becomes on by default later } cmd.Env = append(cmd.Env, "GOPATH="+goPath) + t0 := time.Now() if out, err := cmd.CombinedOutput(); err != nil { + if ctx.Err() == context.DeadlineExceeded { + log.Printf("go build timed out after %v", time.Since(t0)) + return &response{Errors: goBuildTimeoutError}, nil + } if _, ok := err.(*exec.ExitError); ok { // Return compile errors to the user. @@ -396,7 +411,7 @@ } return nil, fmt.Errorf("error building go source: %v", err) } - ctx, cancel := context.WithTimeout(context.Background(), maxRunTime) + ctx, cancel = context.WithTimeout(context.Background(), maxRunTime) defer cancel() cmd = exec.CommandContext(ctx, "sel_ldr_x86_64", "-l", "/dev/null", "-S", "-e", exe, testParam) rec := new(Recorder)