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

fix deadlock when running updateTable in the switch

This commit is contained in:
Arceliar 2020-03-29 01:38:32 -05:00
parent d47797088f
commit 15b850be6e

View File

@ -199,7 +199,7 @@ func (t *switchTable) init(core *Core) {
t.queues.bufs = make(map[switchPort]map[string]switch_buffer) t.queues.bufs = make(map[switchPort]map[string]switch_buffer)
t.idle = make(map[switchPort]struct{}) t.idle = make(map[switchPort]struct{})
}) })
t.updateTable() t._updateTable()
} }
func (t *switchTable) reconfigure() { func (t *switchTable) reconfigure() {
@ -250,7 +250,7 @@ func (t *switchTable) cleanRoot() {
t.time = now t.time = now
if t.data.locator.root != t.key { if t.data.locator.root != t.key {
t.data.seq++ t.data.seq++
defer t.updateTable() defer t._updateTable()
t.core.router.reset(nil) t.core.router.reset(nil)
} }
t.data.locator = switchLocator{root: t.key, tstamp: now.Unix()} t.data.locator = switchLocator{root: t.key, tstamp: now.Unix()}
@ -288,7 +288,7 @@ func (t *switchTable) forgetPeer(port switchPort) {
t.mutex.Lock() t.mutex.Lock()
defer t.mutex.Unlock() defer t.mutex.Unlock()
delete(t.data.peers, port) delete(t.data.peers, port)
defer t.updateTable() defer t._updateTable()
if port != t.parent { if port != t.parent {
return return
} }
@ -524,7 +524,7 @@ func (t *switchTable) unlockedHandleMsg(msg *switchMsg, fromPort switchPort, rep
t.core.peers.sendSwitchMsgs(t) t.core.peers.sendSwitchMsgs(t)
} }
if true || doUpdate { if true || doUpdate {
defer t.updateTable() defer t._updateTable()
} }
return return
} }
@ -534,7 +534,7 @@ func (t *switchTable) unlockedHandleMsg(msg *switchMsg, fromPort switchPort, rep
// The rest of these are related to the switch worker // The rest of these are related to the switch worker
// This is called via a sync.Once to update the atomically readable subset of switch information that gets used for routing decisions. // This is called via a sync.Once to update the atomically readable subset of switch information that gets used for routing decisions.
func (t *switchTable) updateTable() { func (t *switchTable) _updateTable() {
// WARNING this should only be called from within t.data.updater.Do() // WARNING this should only be called from within t.data.updater.Do()
// It relies on the sync.Once for synchronization with messages and lookups // It relies on the sync.Once for synchronization with messages and lookups
// TODO use a pre-computed faster lookup table // TODO use a pre-computed faster lookup table
@ -543,8 +543,6 @@ func (t *switchTable) updateTable() {
// Each struct has stores the best port to forward to, and a next coord map // Each struct has stores the best port to forward to, and a next coord map
// Move to struct, then iterate over coord maps until you dead end // Move to struct, then iterate over coord maps until you dead end
// The last port before the dead end should be the closest // The last port before the dead end should be the closest
t.mutex.RLock()
defer t.mutex.RUnlock()
newTable := lookupTable{ newTable := lookupTable{
self: t.data.locator.clone(), self: t.data.locator.clone(),
elems: make(map[switchPort]tableElem, len(t.data.peers)), elems: make(map[switchPort]tableElem, len(t.data.peers)),