wgengine/magicsock: log when a ReceiveFunc fails

Updates #10976

Change-Id: I86d30151a25c7d42ed36e273fb207873f4acfdb4
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
22332-macos-sequoia-hostname
Brad Fitzpatrick 3 months ago committed by Brad Fitzpatrick
parent 74b9fa1348
commit 2dd71e64ac

@ -65,6 +65,11 @@ type Tracker struct {
// magicsock receive functions: IPv4, IPv6, and DERP. // magicsock receive functions: IPv4, IPv6, and DERP.
MagicSockReceiveFuncs [3]ReceiveFuncStats // indexed by ReceiveFunc values MagicSockReceiveFuncs [3]ReceiveFuncStats // indexed by ReceiveFunc values
// initOnce guards the initialization of the Tracker.
// Notably, it initializes the MagicSockReceiveFuncs names.
// mu should not be held during init.
initOnce sync.Once
// mu guards everything that follows. // mu guards everything that follows.
mu sync.Mutex mu sync.Mutex
@ -433,6 +438,7 @@ func (t *Tracker) RegisterWatcher(cb func(w *Warnable, r *UnhealthyState)) (unre
if t.nil() { if t.nil() {
return func() {} return func() {}
} }
t.initOnce.Do(t.doOnceInit)
t.mu.Lock() t.mu.Lock()
defer t.mu.Unlock() defer t.mu.Unlock()
if t.watchers == nil { if t.watchers == nil {
@ -859,6 +865,7 @@ func (t *Tracker) timerSelfCheck() {
if t.nil() { if t.nil() {
return return
} }
t.initOnce.Do(t.doOnceInit)
t.mu.Lock() t.mu.Lock()
defer t.mu.Unlock() defer t.mu.Unlock()
t.checkReceiveFuncsLocked() t.checkReceiveFuncsLocked()
@ -1168,6 +1175,11 @@ type ReceiveFuncStats struct {
missing bool missing bool
} }
// Name returns the name of the receive func ("ReceiveIPv4", "ReceiveIPv6", etc).
func (s *ReceiveFuncStats) Name() string {
return s.name
}
func (s *ReceiveFuncStats) Enter() { func (s *ReceiveFuncStats) Enter() {
s.numCalls.Add(1) s.numCalls.Add(1)
s.inCall.Store(true) s.inCall.Store(true)
@ -1185,15 +1197,20 @@ func (t *Tracker) ReceiveFuncStats(which ReceiveFunc) *ReceiveFuncStats {
if t == nil { if t == nil {
return nil return nil
} }
t.initOnce.Do(t.doOnceInit)
return &t.MagicSockReceiveFuncs[which] return &t.MagicSockReceiveFuncs[which]
} }
func (t *Tracker) doOnceInit() {
for i := range t.MagicSockReceiveFuncs {
f := &t.MagicSockReceiveFuncs[i]
f.name = (ReceiveFunc(i)).String()
}
}
func (t *Tracker) checkReceiveFuncsLocked() { func (t *Tracker) checkReceiveFuncsLocked() {
for i := range t.MagicSockReceiveFuncs { for i := range t.MagicSockReceiveFuncs {
f := &t.MagicSockReceiveFuncs[i] f := &t.MagicSockReceiveFuncs[i]
if f.name == "" {
f.name = (ReceiveFunc(i)).String()
}
if runtime.GOOS == "js" && i < 2 { if runtime.GOOS == "js" && i < 2 {
// Skip IPv4 and IPv6 on js. // Skip IPv4 and IPv6 on js.
continue continue

@ -1274,10 +1274,15 @@ func (c *Conn) mkReceiveFunc(ruc *RebindingUDPConn, healthItem *health.ReceiveFu
// epCache caches an IPPort->endpoint for hot flows. // epCache caches an IPPort->endpoint for hot flows.
var epCache ippEndpointCache var epCache ippEndpointCache
return func(buffs [][]byte, sizes []int, eps []conn.Endpoint) (int, error) { return func(buffs [][]byte, sizes []int, eps []conn.Endpoint) (_ int, retErr error) {
if healthItem != nil { if healthItem != nil {
healthItem.Enter() healthItem.Enter()
defer healthItem.Exit() defer healthItem.Exit()
defer func() {
if retErr != nil {
c.logf("Receive func %s exiting with error: %T, %v", healthItem.Name(), retErr, retErr)
}
}()
} }
if ruc == nil { if ruc == nil {
panic("nil RebindingUDPConn") panic("nil RebindingUDPConn")

Loading…
Cancel
Save