Opened 3 years ago

Closed 17 months ago

#19511 closed Bug (invalid)

Thread safe bound method weakrefs

Reported by: Kronuz Owned by: nobody
Component: Core (Other) Version: 1.4
Severity: Normal Keywords:
Cc: Kronuz Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

I'm often getting this traceback:

AttributeError: 'BoundMethodWeakref' object has no attribute 'deletionMethods'

Stacktrace (most recent call last):

  File "django/core/handlers/base.py", line 119, in get_response
    response = callback(request, *callback_args, **callback_kwargs)
  File "posts/views.py", line 404, in get
    posts_post.save()
  File "django/db/models/base.py", line 475, in save
    self.save_base(using=using, force_insert=force_insert, force_update=force_update)
  File "django/db/models/base.py", line 506, in save_base
    signals.pre_save.send(sender=origin, instance=self, raw=raw, using=using)
  File "django/dispatch/dispatcher.py", line 183, in send
    response = receiver(signal=self, sender=sender, **named)
  File "haystack/models.py", line 268, in load_indexes
    ui.setup_indexes()
  File "haystack/utils/loading.py", line 283, in setup_indexes
    index._setup_save()
  File "celery_haystack/indexes.py", line 33, in _setup_save
    signals.post_save.connect(self._enqueue_save, sender=model, dispatch_uid=CelerySearchIndex)
  File "django/dispatch/dispatcher.py", line 105, in connect
    receiver = saferef.safeRef(receiver, onDelete=self._remove_receiver)
  File "django/dispatch/saferef.py", line 29, in safeRef
    onDelete=onDelete
  File "django/dispatch/saferef.py", line 248, in get_bound_method_weakref
    return BoundMethodWeakref(target=target, onDelete=onDelete)
  File "django/dispatch/saferef.py", line 88, in __new__
    current.deletionMethods.append( onDelete)

I suspect this has something to do with the threading environment I'm using. I'm attaching a patch that I believe fixes the issue.

Attachments (2)

#19510-thread_safe_template_cache.diff (1.4 KB) - added by Kronuz 3 years ago.
#19511-thread_safe_bound_method_weakref.diff (455 bytes) - added by Kronuz 2 years ago.

Download all attachments as: .zip

Change History (9)

Changed 3 years ago by Kronuz

comment:1 Changed 3 years ago by Kronuz

  • Cc Kronuz added
  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset

comment:2 Changed 3 years ago by apollo13

  • Resolution set to fixed
  • Status changed from new to closed

Did you attach the wrong patch here?

comment:3 Changed 3 years ago by apollo13

  • Resolution fixed deleted
  • Status changed from closed to new

Wth did the resolution get set to fixed :/

comment:4 Changed 3 years ago by aaugustin

  • Resolution set to needsinfo
  • Status changed from new to closed

This may be a valid issue, but the description doesn't include enough information to reproduce it and the wrong patch was attached.

comment:5 Changed 2 years ago by Kronuz

  • Resolution needsinfo deleted
  • Status changed from closed to new

Sorry I attached the wrong file, I've just attached the correct one.

The problem seems to be the BoundMethodWeakref._allInstances is filled with an uninitialised object, and when/if another thread tries to get and use the object, it doesn't still have at least the deletionMethods attribute which is added durin the call to __init__().

Version 0, edited 2 years ago by Kronuz (next)

comment:6 Changed 2 years ago by akaariai

  • Component changed from Uncategorized to Core (Other)
  • Triage Stage changed from Unreviewed to Accepted
  • Type changed from Uncategorized to Bug

The explanation seems correct to me. It also seems this will be impossible to test. You will need to switch to another thread in between the dict assignment and the __init__() call, and then you need to access the same key in another thread. An unlikely scenario.

comment:7 Changed 17 months ago by mjtamlyn

  • Resolution set to invalid
  • Status changed from new to closed

Our implementation of weakrefs has now gone in favour of (backported) code from python 3.4. This should hopefully no longer be an issue.

Note: See TracTickets for help on using tickets.
Back to Top