Commit 2b338dd6a8 removed watchdogEngine because it was weird
(so many methods) and increasingly unnecessary after we'd cleaned up
and simplified so much of the locking.
This adds back a watchdog, but an easier to maintain one that's more
idiomatic.
Updates #19759
Change-Id: I86c458473e126c0809f37696446ce7acf4cc4eb9
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
65 lines
1.7 KiB
Go
65 lines
1.7 KiB
Go
// Copyright (c) Tailscale Inc & contributors
|
|
// SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
package ipnlocal
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"tailscale.com/tstest"
|
|
)
|
|
|
|
func TestCheckDeadlocksRateLimitAndTimerReuse(t *testing.T) {
|
|
clock := tstest.NewClock(tstest.ClockOpts{Start: time.Unix(123, 0)})
|
|
b := &LocalBackend{clock: clock}
|
|
|
|
done := b.CheckDeadlocks()
|
|
if b.lastDeadlockCheckUnix.Load() != 124 {
|
|
t.Fatalf("lastDeadlockCheckUnix = %v, want 124", b.lastDeadlockCheckUnix.Load())
|
|
}
|
|
timer := b.deadlockProbeTimer
|
|
if timer == nil {
|
|
t.Fatal("deadlockProbeTimer is nil")
|
|
}
|
|
if b.deadlockTimer != nil {
|
|
t.Fatal("deadlockTimer is non-nil before delayed probe fires")
|
|
}
|
|
if got := b.deadlockChecksInFlight.Load(); got != 1 {
|
|
t.Fatalf("deadlockChecksInFlight = %v, want 1", got)
|
|
}
|
|
done()
|
|
if b.deadlockChecksInFlight.Load() != 0 {
|
|
t.Fatalf("deadlockChecksInFlight after DoneDeadlockCheck = %v, want 0", b.deadlockChecksInFlight.Load())
|
|
}
|
|
|
|
doneCh := make(chan struct{})
|
|
go func() {
|
|
b.CheckDeadlocks()()
|
|
close(doneCh)
|
|
}()
|
|
select {
|
|
case <-doneCh:
|
|
case <-time.After(1 * time.Second):
|
|
t.Fatal("same-second CheckDeadlocks did not take the rate-limit fast path")
|
|
}
|
|
if b.deadlockProbeTimer != timer {
|
|
t.Fatal("same-second CheckDeadlocks allocated a new probe timer")
|
|
}
|
|
|
|
clock.Advance(time.Second)
|
|
done = b.CheckDeadlocks()
|
|
if b.deadlockProbeTimer != timer {
|
|
t.Fatal("CheckDeadlocks allocated a new probe timer instead of reusing the existing one")
|
|
}
|
|
if got := b.deadlockChecksInFlight.Load(); got != 1 {
|
|
t.Fatalf("deadlockChecksInFlight = %v, want 1", got)
|
|
}
|
|
|
|
b.runDeadlockProbe()
|
|
if b.deadlockTimer == nil {
|
|
t.Fatal("runDeadlockProbe did not allocate the deadlock timer")
|
|
}
|
|
done()
|
|
}
|