mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	Fixed #14533 -- Make django signals more thread-safe. Thanks milosu for the patch!
git-svn-id: http://code.djangoproject.com/svn/django/trunk@14662 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
		| @@ -1,4 +1,5 @@ | ||||
| import weakref | ||||
| import threading | ||||
|  | ||||
| from django.dispatch import saferef | ||||
|  | ||||
| @@ -30,6 +31,7 @@ class Signal(object): | ||||
|         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 @@ class Signal(object): | ||||
|         if weak: | ||||
|             receiver = saferef.safeRef(receiver, onDelete=self._remove_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 @@ class Signal(object): | ||||
|         else: | ||||
|             lookup_key = (_make_id(receiver), _make_id(sender)) | ||||
|          | ||||
|         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,14 +237,21 @@ class Signal(object): | ||||
|         Remove dead receivers from connections. | ||||
|         """ | ||||
|  | ||||
|         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: | ||||
|             for idx, (r_key, _) in enumerate(self.receivers): | ||||
|                 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[idx] | ||||
|                         del self.receivers[last_idx-idx] | ||||
|         finally: | ||||
|             self.lock.release() | ||||
|  | ||||
|  | ||||
| def receiver(signal, **kwargs): | ||||
|   | ||||
		Reference in New Issue
	
	Block a user