From c673d76979c8ad2f70ac3012489d42f04a318635 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Mon, 2 Jun 2014 16:10:33 -0500 Subject: [PATCH] Fix case where block mgr could hang on shutdown. This commit resolves an issue where it was possible the block manager could hang on shutdown due to inventory rebroadcasting. In particular, it adds checks to prevent modification of the of rebroadcast inventory during shutdown and adds a drain on the channel to ensure any outstanding messages are discarded. Found by @dajohi who also provided some of the code. --- server.go | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/server.go b/server.go index 906193a1..d1751543 100644 --- a/server.go +++ b/server.go @@ -118,12 +118,22 @@ func randomUint16Number(max uint16) uint16 { // AddRebroadcastInventory adds 'iv' to the list of inventories to be // rebroadcasted at random intervals until they show up in a block. func (s *server) AddRebroadcastInventory(iv *btcwire.InvVect) { + // Ignore if shutting down. + if atomic.LoadInt32(&s.shutdown) != 0 { + return + } + s.modifyRebroadcastInv <- broadcastInventoryAdd(iv) } // RemoveRebroadcastInventory removes 'iv' from the list of items to be // rebroadcasted if present. func (s *server) RemoveRebroadcastInventory(iv *btcwire.InvVect) { + // Ignore if shutting down. + if atomic.LoadInt32(&s.shutdown) != 0 { + return + } + s.modifyRebroadcastInv <- broadcastInventoryDel(iv) } @@ -802,6 +812,16 @@ out: timer.Stop() + // Drain channels before exiting so nothing is left waiting around + // to send. +cleanup: + for { + select { + case <-s.modifyRebroadcastInv: + default: + break cleanup + } + } s.wg.Done() }