Merge pull request #5941 from bhandras/graph_cache_deadlock

channeldb: avoid locking the graph cache while iterating channels
This commit is contained in:
Olaoluwa Osuntokun 2021-11-08 17:51:07 -08:00 committed by GitHub
commit e7e3adeb98
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 30 additions and 5 deletions

View File

@ -401,10 +401,9 @@ func (c *GraphCache) UpdateChannel(info *ChannelEdgeInfo) {
}
}
// ForEachChannel invokes the given callback for each channel of the given node.
func (c *GraphCache) ForEachChannel(node route.Vertex,
cb func(channel *DirectedChannel) error) error {
// getChannels returns a copy of the passed node's channels or nil if there
// isn't any.
func (c *GraphCache) getChannels(node route.Vertex) []*DirectedChannel {
c.mtx.RLock()
defer c.mtx.RUnlock()
@ -428,6 +427,8 @@ func (c *GraphCache) ForEachChannel(node route.Vertex,
return node
}
i := 0
channelsCopy := make([]*DirectedChannel, len(channels))
for _, channel := range channels {
// We need to copy the channel and policy to avoid it being
// updated in the cache if the path finding algorithm sets
@ -439,9 +440,30 @@ func (c *GraphCache) ForEachChannel(node route.Vertex,
channelCopy.InPolicy.ToNodeFeatures = features
}
if err := cb(channelCopy); err != nil {
channelsCopy[i] = channelCopy
i++
}
return channelsCopy
}
// ForEachChannel invokes the given callback for each channel of the given node.
func (c *GraphCache) ForEachChannel(node route.Vertex,
cb func(channel *DirectedChannel) error) error {
// Obtain a copy of the node's channels. We need do this in order to
// avoid deadlocks caused by interaction with the graph cache, channel
// state and the graph database from multiple goroutines. This snapshot
// is only used for path finding where being stale is acceptable since
// the real world graph and our representation may always become
// slightly out of sync for a short time and the actual channel state
// is stored separately.
channels := c.getChannels(node)
for _, channel := range channels {
if err := cb(channel); err != nil {
return err
}
}
return nil

View File

@ -618,6 +618,9 @@ messages directly. There is no routing/path finding involved.
* [Fixed an issue with external listeners and the `--noseedbackup` development
flag](https://github.com/lightningnetwork/lnd/pull/5930).
* [Fix deadlock when using the graph cache](
https://github.com/lightningnetwork/lnd/pull/5941)
## Documentation
The [code contribution guidelines have been updated to mention the new