Skip to content

os/exec: example test using Command.Stdout causes data race #17769

@stapelberg

Description

@stapelberg

What version of Go are you using (go version)?

go version go1.7.3 linux/amd64

What operating system and processor architecture are you using (go env)?

GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/usr/local/google/home/stapelberg/gocode"
GORACE=""
GOROOT="/usr/lib/google-golang"
GOTOOLDIR="/usr/lib/google-golang/pkg/tool/linux_amd64"
CC="gcc"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build817336530=/tmp/go-build -gno-record-gcc-switches"
CXX="g++"
CGO_ENABLED="1"

What did you do?

The following example test triggers a data race:

package example_test

import (
    "os"
    "os/exec"
)

func ExampleFoo() {
    fmt.Println("foo")

    cmd := exec.Command("/bin/sh", "-c", "sleep 999d")
    cmd.Stdout = os.Stdout
    go cmd.Run()

    // OUTPUT:
    // foo
}

In case it matters, I’m running go test -race -v examplerace/..., the above example is stored in gocode/src/examplerace/example_test.go

What did you expect to see?

I expected the test to pass.

What did you see instead?

The test triggers a data race:

$ go test -race -v examplerace/...
=== RUN   ExampleFoo
--- PASS: ExampleFoo (0.00s)
PASS
==================
WARNING: DATA RACE
Read at 0x00c42009c0c0 by goroutine 8:
  os.startProcess()
      /usr/lib/google-golang/src/os/exec_posix.go:45 +0x65a
  os.StartProcess()
      /usr/lib/google-golang/src/os/doc.go:28 +0x7a
  os/exec.(*Cmd).Start()
      /usr/lib/google-golang/src/os/exec/exec.go:358 +0x6a0
  os/exec.(*Cmd).Run()
      /usr/lib/google-golang/src/os/exec/exec.go:276 +0x3c

Previous write at 0x00c42009c0c0 by main goroutine:
  os.(*file).close()
      /usr/lib/google-golang/src/os/file_unix.go:149 +0x124
  os.(*File).Close()
      /usr/lib/google-golang/src/os/file_unix.go:138 +0x55
  testing.runExample.func2()
      /usr/lib/google-golang/src/testing/example.go:85 +0xdf
  testing.runExample()
      /usr/lib/google-golang/src/testing/example.go:115 +0x1fc
  testing.RunExamples()
      /usr/lib/google-golang/src/testing/example.go:38 +0x1b1
  testing.(*M).Run()
      /usr/lib/google-golang/src/testing/testing.go:746 +0x189
  main.main()
      examplerace/_test/_testmain.go:54 +0x1b8

Goroutine 8 (running) created at:
  examplerace_test.ExampleFoo()
      /usr/local/google/home/stapelberg/gocode/src/examplerace/example_test.go:14 +0x1b9
  testing.runExample()
      /usr/lib/google-golang/src/testing/example.go:114 +0x1fb
  testing.RunExamples()
      /usr/lib/google-golang/src/testing/example.go:38 +0x1b1
  testing.(*M).Run()
      /usr/lib/google-golang/src/testing/testing.go:746 +0x189
  main.main()
      examplerace/_test/_testmain.go:54 +0x1b8
==================
Found 1 data race(s)
exit status 66
FAIL	examplerace	1.029s

Metadata

Metadata

Assignees

No one assigned

    Labels

    FrozenDueToAgeNeedsFixThe path to resolution is known, but the work has not been done.

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions