From 9380e2dfc61a720dc20b0e89173779763f29a3e8 Mon Sep 17 00:00:00 2001 From: Maisem Ali Date: Tue, 7 May 2024 23:42:45 +0000 Subject: [PATCH] ipn/ipnlocal: use lockAndGetUnlock in Start This removes one of the Lock,Unlock,Lock,Unlock at least in the Start function. Still has 3 more of these. Updates #11649 Signed-off-by: Maisem Ali --- ipn/ipnlocal/local.go | 46 +++++++++++++++++--------------------- ipn/ipnlocal/state_test.go | 1 + 2 files changed, 22 insertions(+), 25 deletions(-) diff --git a/ipn/ipnlocal/local.go b/ipn/ipnlocal/local.go index 30eabb9c6..e578fd9c2 100644 --- a/ipn/ipnlocal/local.go +++ b/ipn/ipnlocal/local.go @@ -402,7 +402,6 @@ func NewLocalBackend(logf logger.Logf, logID logid.PublicID, sys *tsd.System, lo osshare.SetFileSharingEnabled(false, logf) ctx, cancel := context.WithCancel(context.Background()) - portpoll := new(portlist.Poller) clock := tstime.StdClock{} b := &LocalBackend{ @@ -420,7 +419,7 @@ func NewLocalBackend(logf logger.Logf, logID logid.PublicID, sys *tsd.System, lo pm: pm, backendLogID: logID, state: ipn.NoState, - portpoll: portpoll, + portpoll: new(portlist.Poller), em: newExpiryManager(logf), gotPortPollRes: make(chan struct{}), loginFlags: loginFlags, @@ -1593,6 +1592,14 @@ func (b *LocalBackend) NodeViewByIDForTest(id tailcfg.NodeID) (_ tailcfg.NodeVie return n, ok } +// DisablePortMapperForTest disables the portmapper for tests. +// It must be called before Start. +func (b *LocalBackend) DisablePortMapperForTest() { + b.mu.Lock() + defer b.mu.Unlock() + b.portpoll = nil +} + // PeersForTest returns all the current peers, sorted by Node.ID, // for integration tests in another repo. func (b *LocalBackend) PeersForTest() []tailcfg.NodeView { @@ -1605,9 +1612,7 @@ func (b *LocalBackend) PeersForTest() []tailcfg.NodeView { return ret } -func (b *LocalBackend) getNewControlClientFunc() clientGen { - b.mu.Lock() - defer b.mu.Unlock() +func (b *LocalBackend) getNewControlClientFuncLocked() clientGen { if b.ccGen == nil { // Initialize it rather than just returning the // default to make any future call to @@ -1632,11 +1637,17 @@ func (b *LocalBackend) getNewControlClientFunc() clientGen { func (b *LocalBackend) Start(opts ipn.Options) error { b.logf("Start") - b.mu.Lock() + var clientToShutdown controlclient.Client + defer func() { + if clientToShutdown != nil { + clientToShutdown.Shutdown() + } + }() + unlock := b.lockAndGetUnlock() + defer unlock() if opts.UpdatePrefs != nil { if err := b.checkPrefsLocked(opts.UpdatePrefs); err != nil { - b.mu.Unlock() return err } } @@ -1668,7 +1679,7 @@ func (b *LocalBackend) Start(opts ipn.Options) error { // into sync with the minimal changes. But that's not how it // is right now, which is a sign that the code is still too // complicated. - prevCC := b.resetControlClientLocked() + clientToShutdown = b.resetControlClientLocked() httpTestClient := b.httpTestClient if b.hostinfo != nil { @@ -1697,7 +1708,6 @@ func (b *LocalBackend) Start(opts ipn.Options) error { wantRunning := prefs.WantRunning() if wantRunning { if err := b.initMachineKeyLocked(); err != nil { - b.mu.Unlock() return fmt.Errorf("initMachineKeyLocked: %w", err) } } @@ -1716,7 +1726,6 @@ func (b *LocalBackend) Start(opts ipn.Options) error { persistv = new(persist.Persist) } b.updateFilterLocked(nil, ipn.PrefsView{}) - b.mu.Unlock() if b.portpoll != nil { b.portpollOnce.Do(func() { @@ -1748,15 +1757,11 @@ func (b *LocalBackend) Start(opts ipn.Options) error { debugFlags = append([]string{"netstack"}, debugFlags...) } - if prevCC != nil { - prevCC.Shutdown() - } - // TODO(apenwarr): The only way to change the ServerURL is to // re-run b.Start, because this is the only place we create a // new controlclient. EditPrefs allows you to overwrite ServerURL, // but it won't take effect until the next Start. - cc, err := b.getNewControlClientFunc()(controlclient.Options{ + cc, err := b.getNewControlClientFuncLocked()(controlclient.Options{ GetMachinePrivateKey: b.createGetMachinePrivateKeyFunc(), Logf: logger.WithPrefix(b.logf, "control: "), Persist: *persistv, @@ -1786,14 +1791,6 @@ func (b *LocalBackend) Start(opts ipn.Options) error { return err } - b.mu.Lock() - // Even though we reset b.cc above, we might have raced with - // another Start() call. If so, shut down the previous one again - // as we do not know if it was created with the same options. - prevCC = b.resetControlClientLocked() - if prevCC != nil { - defer prevCC.Shutdown() // must be called after b.mu is unlocked - } b.setControlClientLocked(cc) endpoints := b.endpoints @@ -1804,13 +1801,12 @@ func (b *LocalBackend) Start(opts ipn.Options) error { if b.tka != nil { head, err := b.tka.authority.Head().MarshalText() if err != nil { - b.mu.Unlock() return fmt.Errorf("marshalling tka head: %w", err) } tkaHead = string(head) } confWantRunning := b.conf != nil && wantRunning - b.mu.Unlock() + unlock.UnlockEarly() if endpoints != nil { cc.UpdateEndpoints(endpoints) diff --git a/ipn/ipnlocal/state_test.go b/ipn/ipnlocal/state_test.go index 1f216e4f1..428e9032b 100644 --- a/ipn/ipnlocal/state_test.go +++ b/ipn/ipnlocal/state_test.go @@ -316,6 +316,7 @@ func TestStateMachine(t *testing.T) { if err != nil { t.Fatalf("NewLocalBackend: %v", err) } + b.DisablePortMapperForTest() var cc, previousCC *mockControl b.SetControlClientGetterForTesting(func(opts controlclient.Options) (controlclient.Client, error) {