[2.1] Deferred being returned from thread

Bug #1631061 reported by Gavin Panella
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
MAAS
Invalid
Critical
Unassigned

Bug Description

Seen in a log file somewhere:

  Unhandled Error
  Traceback (most recent call last):
    File "/usr/lib/python3/dist-packages/twisted/application/app.py",
    line 364, in startReactor
      self.config, oldstdout, oldstderr, self.profiler, reactor)
    File "/usr/lib/python3/dist-packages/twisted/application/app.py",
    line 285, in runReactorWithLogging
      reactor.run()
    File "/usr/lib/python3/dist-packages/twisted/internet/base.py", line
    1194, in run
      self.mainLoop()
    File "/usr/lib/python3/dist-packages/twisted/internet/base.py", line
    1203, in mainLoop
      self.runUntilCurrent()
  --- <exception caught here> ---
    File "/usr/lib/python3/dist-packages/twisted/internet/base.py", line
    798, in runUntilCurrent
      f(*a, **kw)
    File "/usr/lib/python3/dist-packages/twisted/internet/defer.py",
    line 392, in callback
      assert not isinstance(result, Deferred)
  builtins.AssertionError:

This:

    File "/usr/lib/python3/dist-packages/twisted/internet/base.py", line
    798, in runUntilCurrent
      f(*a, **kw)

is calling a function that's been put into the reactor via
callFromThread. I've inspected all uses of this in MAAS and they're
fine. However, this:

    File "/usr/lib/python3/dist-packages/twisted/internet/defer.py",
    line 392, in callback
      assert not isinstance(result, Deferred)

tells us that the `f` earlier is a bound Deferred.callback method.
Looking at Twisted's source code there is exactly one function that does
callFromThread(d.callback, ...): deferToThreadPool. There's only one use
of that in MAAS! Do we have a winner?

No. Unfortunately, Twisted's deferToThread calls deferToThreadPool, and
there are 32 uses of that in MAAS, so more investigation is necessary.

It seems very likely that somewhere in MAAS a Deferred is being returned
from a non-reactor thread. That's almost certainly broken code in its
own right, never mind that it's crashing on the way back into the
reactor.

The effect of this bug may be to permanently leave a Deferred unfired.
It can be reproduced with a simple script that will not exit until you
kill it:

  from twisted.internet.defer import Deferred
  from twisted.internet.task import react
  from twisted.internet.threads import deferToThread

  def run(reactor):
      return deferToThread(Deferred)

  react(run)

Related branches

Gavin Panella (allenap)
description: updated
Changed in maas:
milestone: none → 2.1.0
summary: - Deferred being returned from thread
+ [2.1] Deferred being returned from thread
Changed in maas:
milestone: 2.1.0 → 2.1.1
Changed in maas:
milestone: 2.1.1 → 2.1.2
Changed in maas:
milestone: 2.1.2 → 2.1.3
Revision history for this message
Andres Rodriguez (andreserl) wrote :

Dear user,

This is an automated message.

We believe this bug report is no longer an issue in the latest version of MAAS. For such reason, we are making this issue as Won't Fix. If you believe this issue is still present in the latest version of MAAS, please re-open this bug report.

Changed in maas:
status: Triaged → Invalid
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.