From 649465413b8aec166cfa55ee309cb111cba136e1 Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Thu, 2 Mar 2017 11:34:22 +0100 Subject: [PATCH] Make sure signal is not shared between threads. see #1015 --- modoboa/lib/middleware.py | 23 ++++++++++++++--------- modoboa/lib/signals.py | 7 +++++-- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/modoboa/lib/middleware.py b/modoboa/lib/middleware.py index 015f73746..9469cd84c 100644 --- a/modoboa/lib/middleware.py +++ b/modoboa/lib/middleware.py @@ -2,7 +2,6 @@ """Custom middlewares.""" -from threading import local from django.http import HttpResponseRedirect @@ -12,7 +11,7 @@ from modoboa.lib.web_utils import ( _render_error, ajax_response, render_to_json_response ) -_local_store = local() +from . import singleton class AjaxLoginRedirect(object): @@ -45,20 +44,26 @@ class CommonExceptionCatcher(object): ) -class RequestCatcherMiddleware(object): - """Simple middleware to store the current request.""" +class RequestCatcherMiddleware(singleton.Singleton): + """Simple middleware to store the current request. + + FIXME: the Singleton hack is used to make tests work. I don't know + why but middlewares are not dropped between test case runs so more + than one instance can be listening to the request_accessor signal + and we don't want that! + """ def __init__(self): - _local_store.request = None - request_accessor.connect(self) + self._request = None + request_accessor.signal.connect(self) def process_request(self, request): - _local_store.request = request + self._request = request def process_response(self, request, response): """Empty store.""" - _local_store.request = None + self._request = None return response def __call__(self, **kwargs): - return _local_store.request + return self._request diff --git a/modoboa/lib/signals.py b/modoboa/lib/signals.py index 3bc8aa545..ddfbaab30 100644 --- a/modoboa/lib/signals.py +++ b/modoboa/lib/signals.py @@ -1,13 +1,16 @@ """Custom signals.""" +from threading import local + import django.dispatch -request_accessor = django.dispatch.Signal() +request_accessor = local() +request_accessor.signal = django.dispatch.Signal() def get_request(): """Get the current request from anywhere.""" - request = request_accessor.send(None) + request = request_accessor.signal.send(None) if request: return request[0][1] return None