Author: Honza_Kral
Date: 2010-11-21 08:58:18 -0600 (Sun, 21 Nov 2010)
New Revision: 14663

Modified:
   django/branches/releases/1.2.X/django/dispatch/dispatcher.py
Log:
[1.2.X] Make django signals more thread-safe. Thanks milosu for the patch!

Backport of r14662 from trunk.

Modified: django/branches/releases/1.2.X/django/dispatch/dispatcher.py
===================================================================
--- django/branches/releases/1.2.X/django/dispatch/dispatcher.py        
2010-11-21 14:54:23 UTC (rev 14662)
+++ django/branches/releases/1.2.X/django/dispatch/dispatcher.py        
2010-11-21 14:58:18 UTC (rev 14663)
@@ -1,4 +1,5 @@
 import weakref
+import threading
 
 from django.dispatch import saferef
 
@@ -30,6 +31,7 @@
         if providing_args is None:
             providing_args = []
         self.providing_args = set(providing_args)
+        self.lock = threading.Lock()
 
     def connect(self, receiver, sender=None, weak=True, dispatch_uid=None):
         """
@@ -97,11 +99,15 @@
         if weak:
             receiver = saferef.safeRef(receiver, 
onDelete=self._remove_receiver)
 
-        for r_key, _ in self.receivers:
-            if r_key == lookup_key:
-                break
-        else:
-            self.receivers.append((lookup_key, receiver))
+        try:
+            self.lock.acquire()
+            for r_key, _ in self.receivers:
+                if r_key == lookup_key:
+                    break
+            else:
+                self.receivers.append((lookup_key, receiver))
+        finally:
+            self.lock.release()
 
     def disconnect(self, receiver=None, sender=None, weak=True, 
dispatch_uid=None):
         """
@@ -130,11 +136,15 @@
         else:
             lookup_key = (_make_id(receiver), _make_id(sender))
         
-        for index in xrange(len(self.receivers)):
-            (r_key, _) = self.receivers[index]
-            if r_key == lookup_key:
-                del self.receivers[index]
-                break
+        try:
+            self.lock.acquire()
+            for index in xrange(len(self.receivers)):
+                (r_key, _) = self.receivers[index]
+                if r_key == lookup_key:
+                    del self.receivers[index]
+                    break
+        finally:
+            self.lock.release()
 
     def send(self, sender, **named):
         """
@@ -227,11 +237,20 @@
         Remove dead receivers from connections.
         """
 
-        to_remove = []
-        for key, connected_receiver in self.receivers:
-            if connected_receiver == receiver:
-                to_remove.append(key)
-        for key in to_remove:
-            for idx, (r_key, _) in enumerate(self.receivers):
-                if r_key == key:
-                    del self.receivers[idx]
+        try:
+            self.lock.acquire()
+            to_remove = []
+            for key, connected_receiver in self.receivers:
+                if connected_receiver == receiver:
+                    to_remove.append(key)
+            for key in to_remove:
+                last_idx = len(self.receivers) - 1
+                # enumerate in reverse order so that indexes are valid even
+                # after we delete some items
+                for idx, (r_key, _) in enumerate(reversed(self.receivers)):
+                    if r_key == key:
+                        del self.receivers[last_idx-idx]
+        finally:
+            self.lock.release()
+
+

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To post to this group, send email to django-upda...@googlegroups.com.
To unsubscribe from this group, send email to 
django-updates+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-updates?hl=en.

Reply via email to