diff options
| author | Brad Fitzpatrick <bradfitz@golang.org> | 2011-06-01 15:26:53 -0700 |
|---|---|---|
| committer | Brad Fitzpatrick <bradfitz@golang.org> | 2011-06-01 15:26:53 -0700 |
| commit | f259f6ba0adfa0b98e74b27dbe6013d012a037eb (patch) | |
| tree | f180aad60f74af96b5437c798123c83fab63da8a /src/pkg/http | |
| parent | 2132a7f575cba670eeffde495c0bb2df120c2c5b (diff) | |
| download | go-f259f6ba0adfa0b98e74b27dbe6013d012a037eb.tar.xz | |
exec: new API, replace Run with Command
This removes exec.Run and replaces exec.Cmd with a
new implementation. The new exec.Cmd represents
both a currently-running command and also a command
being prepared. It has a good zero value.
You can Start + Wait on a Cmd, or simply Run it.
Start (and Run) deal with copying stdout, stdin,
and stderr between the Cmd's io.Readers and
io.Writers.
There are convenience methods to capture a command's
stdout and/or stderr.
R=r, n13m3y3r, rsc, gustavo, alex.brainman, dsymonds, r, adg, duzy.chan, mike.rosset, kevlar
CC=golang-dev
https://golang.org/cl/4552052
Diffstat (limited to 'src/pkg/http')
| -rw-r--r-- | src/pkg/http/cgi/host.go | 44 | ||||
| -rw-r--r-- | src/pkg/http/cgi/host_test.go | 23 |
2 files changed, 32 insertions, 35 deletions
diff --git a/src/pkg/http/cgi/host.go b/src/pkg/http/cgi/host.go index 7e4ccf881d..c283191ef2 100644 --- a/src/pkg/http/cgi/host.go +++ b/src/pkg/http/cgi/host.go @@ -156,34 +156,38 @@ func (h *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request) { cwd = "." } - args := []string{h.Path} - args = append(args, h.Args...) - - cmd, err := exec.Run( - pathBase, - args, - env, - cwd, - exec.Pipe, // stdin - exec.Pipe, // stdout - exec.PassThrough, // stderr (for now) - ) - if err != nil { + internalError := func(err os.Error) { rw.WriteHeader(http.StatusInternalServerError) h.printf("CGI error: %v", err) + } + + stdoutRead, stdoutWrite, err := os.Pipe() + if err != nil { + internalError(err) return } - defer func() { - cmd.Stdin.Close() - cmd.Stdout.Close() - cmd.Wait(0) // no zombies - }() + cmd := &exec.Cmd{ + Path: pathBase, + Args: append([]string{h.Path}, h.Args...), + Dir: cwd, + Env: env, + Stdout: stdoutWrite, + Stderr: os.Stderr, // for now + } if req.ContentLength != 0 { - go io.Copy(cmd.Stdin, req.Body) + cmd.Stdin = req.Body + } + + err = cmd.Start() + if err != nil { + internalError(err) + return } + stdoutWrite.Close() + defer cmd.Wait() - linebody, _ := bufio.NewReaderSize(cmd.Stdout, 1024) + linebody, _ := bufio.NewReaderSize(stdoutRead, 1024) headers := make(http.Header) statusCode := 0 for { diff --git a/src/pkg/http/cgi/host_test.go b/src/pkg/http/cgi/host_test.go index 9ac085f2f3..bbdb715cf9 100644 --- a/src/pkg/http/cgi/host_test.go +++ b/src/pkg/http/cgi/host_test.go @@ -17,20 +17,6 @@ import ( "testing" ) -var cgiScriptWorks = canRun("./testdata/test.cgi") - -func canRun(s string) bool { - c, err := exec.Run(s, []string{s}, nil, ".", exec.DevNull, exec.DevNull, exec.DevNull) - if err != nil { - return false - } - w, err := c.Wait(0) - if err != nil { - return false - } - return w.Exited() && w.ExitStatus() == 0 -} - func newRequest(httpreq string) *http.Request { buf := bufio.NewReader(strings.NewReader(httpreq)) req, err := http.ReadRequest(buf) @@ -76,8 +62,15 @@ readlines: return rw } +var cgiTested = false +var cgiWorks bool + func skipTest(t *testing.T) bool { - if !cgiScriptWorks { + if !cgiTested { + cgiTested = true + cgiWorks = exec.Command("./testdata/test.cgi").Run() == nil + } + if !cgiWorks { // No Perl on Windows, needed by test.cgi // TODO: make the child process be Go, not Perl. t.Logf("Skipping test: test.cgi failed.") |
