invoices: fix deadlock in hodl subscription handling

This commit is contained in:
Andras Banki-Horvath
2022-05-31 17:31:55 +02:00
parent cc8a1f0d2b
commit 98f39deb38

View File

@@ -124,6 +124,11 @@ type InvoiceRegistry struct {
// carried. // carried.
invoiceEvents chan *invoiceEvent invoiceEvents chan *invoiceEvent
// hodlSubscriptionsMux locks the hodlSubscriptions and
// hodlReverseSubscriptions. Using a separate mutex for these maps is
// necessary to avoid deadlocks in the registry when processing invoice
// events.
hodlSubscriptionsMux sync.RWMutex
// subscriptions is a map from a circuit key to a list of subscribers. // subscriptions is a map from a circuit key to a list of subscribers.
// It is used for efficient notification of links. // It is used for efficient notification of links.
hodlSubscriptions map[channeldb.CircuitKey]map[chan<- interface{}]struct{} hodlSubscriptions map[channeldb.CircuitKey]map[chan<- interface{}]struct{}
@@ -641,9 +646,6 @@ func (i *InvoiceRegistry) startHtlcTimer(invoiceRef channeldb.InvoiceRef,
func (i *InvoiceRegistry) cancelSingleHtlc(invoiceRef channeldb.InvoiceRef, func (i *InvoiceRegistry) cancelSingleHtlc(invoiceRef channeldb.InvoiceRef,
key channeldb.CircuitKey, result FailResolutionResult) error { key channeldb.CircuitKey, result FailResolutionResult) error {
i.Lock()
defer i.Unlock()
updateInvoice := func(invoice *channeldb.Invoice) ( updateInvoice := func(invoice *channeldb.Invoice) (
*channeldb.InvoiceUpdateDesc, error) { *channeldb.InvoiceUpdateDesc, error) {
@@ -1684,6 +1686,9 @@ func (i *InvoiceRegistry) SubscribeSingleInvoice(
// notifyHodlSubscribers sends out the htlc resolution to all current // notifyHodlSubscribers sends out the htlc resolution to all current
// subscribers. // subscribers.
func (i *InvoiceRegistry) notifyHodlSubscribers(htlcResolution HtlcResolution) { func (i *InvoiceRegistry) notifyHodlSubscribers(htlcResolution HtlcResolution) {
i.hodlSubscriptionsMux.Lock()
defer i.hodlSubscriptionsMux.Unlock()
subscribers, ok := i.hodlSubscriptions[htlcResolution.CircuitKey()] subscribers, ok := i.hodlSubscriptions[htlcResolution.CircuitKey()]
if !ok { if !ok {
return return
@@ -1712,6 +1717,9 @@ func (i *InvoiceRegistry) notifyHodlSubscribers(htlcResolution HtlcResolution) {
func (i *InvoiceRegistry) hodlSubscribe(subscriber chan<- interface{}, func (i *InvoiceRegistry) hodlSubscribe(subscriber chan<- interface{},
circuitKey channeldb.CircuitKey) { circuitKey channeldb.CircuitKey) {
i.hodlSubscriptionsMux.Lock()
defer i.hodlSubscriptionsMux.Unlock()
log.Debugf("Hodl subscribe for %v", circuitKey) log.Debugf("Hodl subscribe for %v", circuitKey)
subscriptions, ok := i.hodlSubscriptions[circuitKey] subscriptions, ok := i.hodlSubscriptions[circuitKey]
@@ -1731,8 +1739,8 @@ func (i *InvoiceRegistry) hodlSubscribe(subscriber chan<- interface{},
// HodlUnsubscribeAll cancels the subscription. // HodlUnsubscribeAll cancels the subscription.
func (i *InvoiceRegistry) HodlUnsubscribeAll(subscriber chan<- interface{}) { func (i *InvoiceRegistry) HodlUnsubscribeAll(subscriber chan<- interface{}) {
i.Lock() i.hodlSubscriptionsMux.Lock()
defer i.Unlock() defer i.hodlSubscriptionsMux.Unlock()
hashes := i.hodlReverseSubscriptions[subscriber] hashes := i.hodlReverseSubscriptions[subscriber]
for hash := range hashes { for hash := range hashes {