mirror of
https://github.com/netbirdio/netbird.git
synced 2026-08-28 18:41:30 +02:00
[client] Serialize availability transitions in the netevents manager
SetNetworkAvailable read IsOnline before updating netState without any locking, so concurrent availability flips could interleave: a false call could observe a stale offline state, skip MarkNetworkChange, and land after a racing true call, leaving the client offline with unswept connections. The netState and recorder updates could also apply out of order, letting the listener state disagree with netState. On Android the initial availability push at service start races the ConnectivityManager callbacks, and iOS feeds the same manager from NWPathMonitor. Hold a manager mutex across the check, sweep mark, state update and recorder update so transitions apply atomically and in order.
This commit is contained in:
@@ -6,6 +6,7 @@ package netevents
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/cenkalti/backoff/v4"
|
||||
@@ -25,6 +26,10 @@ type Recorder interface {
|
||||
// the valid no-events value: the read methods report always-online and never
|
||||
// sweep.
|
||||
type Manager struct {
|
||||
// mu serializes availability transitions: the IsOnline check and the
|
||||
// state update must be atomic, or a racing offline flip can skip the sweep
|
||||
// and leave netState and the recorder disagreeing.
|
||||
mu sync.Mutex
|
||||
netState *netstate.State
|
||||
sweeper *sweep.Sweeper
|
||||
recorder Recorder
|
||||
@@ -48,6 +53,9 @@ func NewManager(recorder Recorder) *Manager {
|
||||
// "connected" until their own timeouts and the client would keep reporting
|
||||
// Connected with no network at all.
|
||||
func (m *Manager) SetNetworkAvailable(available bool) {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
|
||||
if !available && m.netState.IsOnline() {
|
||||
m.sweeper.MarkNetworkChange()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user