ipnlocal: fix deadlock in RequestEngineStatusAndWait() error path.

If the engine was shutting down from a previous session
(e.closing=true), it would return an error code when trying to get
status. In that case, ipnlocal would never unblock any callers that
were waiting on the status.

Not sure if this ever happened in real life, but I accidentally
triggered it while writing a test.

Signed-off-by: Avery Pennarun <apenwarr@tailscale.com>
This commit is contained in:
Avery Pennarun 2021-05-06 01:28:43 -04:00 committed by apenwarr
parent 5a7c6f1678
commit 285d0e3b4d

View File

@ -566,10 +566,18 @@ func (b *LocalBackend) findExitNodeIDLocked(nm *netmap.NetworkMap) (prefsChanged
func (b *LocalBackend) setWgengineStatus(s *wgengine.Status, err error) { func (b *LocalBackend) setWgengineStatus(s *wgengine.Status, err error) {
if err != nil { if err != nil {
b.logf("wgengine status error: %v", err) b.logf("wgengine status error: %v", err)
b.statusLock.Lock()
b.statusChanged.Broadcast()
b.statusLock.Unlock()
return return
} }
if s == nil { if s == nil {
b.logf("[unexpected] non-error wgengine update with status=nil: %v", s) b.logf("[unexpected] non-error wgengine update with status=nil: %v", s)
b.statusLock.Lock()
b.statusChanged.Broadcast()
b.statusLock.Unlock()
return return
} }