Przeglądaj źródła

[desktop and beeswax] Avoid race on Template.render

This hopefully solves the sporatic test failures we're getting
with beeswax.tests's test_parallel_queries.
Erick Tryzelaar 10 lat temu
rodzic
commit
4ea0da8
1 zmienionych plików z 22 dodań i 13 usunięć
  1. 22 13
      desktop/core/src/desktop/lib/test_runners.py

+ 22 - 13
desktop/core/src/desktop/lib/test_runners.py

@@ -16,6 +16,7 @@
 # limitations under the License.
 
 import sys
+import threading
 
 from django.conf import settings
 from django.core.management.base import BaseCommand
@@ -28,25 +29,33 @@ from mako.template import Template
 
 __all__ = ['HueTestRunner']
 
+# Capturing the mako context is not thread safe, so we wrap rendering in a mutex.
+_MAKO_LOCK = threading.RLock()
+
 
 def _instrumented_test_render(self, *args, **data):
     """
     An instrumented Template render method, providing a signal
     that can be intercepted by the test system Client
     """
-    def mako_callable_(context, *args, **kwargs):
-      template_rendered.send(sender=self, template=self, context=context)
-      return self.original_callable_[-1](context, *args, **kwargs)
-    if hasattr(self, 'original_callable_'):
-      self.original_callable_.append(self.callable_)
-    else:
-      self.original_callable_ = [self.callable_]
-    self.callable_ = mako_callable_
-    try:
-      response = runtime._render(self, self.original_callable_[-1], args, data)
-    finally:
-      self.callable_ = self.original_callable_.pop()
-    return response
+
+    with _MAKO_LOCK:
+      def mako_callable_(context, *args, **kwargs):
+        template_rendered.send(sender=self, template=self, context=context)
+        return self.original_callable_[-1](context, *args, **kwargs)
+
+      if hasattr(self, 'original_callable_'):
+        self.original_callable_.append(self.callable_)
+      else:
+        self.original_callable_ = [self.callable_]
+
+      self.callable_ = mako_callable_
+      try:
+        response = runtime._render(self, self.original_callable_[-1], args, data)
+      finally:
+        self.callable_ = self.original_callable_.pop()
+
+      return response
 
 
 class HueTestRunner(NoseTestSuiteRunner):