Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

Commit

Permalink
Take out a lock before modifying _CACHES (#7663)
Browse files Browse the repository at this point in the history
This should fix #7610.
  • Loading branch information
richvdh authored Jun 10, 2020
1 parent fcd6961 commit 0df618f
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 5 deletions.
1 change: 1 addition & 0 deletions changelog.d/7663.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix intermittent exception during startup, introduced in Synapse 1.14.0.
20 changes: 15 additions & 5 deletions synapse/config/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

import os
import re
import threading
from typing import Callable, Dict

from ._base import Config, ConfigError
Expand All @@ -25,6 +26,9 @@
# Map from canonicalised cache name to cache.
_CACHES = {}

# a lock on the contents of _CACHES
_CACHES_LOCK = threading.Lock()

_DEFAULT_FACTOR_SIZE = 0.5
_DEFAULT_EVENT_CACHE_SIZE = "10K"

Expand Down Expand Up @@ -66,7 +70,10 @@ def add_resizable_cache(cache_name: str, cache_resize_callback: Callable):
# Some caches have '*' in them which we strip out.
cache_name = _canonicalise_cache_name(cache_name)

_CACHES[cache_name] = cache_resize_callback
# sometimes caches are initialised from background threads, so we need to make
# sure we don't conflict with another thread running a resize operation
with _CACHES_LOCK:
_CACHES[cache_name] = cache_resize_callback

# Ensure all loaded caches are sized appropriately
#
Expand All @@ -87,7 +94,8 @@ def reset():
os.environ.get(_CACHE_PREFIX, _DEFAULT_FACTOR_SIZE)
)
properties.resize_all_caches_func = None
_CACHES.clear()
with _CACHES_LOCK:
_CACHES.clear()

def generate_config_section(self, **kwargs):
return """\
Expand Down Expand Up @@ -193,6 +201,8 @@ def resize_all_caches(self):
For each cache, run the mapped callback function with either
a specific cache factor or the default, global one.
"""
for cache_name, callback in _CACHES.items():
new_factor = self.cache_factors.get(cache_name, self.global_factor)
callback(new_factor)
# block other threads from modifying _CACHES while we iterate it.
with _CACHES_LOCK:
for cache_name, callback in _CACHES.items():
new_factor = self.cache_factors.get(cache_name, self.global_factor)
callback(new_factor)

0 comments on commit 0df618f

Please sign in to comment.