-
Notifications
You must be signed in to change notification settings - Fork 17.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
testing: Example test with runtime.Goexit hangs #41084
Comments
Is it the documented behavior? |
Thank you for filing this @prashantv, and thank you @go101 for responding to @prashantv’s question. Indeed as @go101 points out, that is the behavior of Goexit(), and in the main test code, there are other goroutines running in the background and as documented it can’t return until all the other goroutines have. I shall close this issue, but thank you again. |
Hi @odeke-em, I think this is a testing package issue, since The |
@prashantv there are other goroutines running for Example as I had mentioned and for example if you see the implementation in Line 21 in 4fc3896
by you invoking runtime.Goexit() you are killing that goroutine in its main without ever returning yet there are other goroutines that haven't yet been terminated and are waiting for output. This is an implementation detail about Example tests that I don't think needs to be changed. You can validate that the goroutines are running by printing the stack of the entire system like this package main
import (
"runtime"
)
func ExampleGoexit() {
buf := make([]byte, 1024)
for {
n := runtime.Stack(buf, true)
if n < len(buf) {
break
}
buf = make([]byte, 2*len(buf))
}
println(string(buf))
runtime.Goexit()
// Output:
} which will produce $ go test
goroutine 1 [running]:
github.com/odeke-em/bugs/golang/41084.ExampleGoexit()
/Users/emmanuelodeke/Desktop/openSrc/bugs/golang/41084/example_test.go:10 +0x9f
testing.runExample(0x1140b3b, 0xd, 0x1148c80, 0x0, 0x0, 0x0, 0x0)
/Users/emmanuelodeke/go/src/go.googlesource.com/go/src/testing/run_example.go:62 +0x209
testing.runExamples(0xc00009ce80, 0x12149c0, 0x1, 0x1, 0xbfcacc4fada05fc8)
/Users/emmanuelodeke/go/src/go.googlesource.com/go/src/testing/example.go:44 +0x1af
testing.(*M).Run(0xc0000cc000, 0x0)
/Users/emmanuelodeke/go/src/go.googlesource.com/go/src/testing/testing.go:1354 +0x2cd
github.com/odeke-em/bugs/golang/41084.TestMain(...)
/Users/emmanuelodeke/Desktop/openSrc/bugs/golang/41084/it_test.go:8
main.main()
_testmain.go:45 +0x165
goroutine 19 [runnable]:
syscall.syscall(0x1076d00, 0x6, 0xc000102000, 0x8000, 0xffffffffffffffff, 0xffffffffffffffff, 0x23)
/Users/emmanuelodeke/go/src/go.googlesource.com/go/src/runtime/sys_darwin.go:63 +0x2e
syscall.read(0x6, 0xc000102000, 0x8000, 0x8000, 0x1208840, 0x1723fd8, 0x100a3bf)
/Users/emmanuelodeke/go/src/go.googlesource.com/go/src/syscall/zsyscall_darwin_amd64.go:1242 +0x66
syscall.Read(0x6, 0xc000102000, 0x8000, 0x8000, 0x72, 0x0, 0x0)
/Users/emmanuelodeke/go/src/go.googlesource.com/go/src/syscall/syscall_unix.go:187 +0x49
internal/poll.ignoringEINTRIO(0x11492d0, 0x6, 0xc000102000, 0x8000, 0x8000, 0x1723fd8, 0x1106d01, 0x10100000111eb80)
/Users/emmanuelodeke/go/src/go.googlesource.com/go/src/internal/poll/fd_unix.go:563 +0x52
internal/poll.(*FD).Read(0xc0000a41e0, 0xc000102000, 0x8000, 0x8000, 0x0, 0x0, 0x0)
/Users/emmanuelodeke/go/src/go.googlesource.com/go/src/internal/poll/fd_unix.go:155 +0x149
os.(*File).read(...)
/Users/emmanuelodeke/go/src/go.googlesource.com/go/src/os/file_posix.go:31
os.(*File).Read(0xc0000a2030, 0xc000102000, 0x8000, 0x8000, 0x0, 0xc000040700, 0x100645d)
/Users/emmanuelodeke/go/src/go.googlesource.com/go/src/os/file.go:116 +0x71
io.copyBuffer(0x11694b8, 0xc000100000, 0x11693d8, 0xc0000a2030, 0xc000102000, 0x8000, 0x8000, 0xc00008c120, 0xc0000407a8, 0x1005eab)
/Users/emmanuelodeke/go/src/go.googlesource.com/go/src/io/io.go:409 +0x12c
io.Copy(...)
/Users/emmanuelodeke/go/src/go.googlesource.com/go/src/io/io.go:368
testing.runExample.func1(0xc0000a2030, 0xc00008c1e0)
/Users/emmanuelodeke/go/src/go.googlesource.com/go/src/testing/run_example.go:37 +0x85
created by testing.runExample
/Users/emmanuelodeke/go/src/go.googlesource.com/go/src/testing/run_example.go:35 +0x176 and you'll see the goroutine that's still waiting in there. |
I understand why it's hanging, but it doesn't hang for Line 1069 in 4fc3896
This logic doesn't exist for example tests, and so it hangs, which doesn't seem ideal. It seems beneficial to users to detect a Perhaps I'm missing a reason for why Example tests should not have consistent behaviour with standard test functions, I thought it might have just been overlooked. |
Thank you for the follow-up question @prashantv, you raise a great concern which I don't have an answer to off the top of my head, thus I shall re-open this for investigation and other comments. |
@prashantv I misunderstood the issue and incorrectly renamed it with the runtime package. It's been corrected. |
/cc @mpvl |
In theory we could run each That said, use of |
@bcmills I don't know refactoring to run |
If the examples are executed sequentially on the same goroutine, then a |
@bcmills Thanks for the quick response. What's the behavior to safely write |
Change https://golang.org/cl/251857 mentions this issue: |
What version of Go are you using (
go version
)?(Also verified on 1.14 on both linux and darwin)
Does this issue reproduce with the latest release?
Yes
What operating system and processor architecture are you using (
go env
)?go env
OutputWhat did you do?
Used
runtime.Goexit
in an example test from the main test goroutine.What did you expect to see?
A failure, similar to when
runtime.Goexit
is used in a test,What did you see instead?
The example test hangs (until the test timeout is hit):
I can send a SIGQUIT to get the backtrace:
In the Go playground, this triggers a deadlock:
https://play.golang.org/p/xaSFhxBPeKB
The text was updated successfully, but these errors were encountered: