summary refs log tree commit diff
diff options
context:
space:
mode:
authorRichard van der Hoff <richard@matrix.org>2017-09-20 01:32:42 +0100
committerRichard van der Hoff <richard@matrix.org>2017-09-20 01:32:42 +0100
commitabdefb8a01bf67b3055e9fbe52bb11a02ffd8d9a (patch)
tree5da0013e4c6d425cbf45980f76c13540ca9d89f2
parentAdd some comments to _start_key_lookups (diff)
downloadsynapse-abdefb8a01bf67b3055e9fbe52bb11a02ffd8d9a.tar.xz
Fix potential race in _start_key_lookups
If the verify_request.deferred has already completed, then `remove_deferreds`
will be called immediately. It therefore might resolve the server_to_deferred
deferred while there are still other requests for that server in flight.

To avoid that, we should build the complete list of requests, and *then* add the
callbacks.
-rw-r--r--synapse/crypto/keyring.py13
1 files changed, 8 insertions, 5 deletions
diff --git a/synapse/crypto/keyring.py b/synapse/crypto/keyring.py
index d7fd831bf9..0e381c4710 100644
--- a/synapse/crypto/keyring.py
+++ b/synapse/crypto/keyring.py
@@ -172,7 +172,13 @@ class Keyring(object):
             # map from server name to a set of request ids
             server_to_request_ids = {}
 
-            def remove_deferreds(res, server_name, verify_request):
+            for verify_request in verify_requests:
+                server_name = verify_request.server_name
+                request_id = id(verify_request)
+                server_to_request_ids.setdefault(server_name, set()).add(request_id)
+
+            def remove_deferreds(res, verify_request):
+                server_name = verify_request.server_name
                 request_id = id(verify_request)
                 server_to_request_ids[server_name].discard(request_id)
                 if not server_to_request_ids[server_name]:
@@ -182,11 +188,8 @@ class Keyring(object):
                 return res
 
             for verify_request in verify_requests:
-                server_name = verify_request.server_name
-                request_id = id(verify_request)
-                server_to_request_ids.setdefault(server_name, set()).add(request_id)
                 verify_request.deferred.addBoth(
-                    remove_deferreds, server_name, verify_request,
+                    remove_deferreds, verify_request,
                 )
 
     @defer.inlineCallbacks