Skip to content

fix(electrum): handle shutdown race in acceptor thread#209

Open
EddieHouston wants to merge 1 commit intoBlockstream:new-indexfrom
EddieHouston:fix/electrum-acceptor-shutdown-race
Open

fix(electrum): handle shutdown race in acceptor thread#209
EddieHouston wants to merge 1 commit intoBlockstream:new-indexfrom
EddieHouston:fix/electrum-acceptor-shutdown-race

Conversation

@EddieHouston
Copy link
Copy Markdown
Collaborator

@EddieHouston EddieHouston commented Apr 20, 2026

Summary

Fixes a shutdown race we saw in the Electrum RPC server that caused the
acceptor thread to panic with "send failed" when a TCP connection
arrived at the exact moment the server was tearing down.

Root Cause

The acceptor thread and the rpc thread communicate via a channel:

  • The acceptor thread calls listener.accept() in a loop and sends
    each new connection as Some((stream, addr)) to the rpc thread
  • On shutdown, the notification thread sends None into the channel
  • The rpc thread receives None, exits its while let Some(...) loop,
    and drops the channel receiver
  • If the acceptor thread accepts a new TCP connection at this moment
    and calls send(Some(...)), the send fails because the receiver is
    already gone → .expect("send failed")panic

This is a normal production scenario: on a live Electrum server with
active wallet connections, a client connecting during shutdown is
expected.

@EddieHouston EddieHouston self-assigned this Apr 20, 2026
@philippem
Copy link
Copy Markdown
Collaborator

is there a way to reliably reproduce this locally/in test?

Copy link
Copy Markdown
Collaborator

@shesek shesek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The changes makes sense and seem correct. Agreed that it would be great to have a test/reproduction, but I see that it can be kind of tricky.

@RCasatta
Copy link
Copy Markdown
Collaborator

LGTM

  The 'acceptor' thread panicked with 'send failed' when a TCP connection
  arrived at the exact moment the server was shutting down. The 'rpc'
  thread drops the channel receiver upon receiving the Exit notification,
  leaving the 'acceptor' thread's next send() with no receiver.

  - Break cleanly from the acceptor loop when the receiver is dropped
  - Replace unwrap() with a warn! log in the notification thread for the
    symmetric case where the acceptor has already exited before Exit fires
@EddieHouston EddieHouston force-pushed the fix/electrum-acceptor-shutdown-race branch from e8380f0 to e4b15a4 Compare April 21, 2026 16:23
@EddieHouston
Copy link
Copy Markdown
Collaborator Author

is there a way to reliably reproduce this locally/in test?

Thought about that... it is tricky as it is such a narrow window between rpc thread processing Exit and the acceptor thread's next send(). So "reliably test" is the key... not really. It's a fairly straight forward fix without a downside I can see.

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.

4 participants