From 391d5e4a014c28e94329fb5dca3b475565ded613 Mon Sep 17 00:00:00 2001 From: Jonathan Gillham Date: Wed, 6 Apr 2016 19:20:01 +0100 Subject: [PATCH] server: Stop main loop from blocking when RPC server is not running. When the RPC server is not running a buffered transaction notification channel fills and eventually blocks. This commit ensures that the channel continues to be drained irrespective of the RPC server status. --- server.go | 46 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 37 insertions(+), 9 deletions(-) diff --git a/server.go b/server.go index 82aae218..0156ff59 100644 --- a/server.go +++ b/server.go @@ -1954,14 +1954,10 @@ func (s *server) UpdatePeerHeights(latestBlkSha *wire.ShaHash, latestHeight int3 } } -// rebroadcastHandler keeps track of user submitted inventories that we have -// sent out but have not yet made it into a block. We periodically rebroadcast -// them in case our peers restarted or otherwise lost track of them. -func (s *server) rebroadcastHandler() { - // Wait 5 min before first tx rebroadcast. - timer := time.NewTimer(5 * time.Minute) - pendingInvs := make(map[wire.InvVect]interface{}) - +// relayTransactionsHandler relays transactions sent on relayNtfnChan to other +// peers and to the RPC infrastructure if necessary. It must be run as a +// goroutine. +func (s *server) relayTransactionsHandler() { out: for { select { @@ -1976,9 +1972,38 @@ out: // Potentially notify any getblocktemplate long poll clients // about stale block templates due to the new transaction. - s.rpcServer.gbtWorkState.NotifyMempoolTx(s.txMemPool.LastUpdated()) + s.rpcServer.gbtWorkState.NotifyMempoolTx( + s.txMemPool.LastUpdated()) } + case <-s.quit: + break out + } + } + + // Drain channels before exiting so nothing is left waiting around to send. +cleanup: + for { + select { + case <-s.relayNtfnChan: + default: + break cleanup + } + } + s.wg.Done() +} + +// rebroadcastHandler keeps track of user submitted inventories that we have +// sent out but have not yet made it into a block. We periodically rebroadcast +// them in case our peers restarted or otherwise lost track of them. +func (s *server) rebroadcastHandler() { + // Wait 5 min before first tx rebroadcast. + timer := time.NewTimer(5 * time.Minute) + pendingInvs := make(map[wire.InvVect]interface{}) + +out: + for { + select { case riv := <-s.modifyRebroadcastInv: switch msg := riv.(type) { // Incoming InvVects are added to our map of RPC txs. @@ -2047,6 +2072,9 @@ func (s *server) Start() { s.wg.Add(1) go s.peerHandler() + s.wg.Add(1) + go s.relayTransactionsHandler() + if s.nat != nil { s.wg.Add(1) go s.upnpUpdateThread()