From f575ab3cb47c86224dc4d84512f38aa1390459e4 Mon Sep 17 00:00:00 2001 From: mykola2312 <49044616+mykola2312@users.noreply.github.com> Date: Wed, 29 Jan 2025 04:46:03 +0200 Subject: [PATCH] FIX deadlock related to blocking channel sending --- node/lux_node.go | 41 ++++++++++++++++++++++++++++++------- node/lux_node_subscriber.go | 5 +++++ 2 files changed, 39 insertions(+), 7 deletions(-) create mode 100644 node/lux_node_subscriber.go diff --git a/node/lux_node.go b/node/lux_node.go index 29cccca..8532005 100644 --- a/node/lux_node.go +++ b/node/lux_node.go @@ -24,6 +24,9 @@ type LuxNode struct { state LuxNodeState stateLock deadlock.RWMutex + subscribers []LuxNodeSubscriber + stopChan chan bool + genlist net.LuxNonceList dns *LuxDnsServer @@ -31,13 +34,15 @@ type LuxNode struct { func NewLuxNode(nodeKey crypto.LuxKey, ks crypto.LuxKeyStore) LuxNode { return LuxNode{ - nodeId: &nodeKey.Id, - router: net.NewLuxRouter(nodeKey, ks), - running: false, - neighbors: make(map[proto.LuxID]*ipnet.UDPAddr), - state: NewLuxNodeState(), - genlist: net.NewLuxNonceList(), - dns: nil, + nodeId: &nodeKey.Id, + router: net.NewLuxRouter(nodeKey, ks), + running: false, + neighbors: make(map[proto.LuxID]*ipnet.UDPAddr), + state: NewLuxNodeState(), + subscribers: make([]LuxNodeSubscriber, 0), + stopChan: make(chan bool), + genlist: net.NewLuxNonceList(), + dns: nil, } } @@ -85,6 +90,10 @@ func (node *LuxNode) AddNeighbor(id proto.LuxID, udpAddr string) error { return nil } +func (node *LuxNode) AddSubscriber(subscriber LuxNodeSubscriber) { + node.subscribers = append(node.subscribers, subscriber) +} + func (node *LuxNode) AddDnsFrontend(udpListen string) error { if node.dns == nil { node.dns = NewLuxDnsServer(node) @@ -232,11 +241,27 @@ func nodeLoop(node *LuxNode) { } } +// we need to read state from stateChan, or otherwise sending to it +// will block everything and cause deadlock +func subscriberLoop(node *LuxNode) { + for node.running { + select { + case <-node.stopChan: + return + case state := <-node.state.stateChan: + for _, subscriber := range node.subscribers { + subscriber.HandleStateUpdate(state) + } + } + } +} + func (node *LuxNode) Start() { node.router.Start() node.running = true go nodeLoop(node) + go subscriberLoop(node) } func (node *LuxNode) Stop() { @@ -245,6 +270,8 @@ func (node *LuxNode) Stop() { } node.running = false + node.stopChan <- true + node.router.Stop() } diff --git a/node/lux_node_subscriber.go b/node/lux_node_subscriber.go new file mode 100644 index 0000000..ff28532 --- /dev/null +++ b/node/lux_node_subscriber.go @@ -0,0 +1,5 @@ +package node + +type LuxNodeSubscriber interface { + HandleStateUpdate(state LuxHostState) +}