summaryrefslogtreecommitdiffhomepage
path: root/ipn/ipnlocal/local.go
diff options
context:
space:
mode:
Diffstat (limited to 'ipn/ipnlocal/local.go')
-rw-r--r--ipn/ipnlocal/local.go32
1 files changed, 25 insertions, 7 deletions
diff --git a/ipn/ipnlocal/local.go b/ipn/ipnlocal/local.go
index a407e7242..6c56d5ac4 100644
--- a/ipn/ipnlocal/local.go
+++ b/ipn/ipnlocal/local.go
@@ -810,7 +810,9 @@ func (b *LocalBackend) setClientStatus(st controlclient.Status) {
if err := b.pm.DeleteProfile(b.pm.CurrentProfile().ID); err != nil {
b.logf("error deleting profile: %v", err)
}
- b.resetForProfileChangeLockedOnEntry()
+ // Restart backend asychonously, so that we avoid reentrancy in the
+ // controclient (we're currently in a callback from it).
+ b.resetForProfileChangeLockedOnEntry(profileChangeStartAsync)
return
}
@@ -2110,7 +2112,7 @@ func (b *LocalBackend) SetCurrentUserID(uid string) {
b.mu.Unlock()
return
}
- b.resetForProfileChangeLockedOnEntry()
+ b.resetForProfileChangeLockedOnEntry(profileChangeStartSync)
}
func (b *LocalBackend) CheckPrefs(p *ipn.Prefs) error {
@@ -4045,16 +4047,32 @@ func (b *LocalBackend) SwitchProfile(profile ipn.ProfileID) error {
b.mu.Unlock()
return err
}
- return b.resetForProfileChangeLockedOnEntry()
+ return b.resetForProfileChangeLockedOnEntry(profileChangeStartSync)
}
+type profileChangeStartMode int
+
+const (
+ profileChangeStartSync profileChangeStartMode = iota
+ profileChangeStartAsync
+)
+
// resetForProfileChangeLockedOnEntry resets the backend for a profile change.
-func (b *LocalBackend) resetForProfileChangeLockedOnEntry() error {
+// It requires b.mu be held to call it, but it unlocks b.mu when done.
+func (b *LocalBackend) resetForProfileChangeLockedOnEntry(startMode profileChangeStartMode) error {
b.setNetMapLocked(nil) // Reset netmap.
// Reset the NetworkMap in the engine
b.e.SetNetworkMap(new(netmap.NetworkMap))
b.enterStateLockedOnEntry(ipn.NoState) // Reset state.
- return b.Start(ipn.Options{})
+ switch startMode {
+ case profileChangeStartSync:
+ return b.Start(ipn.Options{})
+ case profileChangeStartAsync:
+ go b.Start(ipn.Options{})
+ return nil
+ default:
+ panic("unreachable")
+ }
}
// DeleteProfile deletes a profile with the given ID.
@@ -4072,7 +4090,7 @@ func (b *LocalBackend) DeleteProfile(p ipn.ProfileID) error {
if !needToRestart {
return nil
}
- return b.resetForProfileChangeLockedOnEntry()
+ return b.resetForProfileChangeLockedOnEntry(profileChangeStartSync)
}
// CurrentProfile returns the current LoginProfile.
@@ -4087,7 +4105,7 @@ func (b *LocalBackend) CurrentProfile() ipn.LoginProfile {
func (b *LocalBackend) NewProfile() error {
b.mu.Lock()
b.pm.NewProfile()
- return b.resetForProfileChangeLockedOnEntry()
+ return b.resetForProfileChangeLockedOnEntry(profileChangeStartSync)
}
// ListProfiles returns a list of all LoginProfiles.