-
Notifications
You must be signed in to change notification settings - Fork 17.7k
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: timeouts prevent deadlock detection from working #69188
Comments
If there is an active timer, the program is not deadlocked. It will keep running when the timer expires. To fix this we would need to somehow add a special case for the testing timeout. I don't think it's worth it. There are already many other cases where the deadlock detector does not reliably detect deadlocks. |
Would it suffice to simply keep a count of goroutines excluded from deadlock analysis? Something like the following pseudocode: diff --git a/src/runtime/proc.go b/src/runtime/proc.go
index c4f175b..5304612 100644
--- a/src/runtime/proc.go
+++ b/src/runtime/proc.go
@@ -5902,10 +5902,12 @@ func incidlelocked(v int32) {
checkdead()
}
unlock(&sched.lock)
}
+var excludedGoroutines atomic.Int32
+
// Check for deadlock situation.
// The check is based on number of running M's, if 0 -> deadlock.
// sched.lock must be held.
func checkdead() {
assertLockHeld(&sched.lock)
@@ -5931,10 +5933,11 @@ func checkdead() {
// for details.)
var run0 int32
if !iscgo && cgoHasExtraM && extraMLength.Load() > 0 {
run0 = 1
}
+ run0 += excludedGoroutines.Load()
run := mcount() - sched.nmidle - sched.nmidlelocked - sched.nmsys
if run > run0 {
return
}
diff --git a/src/testing/testing.go b/src/testing/testing.go
index 526cba3..d6731e2 100644
--- a/src/testing/testing.go
+++ b/src/testing/testing.go
@@ -2370,10 +2370,11 @@ func (m *M) startAlarm() time.Time {
}
extra = b.String()
}
panic(fmt.Sprintf("test timed out after %v%s", *timeout, extra))
})
+ excludedGoroutines.Add(1)
return deadline
}
// runningList returns the list of running tests.
func runningList() []string {
@@ -2387,10 +2388,11 @@ func runningList() []string {
}
// stopAlarm turns off the alarm.
func (m *M) stopAlarm() {
if *timeout > 0 {
+ excludedGoroutines.Add(-1)
m.timer.Stop()
}
}
func parseCpuList() { Relevant code blocks: Lines 5928 to 5940 in 6885bad
Lines 2352 to 2394 in 6885bad
|
It doesn't really have anything to do with goroutines. A timer does not imply a goroutine. A timer just mean that at some point in the future a value will appear on a channel or a function will be run. That might in turn unblock some other goroutine. |
Go version
go version go1.23.0 linux/amd64
Output of
go env
in your module/workspace:Click to expand
What did you do?
What did you see happen?
What did you expect to see?
The text was updated successfully, but these errors were encountered: