mirror of
https://github.com/lightningnetwork/lnd.git
synced 2026-08-13 12:32:48 +02:00
The channelLink.Stop() teardown had an inverted ordering that could cause a permanent deadlock of the invoice registry under concurrent peer disconnect. The previous order was: 1. HodlUnsubscribeAll -- removes subscriptions 2. hodlQueue.Stop() -- kills the queue's internal goroutine 3. cg.Quit() -- signals htlcManager to stop 4. cg.WgWait() -- waits for htlcManager to exit The race window between steps 2 and 4 left htlcManager alive. A RevokeAndAck arriving during that window could drive processRemoteAdds → processExitHop → NotifyExitHopHtlc, registering a new hodl subscription backed by a dead hodlQueue (ChanIn() has no reader). Any subsequent call to notifyHodlSubscribers (e.g. MPP auto-release timer, expiry watcher, or explicit settle/cancel) would then block indefinitely on the unbuffered ChanIn(), holding hodlSubscriptionsMux. Concurrent NotifyExitHopHtlc calls waiting for that lock, plus callers holding the invoice-level lock waiting for those, produce a full deadlock of the invoice registry with no recovery path short of a daemon restart. The fix is to stop htlcManager before touching the hodl subscription state. htlcManager is the sole caller of NotifyExitHopHtlc, so once cg.WgWait() returns no new subscriptions can be registered, making HodlUnsubscribeAll and hodlQueue.Stop() race-free. |
||
|---|---|---|
| .. | ||
| hodl | ||
| hop | ||
| testdata | ||
| circuit.go | ||
| circuit_map.go | ||
| circuit_map_test.go | ||
| circuit_test.go | ||
| decayedlog.go | ||
| decayedlog_test.go | ||
| failure.go | ||
| failure_detail.go | ||
| failure_test.go | ||
| held_htlc_set.go | ||
| held_htlc_set_test.go | ||
| htlcnotifier.go | ||
| interceptable_switch.go | ||
| interfaces.go | ||
| link.go | ||
| link_isolated_test.go | ||
| link_test.go | ||
| linkfailure.go | ||
| log.go | ||
| mailbox.go | ||
| mailbox_test.go | ||
| mock.go | ||
| packet.go | ||
| payment_result.go | ||
| payment_result_test.go | ||
| quiescer.go | ||
| quiescer_test.go | ||
| resolution_store.go | ||
| resolution_store_test.go | ||
| sequencer.go | ||
| switch.go | ||
| switch_test.go | ||
| test_utils.go | ||