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
parent 5a7c6f1678
commit c6756a82c3

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
} }