-
Notifications
You must be signed in to change notification settings - Fork 17.9k
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
cmd/go: go test hangs when exec.CommandContext program uses stdout/stderr #28039
Comments
This is a race condition in the test. You aren't waiting for the sleep program to complete. cmd/go works by building the test program and then running it. Standard output of the test program will be a pipe being read by cmd/go. cmd/go will keep reading from the pipe until all data has been read (this is related to #23019). Using Since you set This is easy to fix in the test by writing it as ctx, canc := context.WithCancel(context.Background())
sleep := exec.CommandContext(ctx, "sleep", "1d")
defer sleep.Wait()
defer canc() The only other fix would be to fix #23019. So closing this issue as a dup. |
Thanks for the explanation, especially the reason why context cancellation doesn’t seem to have any effect here is now clear. Note that the suggested fix ( I extracted this issue from a more elaborate test, where I have a helper function to set up a server process, which is called from multiple tests, e.g.: func setupEnv(ctx context.Context) error {
sleep := exec.CommandContext(ctx, "sleep", "1d")
sleep.Stdout = os.Stdout // sleep.Stderr = os.Stderr triggers the same symptom
if err := sleep.Start(); err != nil {
return err
}
return nil
}
func TestFoo(t *testing.T) {
ctx, canc := context.WithCancel(context.Background())
defer canc()
if err := setupEnv(ctx); err != nil {
t.Fatal(err)
}
// test the server process works correctly
} Obviously, I can’t |
You should definitely arrange for your tests to wait for the server process to exit before they return, one way or another. Apart from this issue it's not great practice to leave a process around potentially writing to stdout as you start a new test. There are various ways you could wait. Returning a cleanup function from |
What version of Go are you using (
go version
)?go version go1.11.1 linux/amd64
Does this issue reproduce with the latest release?
Yes.
What operating system and processor architecture are you using (
go env
)?GOARCH="amd64"
GOBIN=""
GOCACHE="/home/michael/.cache/go-build"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/michael/go"
GOPROXY=""
GORACE=""
GOROOT="/home/michael/sdk/go1.11.1"
GOTMPDIR=""
GOTOOLDIR="/home/michael/sdk/go1.11.1/pkg/tool/linux_amd64"
GCCGO="/usr/bin/gccgo"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build672074712=/tmp/go-build -gno-record-gcc-switches"
What did you do?
What did you expect to see?
The test should pass.
What did you see instead?
go test -count=1 ./repro_test.go
hangs indefinitely.defer func() { sleep.Process.Kill() }()
after sleep.Stdout makes the test pass. I would have expected the context cancellation to have the same effect.killall sleep
makes the test pass with resultok
.The text was updated successfully, but these errors were encountered: