From 1579fdd54a9aab6b65ddb8de4e83b61c3384e2fe Mon Sep 17 00:00:00 2001
From: Erik Johnston <erik@matrix.org>
Date: Fri, 9 Jul 2021 10:16:54 +0100
Subject: [PATCH] Ensure we always drop the federation inbound lock (#10336)

---
 changelog.d/10336.bugfix                |  1 +
 synapse/federation/federation_server.py |  1 +
 synapse/storage/databases/main/lock.py  | 15 +++++++++++++--
 3 files changed, 15 insertions(+), 2 deletions(-)
 create mode 100644 changelog.d/10336.bugfix

diff --git a/changelog.d/10336.bugfix b/changelog.d/10336.bugfix
new file mode 100644
index 0000000000..5e75ed3335
--- /dev/null
+++ b/changelog.d/10336.bugfix
@@ -0,0 +1 @@
+Fix bug where inbound federation in a room could be delayed due to not correctly dropping a lock. Introduced in v1.37.1.
diff --git a/synapse/federation/federation_server.py b/synapse/federation/federation_server.py
index bf67d0f574..ac0f2ccfb3 100644
--- a/synapse/federation/federation_server.py
+++ b/synapse/federation/federation_server.py
@@ -949,6 +949,7 @@ class FederationServer(FederationBase):
                 room_id, room_version
             )
             if not next:
+                await lock.release()
                 return
 
             origin, event = next
diff --git a/synapse/storage/databases/main/lock.py b/synapse/storage/databases/main/lock.py
index e76188328c..774861074c 100644
--- a/synapse/storage/databases/main/lock.py
+++ b/synapse/storage/databases/main/lock.py
@@ -310,14 +310,25 @@ class Lock:
         _excinst: Optional[BaseException],
         _exctb: Optional[TracebackType],
     ) -> bool:
+        await self.release()
+
+        return False
+
+    async def release(self) -> None:
+        """Release the lock.
+
+        This is automatically called when using the lock as a context manager.
+        """
+
+        if self._dropped:
+            return
+
         if self._looping_call.running:
             self._looping_call.stop()
 
         await self._store._drop_lock(self._lock_name, self._lock_key, self._token)
         self._dropped = True
 
-        return False
-
     def __del__(self) -> None:
         if not self._dropped:
             # We should not be dropped without the lock being released (unless
-- 
GitLab