Skip to content

Fix nil pointer panic in Deliverer.Stop() during leader election#5420

Open
Ady0333 wants to merge 1 commit intohyperledger:mainfrom
Ady0333:fix/deliverer-stop-nil-blockReceiver
Open

Fix nil pointer panic in Deliverer.Stop() during leader election#5420
Ady0333 wants to merge 1 commit intohyperledger:mainfrom
Ady0333:fix/deliverer-stop-nil-blockReceiver

Conversation

@Ady0333
Copy link
Contributor

@Ady0333 Ady0333 commented Mar 16, 2026

Type of change

  • Bug fix

Description

Fixed a nil pointer dereference that crashes the peer when Stop() is called before a successful orderer connection.

The issue occurs during normal gossip leader election when the orderer is unreachable. When a peer renounces leadership, it calls StopDeliverForChannel()Deliverer.Stop(), which unconditionally dereferences d.blockReceiver.Stop(). However, blockReceiver is only initialized inside DeliverBlocks() after a successful gRPC connection to an orderer. If Stop() is called before that connection succeeds, the peer panics and crashes.

I've added a nil check before calling blockReceiver.Stop() in both Deliverer.Stop() and BFTDeliverer.Stop(). The fix is safe because close(d.DoneC) already signals DeliverBlocks() to exit, and the mutex protects against races.

I've also added regression tests that reproduce the crash scenario - calling Stop() before DeliverBlocks() starts. These tests panic without the fix and pass with it.


Additional details

This affects production networks during:

  • Orderer maintenance windows
  • Network partitions
  • Rapid gossip leader election changes
  • Peers joining channels when orderers are unreachable

The crash is not a shutdown-only bug - it happens during normal operation when leadership flips while orderers are down.


Related issues

Fixes the peer crash during gossip leader election when orderers are unreachable.


Fixed a critical nil pointer dereference in the delivery service that caused peer crashes during gossip leader election when orderers were unreachable. The bug affected both CFT (etcdraft) and BFT consensus modes. When a peer renounced gossip leadership while unable to connect to orderers, the delivery service's Stop() method would panic, crashing the entire peer process and disrupting all channels on that peer.

Deliverer.Stop() and BFTDeliverer.Stop() unconditionally called
d.blockReceiver.Stop() without a nil guard. blockReceiver is only
set inside DeliverBlocks() after a successful orderer connection,
so calling Stop() before that connection succeeds (e.g. when a peer
renounces gossip leadership while the orderer is unreachable) caused
a nil pointer dereference and panicked the peer.

Add a nil check before calling blockReceiver.Stop() in both paths.
Add regression tests that call Stop() before DeliverBlocks() is
ever started to confirm no panic occurs.

Signed-off-by: Ady0333 <adityashinde1525@gmail.com>
@Ady0333 Ady0333 requested a review from a team as a code owner March 16, 2026 06:16
@Ady0333
Copy link
Contributor Author

Ady0333 commented Mar 16, 2026

@C0rWin and @pfi79 , Please review this pr once you have time! Happy to make any changes if needed.

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.

1 participant