}
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 {}
}
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) {
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.
}
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 {