5
0
mirror of https://github.com/cwinfo/yggdrasil-go.git synced 2024-11-22 22:20:27 +00:00

Merge pull request #534 from Arceliar/bugfix

Fix race between router and dial code
This commit is contained in:
Neil Alexander 2019-09-04 12:21:42 +01:00 committed by GitHub
commit 9da0c40239
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -90,45 +90,47 @@ func (c *Conn) setMTU(from phony.Actor, mtu uint16) {
// This should never be called from the router goroutine, used in the dial functions // This should never be called from the router goroutine, used in the dial functions
func (c *Conn) search() error { func (c *Conn) search() error {
var sinfo *searchInfo var err error
var isIn bool done := make(chan struct{})
phony.Block(&c.core.router, func() { phony.Block(&c.core.router, func() {
sinfo, isIn = c.core.router.searches.searches[*c.nodeID] _, isIn := c.core.router.searches.searches[*c.nodeID]
}) if !isIn {
if !isIn { searchCompleted := func(sinfo *sessionInfo, e error) {
done := make(chan struct{}, 1) select {
var sess *sessionInfo case <-done:
var err error // Somehow this was called multiple times, TODO don't let that happen
searchCompleted := func(sinfo *sessionInfo, e error) { if sinfo != nil {
sess = sinfo // Need to clean up to avoid a session leak
err = e sinfo.cancel.Cancel(nil)
// FIXME close can be called multiple times, do a non-blocking send instead }
select { default:
case done <- struct{}{}: if sinfo != nil {
default: // Finish initializing the session
sinfo.conn = c
}
c.session = sinfo
err = e
close(done)
}
} }
} sinfo := c.core.router.searches.newIterSearch(c.nodeID, c.nodeMask, searchCompleted)
phony.Block(&c.core.router, func() {
sinfo = c.core.router.searches.newIterSearch(c.nodeID, c.nodeMask, searchCompleted)
sinfo.continueSearch() sinfo.continueSearch()
}) } else {
<-done err = errors.New("search already exists")
c.session = sess close(done)
if c.session == nil && err == nil {
panic("search failed but returned no error")
} }
if c.session != nil { })
c.nodeID = crypto.GetNodeID(&c.session.theirPermPub) <-done
for i := range c.nodeMask { if c.session == nil && err == nil {
c.nodeMask[i] = 0xFF panic("search failed but returned no error")
}
c.session.conn = c
}
return err
} else {
return errors.New("search already exists")
} }
return nil if c.session != nil {
c.nodeID = crypto.GetNodeID(&c.session.theirPermPub)
for i := range c.nodeMask {
c.nodeMask[i] = 0xFF
}
}
return err
} }
// Used in session keep-alive traffic // Used in session keep-alive traffic