summary refs log tree commit diff
diff options
context:
space:
mode:
authorErik Johnston <erik@matrix.org>2015-06-18 11:36:26 +0100
committerErik Johnston <erik@matrix.org>2015-06-18 11:36:26 +0100
commit050ebccf309916c57c58b67776e66d98fffbff0f (patch)
tree5cc99f3306d8ebf55e74f5f8d231cca0390f706e
parentMerge pull request #185 from matrix-org/erikj/listeners_config (diff)
downloadsynapse-050ebccf309916c57c58b67776e66d98fffbff0f.tar.xz
Fix notifier leak
-rw-r--r--synapse/notifier.py41
1 files changed, 20 insertions, 21 deletions
diff --git a/synapse/notifier.py b/synapse/notifier.py
index 078abfc56d..27c034ed51 100644
--- a/synapse/notifier.py
+++ b/synapse/notifier.py
@@ -308,49 +308,48 @@ class Notifier(object):
         else:
             current_token = user_stream.current_token
 
-        listener = [_NotificationListener(deferred)]
-
-        if timeout and not current_token.is_after(from_token):
-            user_stream.listeners.add(listener[0])
-
+        result = None
         if current_token.is_after(from_token):
             result = yield callback(from_token, current_token)
-        else:
-            result = None
-
-        timer = [None]
 
         if result:
-            user_stream.listeners.discard(listener[0])
             defer.returnValue(result)
-            return
 
         if timeout:
+            timer = [None]
+            listeners = []
             timed_out = [False]
 
+            def notify_listeners():
+                user_stream.listeners.difference_update(listeners)
+                for listener in listeners:
+                    listener.notify(current_token)
+                del listeners[:]
+
             def _timeout_listener():
                 timed_out[0] = True
                 timer[0] = None
-                user_stream.listeners.discard(listener[0])
-                listener[0].notify(current_token)
+                notify_listeners()
 
             # We create multiple notification listeners so we have to manage
             # canceling the timeout ourselves.
             timer[0] = self.clock.call_later(timeout/1000., _timeout_listener)
 
             while not result and not timed_out[0]:
-                new_token = yield deferred
                 deferred = defer.Deferred()
-                listener[0] = _NotificationListener(deferred)
-                user_stream.listeners.add(listener[0])
+                notify_listeners()
+                listeners.append(_NotificationListener(deferred))
+                user_stream.listeners.update(listeners)
+                new_token = yield deferred
+
                 result = yield callback(current_token, new_token)
                 current_token = new_token
 
-        if timer[0] is not None:
-            try:
-                self.clock.cancel_call_later(timer[0])
-            except:
-                logger.exception("Failed to cancel notifer timer")
+            if timer[0] is not None:
+                try:
+                    self.clock.cancel_call_later(timer[0])
+                except:
+                    logger.exception("Failed to cancel notifer timer")
 
         defer.returnValue(result)