From fcafa0baa53a5e0db69100c05da04c61d4810768 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Thu, 16 Jan 2020 13:10:15 +0100 Subject: [PATCH] p2p: wait for listener goroutines on shutdown (#20569) * p2p: wait for goroutine exit, fixes #20558 * p2p: wait for all slots on exit Co-authored-by: Martin Holst Swende --- p2p/server.go | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/p2p/server.go b/p2p/server.go index 9b9effaf6c..9242961764 100644 --- a/p2p/server.go +++ b/p2p/server.go @@ -864,9 +864,9 @@ func (srv *Server) maxDialedConns() int { // listenLoop runs in its own goroutine and accepts // inbound connections. func (srv *Server) listenLoop() { - defer srv.loopWG.Done() srv.log.Debug("TCP listener up", "addr", srv.listener.Addr()) + // The slots channel limits accepts of new connections. tokens := defaultMaxPendingPeers if srv.MaxPendingPeers > 0 { tokens = srv.MaxPendingPeers @@ -876,6 +876,15 @@ func (srv *Server) listenLoop() { slots <- struct{}{} } + // Wait for slots to be returned on exit. This ensures all connection goroutines + // are down before listenLoop returns. + defer srv.loopWG.Done() + defer func() { + for i := 0; i < cap(slots); i++ { + <-slots + } + }() + for { // Wait for a free slot before accepting. <-slots @@ -891,6 +900,7 @@ func (srv *Server) listenLoop() { continue } else if err != nil { srv.log.Debug("Read error", "err", err) + slots <- struct{}{} return } break