From 2e055cf6301e983c23cd1565ef34b7097da222f5 Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Sun, 3 May 2020 21:30:16 -0700 Subject: [PATCH] Unsubscribe any open event listeners when deleting a server --- router/router_server.go | 3 +++ server/events.go | 30 +++++++++++++++++++++++------- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/router/router_server.go b/router/router_server.go index c93c8e7..0412d7d 100644 --- a/router/router_server.go +++ b/router/router_server.go @@ -178,6 +178,9 @@ func deleteServer(c *gin.Context) { zap.S().Warnw("failed to delete server archive during deletion process", zap.String("server", s.Uuid), zap.Error(err)) } + // Unsubscribe all of the event listeners. + s.Events().UnsubscribeAll() + // Destroy the environment; in Docker this will handle a running container and // forcibly terminate it before removing the container, so we do not need to handle // that here. diff --git a/server/events.go b/server/events.go index c22ebb1..5ea6ceb 100644 --- a/server/events.go +++ b/server/events.go @@ -23,8 +23,9 @@ type Event struct { } type EventBus struct { + sync.RWMutex + subscribers map[string][]chan Event - mu sync.Mutex } // Returns the server's emitter instance. @@ -40,8 +41,8 @@ func (s *Server) Events() *EventBus { // Publish data to a given topic. func (e *EventBus) Publish(topic string, data string) { - e.mu.Lock() - defer e.mu.Unlock() + e.RLock() + defer e.RUnlock() t := topic // Some of our topics for the socket support passing a more specific namespace, @@ -79,8 +80,8 @@ func (e *EventBus) PublishJson(topic string, data interface{}) error { // Subscribe to an emitter topic using a channel. func (e *EventBus) Subscribe(topic string, ch chan Event) { - e.mu.Lock() - defer e.mu.Unlock() + e.Lock() + defer e.Unlock() if p, ok := e.subscribers[topic]; ok { e.subscribers[topic] = append(p, ch) @@ -91,8 +92,8 @@ func (e *EventBus) Subscribe(topic string, ch chan Event) { // Unsubscribe a channel from a topic. func (e *EventBus) Unsubscribe(topic string, ch chan Event) { - e.mu.Lock() - defer e.mu.Unlock() + e.Lock() + defer e.Unlock() if _, ok := e.subscribers[topic]; ok { for i := range e.subscribers[topic] { @@ -102,3 +103,18 @@ func (e *EventBus) Unsubscribe(topic string, ch chan Event) { } } } + +// Removes all of the event listeners for the server. This is used when a server +// is being deleted to avoid a bunch of de-reference errors cropping up. Obviously +// should also check elsewhere and handle a server reference going nil, but this +// won't hurt. +func (e *EventBus) UnsubscribeAll() { + e.Lock() + defer e.Unlock() + + // Loop over all of the subscribers and just remove all of the events + // for them. + for t := range e.subscribers { + e.subscribers[t] = make([]chan Event, 0) + } +}