mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
runtime: return a different bubble deadlock error when main goroutine is done
The synctest.Test function waits for all goroutines in a bubble to exit before returning. If there is ever a point when all goroutines in a bubble are durably blocked, it panics and reports a deadlock. Panic with a different message depending on whether the bubble's main goroutine has returned or not. The main goroutine returning stops the bubble clock, so knowing whether it is running or not is useful debugging information. The new panic messages are: deadlock: all goroutines in bubble are blocked deadlock: main bubble goroutine has exited but blocked goroutines remain Change-Id: I94a69e79121c272d9c86f412c1c9c7de57ef27ef Reviewed-on: https://go-review.googlesource.com/c/go/+/679375 Auto-Submit: Damien Neil <dneil@google.com> Reviewed-by: Michael Pratt <mpratt@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
parent
ac1686752b
commit
049a5e6036
2 changed files with 12 additions and 5 deletions
|
|
@ -488,7 +488,7 @@ func TestDeadlockRoot(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestDeadlockChild(t *testing.T) {
|
||||
defer wantPanic(t, "deadlock: all goroutines in bubble are blocked")
|
||||
defer wantPanic(t, "deadlock: main bubble goroutine has exited but blocked goroutines remain")
|
||||
synctest.Run(func() {
|
||||
go func() {
|
||||
select {}
|
||||
|
|
@ -497,7 +497,7 @@ func TestDeadlockChild(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestDeadlockTicker(t *testing.T) {
|
||||
defer wantPanic(t, "deadlock: all goroutines in bubble are blocked")
|
||||
defer wantPanic(t, "deadlock: main bubble goroutine has exited but blocked goroutines remain")
|
||||
synctest.Run(func() {
|
||||
go func() {
|
||||
for range time.Tick(1 * time.Second) {
|
||||
|
|
|
|||
|
|
@ -242,7 +242,13 @@ func synctestRun(f func()) {
|
|||
raceacquireg(gp, gp.bubble.raceaddr())
|
||||
}
|
||||
if total != 1 {
|
||||
panic(synctestDeadlockError{bubble})
|
||||
var reason string
|
||||
if bubble.done {
|
||||
reason = "deadlock: main bubble goroutine has exited but blocked goroutines remain"
|
||||
} else {
|
||||
reason = "deadlock: all goroutines in bubble are blocked"
|
||||
}
|
||||
panic(synctestDeadlockError{reason: reason, bubble: bubble})
|
||||
}
|
||||
if gp.timer != nil && gp.timer.isFake {
|
||||
// Verify that we haven't marked this goroutine's sleep timer as fake.
|
||||
|
|
@ -252,11 +258,12 @@ func synctestRun(f func()) {
|
|||
}
|
||||
|
||||
type synctestDeadlockError struct {
|
||||
reason string
|
||||
bubble *synctestBubble
|
||||
}
|
||||
|
||||
func (synctestDeadlockError) Error() string {
|
||||
return "deadlock: all goroutines in bubble are blocked"
|
||||
func (e synctestDeadlockError) Error() string {
|
||||
return e.reason
|
||||
}
|
||||
|
||||
func synctestidle_c(gp *g, _ unsafe.Pointer) bool {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue