Skip to content

lightningd: don't ask the Bitcoin backend anything once we're shutting down - #9720

Open
nepet wants to merge 1 commit into
ElementsProject:masterfrom
nepet:shutdown-bcli-segfault
Open

nepet wants to merge 1 commit into
ElementsProject:masterfrom
nepet:shutdown-bcli-segfault

Conversation

@nepet

@nepet nepet commented Nov 8, 2026

Copy link
Copy Markdown
Member

Checklist

Before submitting the PR, ensure the following tasks are completed. If an item is not applicable to your PR, please mark it as checked:

  • The changelog has been updated in the relevant commit(s) according to the guidelines.
  • Tests have been added or modified to reflect the changes.
  • Documentation has been reviewed and updated as needed.
  • Related issues have been listed and linked, including any that this PR closes.
  • Important All PRs must consider how to reverse any persistent changes for tools/lightning-downgrade

Fixes #9719.

At shutdown, the backend plugin (bcli) can exit and be freed while bitcoind->pluginsmap still points at it. #8687 stopped gossipd's get_txout() from using it at that point. A channel that fails during shutdown uses it too: drop_to_chain() broadcasts the commitment tx through bitcoin_plugin_send(), and lightningd crashes in plugin_send() (backtrace in #9719).

With this PR, bitcoin_plugin_send() sends nothing once LD_STATE_SHUTDOWN is set, and estimatefees, which called plugin_request_send() directly, goes through it too. Callers get no callback. That's fine at shutdown: stop_topology() already drops the answers to topology's requests. A close we don't broadcast is broadcast on restart by resend_closing_transactions(), because the channel is already AWAITING_UNILATERAL in the db. The check #8687 added in get_txout() stays, and now only saves starting the request.

One behaviour change: a plugin that uses the backend from its shutdown handler, over an RPC connection it already has open, gets no answer and is killed after 30 seconds. Today that works only if bcli hasn't exited yet; otherwise it reads freed memory.

The new test makes a peer that forgot the channel reconnect while lightningd waits for a plugin that ignores shutdown. With this PR, lightningd fails the channel, doesn't broadcast, exits cleanly, and broadcasts the close after the restart. On master it aborts in plugin_send().

It doesn't stop connectd from reconnecting during shutdown, which is how a channeld gets started after subd_shutdown_nonglobals(). See #9719.

…g down

bitcoind->pluginsmap keeps a pointer to the backend plugin for each of
its methods.  When the plugin exits during shutdown, bitcoin_destructor()
lets it go, but the map still points at the freed plugin, so anything
that asks the backend after that uses freed memory.

0b8239f ("lightningd: fix access to bcli plugin once it's freed.")
stopped gossipd's get_txout from doing that.  A channel that fails
during shutdown does it too, through drop_to_chain():

    lightningd: FATAL SIGNAL 11 (version v26.06.9)
    plugin_send <- plugin_request_send <- bitcoin_plugin_send
      <- bitcoind_sendrawtx_ <- broadcast_tx_ <- sign_and_send_last
      <- drop_to_chain <- channel_fail_perm <- channel_fail_permanent
      <- channel_errmsg <- channel_control_errmsg <- handle_peer_error
      <- sd_msg_read <- ... <- io_loop <- shutdown_plugins <- main

There, connectd reconnected to the peer while shutdown_plugins() waited
for the plugins to exit, lightningd started channeld for the channel,
and the peer answered the reestablish with an error.  So lightningd
failed the channel and broadcast its commitment tx through the freed
bcli.

Check in bitcoin_plugin_send() instead, so no caller can get there, and
send estimatefees through it too.  Not broadcasting the close is safe:
the channel is AWAITING_UNILATERAL in the db, and
resend_closing_transactions() broadcasts it on restart.

Fixes: ElementsProject#9719
Changelog-Fixed: lightningd: no longer crashes when a channel is force-closed while plugins shut down (e.g. a peer reconnects and sends an error); the close is broadcast on restart.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

lightningd crashes at shutdown when a channel fails after bcli has exited

1 participant