Connecting signals with use_caching inside mute_signals breaks unmute #212

Closed
coagulant opened this Issue Jul 1, 2015 · 0 comments

Comments

Projects
None yet
1 participant
@coagulant

Django model signals like post_save are defined with use_caching=True,
which enables per-signal internal cache.

  • mute_signals enters, patching corresponding signal's receivers
  • code inside context manager runs, and at some point a new callback (X) is connected to the signal
  • at this point only this new callback is in receivers and sender_receivers_cache (because cache is cleaned on connect/disconnect)
  • mute_signals exits, unpatching receivers, but X stays in receiver cache alone
  • old receivers that were supposed to be resored are not called until new receiver is connected or disconnected to the signal.

Proposed solution is to clear signal caches on exit:

def __exit__(self, exc_type, exc_value, traceback):
    for signal, receivers in self.paused.items():
        logger.debug('mute_signals: Restoring signal handlers %r',
                     receivers)
        signal.sender_receivers_cache.clear()
        signal.receivers = receivers
    self.paused = {}

or better store sender_receivers_cache in paused attribute

coagulant added a commit to MyBook/factory_boy that referenced this issue Jul 2, 2015

Fix mute_signals behavior for signals with caching
Connecting signals (with use_caching=True) inside mute_signals
was breaking unmute on exit. Paused receivers were not running.
This was caused by signal cache not being restored after unpatching.
Workaround is to clear signal cache on exit.

Fixes #212

@rbarrois rbarrois closed this in d471c1b Jul 5, 2015

rbarrois added a commit that referenced this issue Jul 5, 2015

Improve @coagulant's fixes to django signals (Closes #212).
Signal caching didn't exist until Django 1.6.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment