]> git.ipfire.org Git - thirdparty/wireguard-go.git/commitdiff
device: fix data race in peer.timersActive
authorJosh Bleecher Snyder <josh@tailscale.com>
Wed, 16 Dec 2020 01:44:21 +0000 (17:44 -0800)
committerJosh Bleecher Snyder <josh@tailscale.com>
Thu, 17 Dec 2020 00:16:26 +0000 (16:16 -0800)
Found by the race detector and existing tests.

To avoid introducing a lock into this hot path,
calculate and cache whether any peers exist.

Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
device/device.go
device/peer.go
device/timers.go

index 99f5e602d83ed744cdabd3c38066b7e2a5ff3338..e7d70c4e1a0583ae3b894c58fa1583d23629dbfa 100644 (file)
@@ -49,8 +49,9 @@ type Device struct {
        }
 
        peers struct {
-               sync.RWMutex
-               keyMap map[NoisePublicKey]*Peer
+               empty        AtomicBool // empty reports whether len(keyMap) == 0
+               sync.RWMutex            // protects keyMap
+               keyMap       map[NoisePublicKey]*Peer
        }
 
        // unprotected / "self-synchronising resources"
@@ -129,6 +130,7 @@ func unsafeRemovePeer(device *Device, peer *Peer, key NoisePublicKey) {
        // remove from peer map
 
        delete(device.peers.keyMap, key)
+       device.peers.empty.Set(len(device.peers.keyMap) == 0)
 }
 
 func deviceUpdateState(device *Device) {
index fe6de3345458c642df2ae12bd29cd6b088ba623b..73e60839075ed0b0b4f34498a5001460e44c3973 100644 (file)
@@ -125,6 +125,7 @@ func (device *Device) NewPeer(pk NoisePublicKey) (*Peer, error) {
        // add
 
        device.peers.keyMap[pk] = peer
+       device.peers.empty.Set(false)
 
        // start peer
 
index e94da3654757e05eabf75344298a32ded003df58..dbd4c6676999f7e8ff18771cc511e5ddc308acc5 100644 (file)
@@ -73,7 +73,7 @@ func (timer *Timer) IsPending() bool {
 }
 
 func (peer *Peer) timersActive() bool {
-       return peer.isRunning.Get() && peer.device != nil && peer.device.isUp.Get() && len(peer.device.peers.keyMap) > 0
+       return peer.isRunning.Get() && peer.device != nil && peer.device.isUp.Get() && !peer.device.peers.empty.Get()
 }
 
 func expiredRetransmitHandshake(peer *Peer) {