summary refs log tree commit diff
diff options
context:
space:
mode:
authorSean Quah <8349537+squahtx@users.noreply.github.com>2021-10-08 12:27:16 +0100
committerGitHub <noreply@github.com>2021-10-08 12:27:16 +0100
commit49a683d871add82fb1a8125c6803ac15ec7d341b (patch)
treea565024f2db39f4cf6987ec2853dbc43e625a3c9
parentInclude exception in json logging (#11028) (diff)
downloadsynapse-49a683d871add82fb1a8125c6803ac15ec7d341b.tar.xz
Fix long-standing bug where `ReadWriteLock` could drop logging contexts (#10993)
Use `PreserveLoggingContext()` to ensure that logging contexts are not
lost when exiting a read/write lock.

When exiting a read/write lock, callbacks on a `Deferred` are triggered
as a signal to any waiting coroutines. Any waiting coroutine that
becomes runnable is likely to follow the Synapse logging context rules
and will restore its own logging context, then either run to completion
or await another `Deferred`, resetting the logging context in the
process.
-rw-r--r--changelog.d/10993.misc1
-rw-r--r--synapse/util/async_helpers.py6
2 files changed, 5 insertions, 2 deletions
diff --git a/changelog.d/10993.misc b/changelog.d/10993.misc
new file mode 100644
index 0000000000..23c73dbac5
--- /dev/null
+++ b/changelog.d/10993.misc
@@ -0,0 +1 @@
+Fix a long-standing bug where `ReadWriteLock`s could drop logging contexts on exit.
diff --git a/synapse/util/async_helpers.py b/synapse/util/async_helpers.py
index 82d918a05f..5df80ea8e7 100644
--- a/synapse/util/async_helpers.py
+++ b/synapse/util/async_helpers.py
@@ -438,7 +438,8 @@ class ReadWriteLock:
             try:
                 yield
             finally:
-                new_defer.callback(None)
+                with PreserveLoggingContext():
+                    new_defer.callback(None)
                 self.key_to_current_readers.get(key, set()).discard(new_defer)
 
         return _ctx_manager()
@@ -466,7 +467,8 @@ class ReadWriteLock:
             try:
                 yield
             finally:
-                new_defer.callback(None)
+                with PreserveLoggingContext():
+                    new_defer.callback(None)
                 if self.key_to_current_writer[key] == new_defer:
                     self.key_to_current_writer.pop(key)