From f7e2db9687b7b159d36ecee9f6d1eca6b305d793 Mon Sep 17 00:00:00 2001 From: Eugene Siegel Date: Tue, 7 Nov 2023 11:17:27 -0500 Subject: [PATCH 1/2] peer: send messages in Start via writeMessage to bypass writeHandler Without this the following could happen: * InboundPeerConnected is called while we already have an inbound connection with the peer. This calls removePeer which calls Disconnect. * If the peer is starting up in Start, it may be sending messages synchronously via SendMessage(true, ...). This eventually calls the writeMessage function which will exit if disconnect is set to 1. * Since Disconnect was called, disconnect will be 1 and writeMessage will exit, causing writeHandler to exit. * If there is more than 1 message being sent, later messages will queue in queueHandler but be unable to get into sendQueue as the writeHandler goroutine has exited. * The synchronous sends will be waiting on the errChan indefinitely and startReady will never get closed meaning Disconnect will never proceed. The end result is that the server's mutex will be held until shutdown. Avoid this by using writeMessage to bypass the writeHandler goroutine. --- peer/brontide.go | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/peer/brontide.go b/peer/brontide.go index 1e840cc7d..1810f44c2 100644 --- a/peer/brontide.go +++ b/peer/brontide.go @@ -655,9 +655,15 @@ func (p *Brontide) Start() error { if len(msgs) > 0 { p.log.Infof("Sending %d channel sync messages to peer after "+ "loading active channels", len(msgs)) - if err := p.SendMessage(true, msgs...); err != nil { - p.log.Warnf("Failed sending channel sync "+ - "messages to peer: %v", err) + + // Send the messages directly via writeMessage and bypass the + // writeHandler goroutine to avoid cases where writeHandler + // may exit and cause a deadlock. + for _, msg := range msgs { + if err := p.writeMessage(msg); err != nil { + return fmt.Errorf("unable to send reestablish"+ + "msg: %v", err) + } } } @@ -2020,11 +2026,6 @@ func (p *Brontide) logWireMessage(msg lnwire.Message, read bool) { // with a nil message iff a timeout error is returned. This will continue to // flush the pending message to the wire. func (p *Brontide) writeMessage(msg lnwire.Message) error { - // Simply exit if we're shutting down. - if atomic.LoadInt32(&p.disconnect) != 0 { - return lnpeer.ErrPeerExiting - } - // Only log the message on the first attempt. if msg != nil { p.logWireMessage(msg, false) From 8e8923c251a2eef6a84913c4a59a01a416b8c01a Mon Sep 17 00:00:00 2001 From: Eugene Siegel Date: Wed, 8 Nov 2023 09:10:27 -0500 Subject: [PATCH 2/2] release-notes: update for 0.17.1 --- docs/release-notes/release-notes-0.17.1.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/release-notes/release-notes-0.17.1.md b/docs/release-notes/release-notes-0.17.1.md index fbb2ef89f..bfb4e5ce7 100644 --- a/docs/release-notes/release-notes-0.17.1.md +++ b/docs/release-notes/release-notes-0.17.1.md @@ -19,6 +19,8 @@ # Bug Fixes +* A bug that caused certain API calls to hang [has been fixed](https://github.com/lightningnetwork/lnd/pull/8158). + * [LND now sets the `BADONION`](https://github.com/lightningnetwork/lnd/pull/7937) bit when sending `update_fail_malformed_htlc`. This avoids a force close with other implementations.