Browse Source

ipn/ipnlocal: remember last notified taildrive shares and only notify if they've changed

Fixes #13195

Signed-off-by: Percy Wegmann <[email protected]>
Percy Wegmann 1 year ago
parent
commit
4637ac732e
2 changed files with 16 additions and 7 deletions
  1. 12 6
      ipn/ipnlocal/drive.go
  2. 4 1
      ipn/ipnlocal/local.go

+ 12 - 6
ipn/ipnlocal/drive.go

@@ -247,8 +247,17 @@ func (b *LocalBackend) driveSetSharesLocked(shares []*drive.Share) error {
 }
 
 // driveNotifyShares notifies IPN bus listeners (e.g. Mac Application process)
-// about the latest list of shares.
+// about the latest list of shares, if and only if the shares have changed since
+// the last time we notified.
 func (b *LocalBackend) driveNotifyShares(shares views.SliceView[*drive.Share, drive.ShareView]) {
+	b.lastNotifiedDriveSharesMu.Lock()
+	defer b.lastNotifiedDriveSharesMu.Unlock()
+	if b.lastNotifiedDriveShares != nil && driveShareViewsEqual(b.lastNotifiedDriveShares, shares) {
+		// shares are unchanged since last notification, don't bother notifying
+		return
+	}
+	b.lastNotifiedDriveShares = &shares
+
 	// Ensures shares is not nil to distinguish "no shares" from "not notifying shares"
 	if shares.IsNil() {
 		shares = views.SliceOfViews(make([]*drive.Share, 0))
@@ -265,11 +274,8 @@ func (b *LocalBackend) driveNotifyCurrentSharesLocked() {
 		shares = b.pm.prefs.DriveShares()
 	}
 
-	lastNotified := b.lastNotifiedDriveShares.Load()
-	if lastNotified == nil || !driveShareViewsEqual(lastNotified, shares) {
-		// Do the below on a goroutine to avoid deadlocking on b.mu in b.send().
-		go b.driveNotifyShares(shares)
-	}
+	// Do the below on a goroutine to avoid deadlocking on b.mu in b.send().
+	go b.driveNotifyShares(shares)
 }
 
 func driveShareViewsEqual(a *views.SliceView[*drive.Share, drive.ShareView], b views.SliceView[*drive.Share, drive.ShareView]) bool {

+ 4 - 1
ipn/ipnlocal/local.go

@@ -332,9 +332,12 @@ type LocalBackend struct {
 	// Last ClientVersion received in MapResponse, guarded by mu.
 	lastClientVersion *tailcfg.ClientVersion
 
+	// lastNotifiedDriveSharesMu guards lastNotifiedDriveShares
+	lastNotifiedDriveSharesMu sync.Mutex
+
 	// lastNotifiedDriveShares keeps track of the last set of shares that we
 	// notified about.
-	lastNotifiedDriveShares atomic.Pointer[views.SliceView[*drive.Share, drive.ShareView]]
+	lastNotifiedDriveShares *views.SliceView[*drive.Share, drive.ShareView]
 
 	// outgoingFiles keeps track of Taildrop outgoing files keyed to their OutgoingFile.ID
 	outgoingFiles map[string]*ipn.OutgoingFile