htlcswitch: fix possible deadlock bug in packetQueue
This commit fixes a possible deadlock within the packetQueue that could be caused by the following circular waiting dependency: packetCoordinator woken up, grabs lock, queue isn’t empty, attempts to send packet to link (lock still held) -> channelLink has commitment overflow, attempts to add new item to packet queue, in AddPkt grabs Lock -> circular wait. We avoid this scenario by *not* holding the lock within the packetCoordinator when we attempt to send a new packet to the switch. Instead, we release the lock before the second select statement in the main processing loop.
This commit is contained in:
parent
2c36051a52
commit
97e730cf51
@ -107,12 +107,15 @@ func (p *packetQueue) packetCoordinator() {
|
||||
|
||||
nextPkt := p.queue[0]
|
||||
|
||||
p.queueCond.L.Unlock()
|
||||
|
||||
// If there aren't any further messages to sent (or the link
|
||||
// didn't immediately read our message), then we'll block and
|
||||
// wait for a new message to be sent into the overflow queue,
|
||||
// or for the link's htlcForwarder to wake up.
|
||||
select {
|
||||
case <-p.freeSlots:
|
||||
|
||||
select {
|
||||
case p.outgoingPkts <- nextPkt:
|
||||
// Pop the item off the front of the queue and
|
||||
@ -120,22 +123,20 @@ func (p *packetQueue) packetCoordinator() {
|
||||
// the head pointer. This will set us up for
|
||||
// the next iteration. If the queue is empty
|
||||
// at this point, then we'll block at the top.
|
||||
p.queueCond.L.Lock()
|
||||
p.queue[0] = nil
|
||||
p.queue = p.queue[1:]
|
||||
p.queueCond.L.Unlock()
|
||||
atomic.AddInt32(&p.queueLen, -1)
|
||||
case <-p.quit:
|
||||
p.queueCond.L.Unlock()
|
||||
return
|
||||
}
|
||||
|
||||
case <-p.quit:
|
||||
p.queueCond.L.Unlock()
|
||||
return
|
||||
|
||||
default:
|
||||
}
|
||||
|
||||
p.queueCond.L.Unlock()
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user