diff options
| author | Honza Král <honza.kral@gmail.com> | 2010-11-21 14:54:23 +0000 |
|---|---|---|
| committer | Honza Král <honza.kral@gmail.com> | 2010-11-21 14:54:23 +0000 |
| commit | f27e6f0dd198309e0d965ca78bf1c5fd04a29f8e (patch) | |
| tree | fd3818b720e9f2a84ea9c387dc08c15c4d073db6 | |
| parent | 14abb7c52c128c1ce903d8cfb295f9324081ad39 (diff) | |
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
| -rw-r--r-- | django/dispatch/dispatcher.py | 53 |
1 files changed, 35 insertions, 18 deletions
diff --git a/django/dispatch/dispatcher.py b/django/dispatch/dispatcher.py index 3b6b72d044..9beb309ac1 100644 --- a/django/dispatch/dispatcher.py +++ b/django/dispatch/dispatcher.py @@ -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) - 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 @@ class Signal(object): 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,14 +237,21 @@ class Signal(object): 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() def receiver(signal, **kwargs): |
