[lxc-devel] [lxd/master] Prevent event listeners from lying around even after Disconnect()

freeekanayaka on Github lxc-bot at linuxcontainers.org
Wed Oct 17 08:41:27 UTC 2018


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 1053 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20181017/b081dff5/attachment.bin>
-------------- next part --------------
From 2024096d4b906ab3f044e40a6794eb6a3ba0f5e1 Mon Sep 17 00:00:00 2001
From: Free Ekanayaka <free.ekanayaka at canonical.com>
Date: Wed, 17 Oct 2018 10:34:36 +0200
Subject: [PATCH] Prevent event listeners from lying around even after
 Disconnect()

Currently the EventListener.Disconnect() method just removes the listener from
the list, but does not close the underlying websocket connection (since there
might be other listeners). However if the list of event listeners has become
empty, the current logic won't close the connection since it's blocked on
conn.ReadMessage().

This change separates the job of fetching events via conn.ReadMessage() from the
job of monitoring if all listeners are gone.

Signed-off-by: Free Ekanayaka <free.ekanayaka at canonical.com>
---
 client/lxd_events.go | 20 +++++++++++++++++++-
 1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/client/lxd_events.go b/client/lxd_events.go
index 9df4f31f4d..15fc35cb6f 100644
--- a/client/lxd_events.go
+++ b/client/lxd_events.go
@@ -3,6 +3,7 @@ package lxd
 import (
 	"encoding/json"
 	"fmt"
+	"time"
 
 	"github.com/lxc/lxd/shared"
 )
@@ -39,9 +40,17 @@ func (r *ProtocolLXD) GetEvents() (*EventListener, error) {
 	// Add the listener
 	r.eventListeners = append(r.eventListeners, &listener)
 
-	// And spawn the listener
+	// Spawn a watcher that will close the websocket connection after all
+	// listeners are gone.
+	stopCh := make(chan struct{}, 0)
 	go func() {
 		for {
+			select {
+			case <-time.After(time.Minute):
+			case <-stopCh:
+				break
+			}
+
 			r.eventListenersLock.Lock()
 			if len(r.eventListeners) == 0 {
 				// We don't need the connection anymore, disconnect
@@ -52,7 +61,12 @@ func (r *ProtocolLXD) GetEvents() (*EventListener, error) {
 				break
 			}
 			r.eventListenersLock.Unlock()
+		}
+	}()
 
+	// Spawn the listener
+	go func() {
+		for {
 			_, data, err := conn.ReadMessage()
 			if err != nil {
 				// Prevent anything else from interacting with the listeners
@@ -68,6 +82,10 @@ func (r *ProtocolLXD) GetEvents() (*EventListener, error) {
 
 				// And remove them all from the list
 				r.eventListeners = []*EventListener{}
+
+				conn.Close()
+				close(stopCh)
+
 				return
 			}
 


More information about the lxc-devel mailing list