From 5c45d52ab6069f3e1439fba275d035e984a9af85 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Sun, 25 Jun 2017 13:31:41 +0100 Subject: [PATCH] routing: wait for topology clients to fully exit before closing ntfn chan This commit fixes a send on closed channel panic by adding additional synchronization when cancelling the notifications for a particular topology client. We now ensure that all goroutines belonging to a particular topology client exit fully before we close the notification channel in order to avoid a panic. --- routing/notifications.go | 7 +++++++ routing/router.go | 3 +++ 2 files changed, 10 insertions(+) diff --git a/routing/notifications.go b/routing/notifications.go index 51e1a7d7..dd0e24e9 100644 --- a/routing/notifications.go +++ b/routing/notifications.go @@ -3,6 +3,7 @@ package routing import ( "fmt" "net" + "sync" "sync/atomic" "github.com/davecgh/go-spew/spew" @@ -101,6 +102,8 @@ type topologyClient struct { // exit is a channel that is used internally by the channel router to // cancel any active un-consumed goroutine notifications. exit chan struct{} + + wg sync.WaitGroup } // notifyTopologyChange notifies all registered clients of a new change in @@ -116,7 +119,11 @@ func (r *ChannelRouter) notifyTopologyChange(topologyDiff *TopologyChange) { } for _, client := range r.topologyClients { + client.wg.Add(1) + go func(c topologyClient) { + defer c.wg.Done() + select { // In this case we'll try to send the notification diff --git a/routing/router.go b/routing/router.go index 9717688c..14088d01 100644 --- a/routing/router.go +++ b/routing/router.go @@ -489,7 +489,10 @@ func (r *ChannelRouter) networkHandler() { if ntfnUpdate.cancel { if client, ok := r.topologyClients[ntfnUpdate.clientID]; ok { delete(r.topologyClients, clientID) + close(client.exit) + client.wg.Wait() + close(client.ntfnChan) }