wgengine: fix link monitor / magicsock Start race

Fixes #2733

Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
pull/2734/head
Brad Fitzpatrick 3 years ago committed by Brad Fitzpatrick
parent 0b962567fa
commit 7fcf86a14a

@ -84,6 +84,7 @@ type userspaceEngine struct {
wgLogger *wglog.Logger //a wireguard-go logging wrapper wgLogger *wglog.Logger //a wireguard-go logging wrapper
reqCh chan struct{} reqCh chan struct{}
waitCh chan struct{} // chan is closed when first Close call completes; contrast with closing bool waitCh chan struct{} // chan is closed when first Close call completes; contrast with closing bool
magicConnStarted chan struct{} // chan is closed after magicConn.Start
timeNow func() mono.Time timeNow func() mono.Time
tundev *tstun.Wrapper tundev *tstun.Wrapper
wgdev *device.Device wgdev *device.Device
@ -249,13 +250,14 @@ func NewUserspaceEngine(logf logger.Logf, conf Config) (_ Engine, reterr error)
closePool.add(tsTUNDev) closePool.add(tsTUNDev)
e := &userspaceEngine{ e := &userspaceEngine{
timeNow: mono.Now, timeNow: mono.Now,
logf: logf, logf: logf,
reqCh: make(chan struct{}, 1), reqCh: make(chan struct{}, 1),
waitCh: make(chan struct{}), waitCh: make(chan struct{}),
tundev: tsTUNDev, tundev: tsTUNDev,
router: conf.Router, router: conf.Router,
confListenPort: conf.ListenPort, confListenPort: conf.ListenPort,
magicConnStarted: make(chan struct{}),
} }
e.isLocalAddr.Store(tsaddr.NewContainsIPFunc(nil)) e.isLocalAddr.Store(tsaddr.NewContainsIPFunc(nil))
e.isDNSIPOverTailscale.Store(tsaddr.NewContainsIPFunc(nil)) e.isDNSIPOverTailscale.Store(tsaddr.NewContainsIPFunc(nil))
@ -371,7 +373,7 @@ func NewUserspaceEngine(logf logger.Logf, conf Config) (_ Engine, reterr error)
// It's a little pointless to apply no-op settings here (they // It's a little pointless to apply no-op settings here (they
// should already be empty?), but it at least exercises the // should already be empty?), but it at least exercises the
// router implementation early on the machine. // router implementation early on.
e.logf("Clearing router settings...") e.logf("Clearing router settings...")
if err := e.router.Set(nil); err != nil { if err := e.router.Set(nil); err != nil {
return nil, err return nil, err
@ -380,6 +382,7 @@ func NewUserspaceEngine(logf logger.Logf, conf Config) (_ Engine, reterr error)
e.linkMon.Start() e.linkMon.Start()
e.logf("Starting magicsock...") e.logf("Starting magicsock...")
e.magicConn.Start() e.magicConn.Start()
close(e.magicConnStarted)
go e.pollResolver() go e.pollResolver()
@ -1092,6 +1095,10 @@ func (e *userspaceEngine) LinkChange(_ bool) {
} }
func (e *userspaceEngine) linkChange(changed bool, cur *interfaces.State) { func (e *userspaceEngine) linkChange(changed bool, cur *interfaces.State) {
// Issue 2733: wait for e.magicConn to be started; there's two tiny
// windows at startup where this callback can be run before Start
<-e.magicConnStarted
up := cur.AnyInterfaceUp() up := cur.AnyInterfaceUp()
if !up { if !up {
e.logf("LinkChange: all links down; pausing: %v", cur) e.logf("LinkChange: all links down; pausing: %v", cur)

Loading…
Cancel
Save