health: fix nil DERPMap dereference panic

Looks like a DERPmap might not be available when we try to get the
name associated with a region ID, and that was causing an intermittent
panic in CI.

Fixes #12534

Change-Id: I4ace53681bf004df46c728cff830b27339254243
Signed-off-by: Andrea Gottardo <andrea@gottardo.me>
This commit is contained in:
Andrea Gottardo 2024-06-18 22:34:50 -07:00 committed by Brad Fitzpatrick
parent 25eeafde23
commit d7619d273b

View File

@ -685,6 +685,18 @@ func (t *Tracker) SetDERPMap(dm *tailcfg.DERPMap) {
t.selfCheckLocked()
}
// derpRegionNameLocked returns the name of the DERP region with the given ID
// or the empty string if unknown.
func (t *Tracker) derpRegionNameLocked(regID int) string {
if t.derpMap == nil {
return ""
}
if r, ok := t.derpMap.Regions[regID]; ok {
return r.RegionName
}
return ""
}
// state is an ipn.State.String() value: "Running", "Stopped", "NeedsLogin", etc.
func (t *Tracker) SetIPNState(state string, wantRunning bool) {
if t.nil() {
@ -928,13 +940,13 @@ func (t *Tracker) updateBuiltinWarnablesLocked() {
} else if !t.derpRegionConnected[rid] {
t.setUnhealthyLocked(noDERPConnectionWarnable, Args{
ArgDERPRegionID: fmt.Sprint(rid),
ArgDERPRegionName: t.derpMap.Regions[rid].RegionName,
ArgDERPRegionName: t.derpRegionNameLocked(rid),
})
return
} else if d := now.Sub(t.derpRegionLastFrame[rid]).Round(time.Second); d > tooIdle {
t.setUnhealthyLocked(derpTimeoutWarnable, Args{
ArgDERPRegionID: fmt.Sprint(rid),
ArgDERPRegionName: t.derpMap.Regions[rid].RegionName,
ArgDERPRegionName: t.derpRegionNameLocked(rid),
ArgDuration: d.String(),
})
return