[Twisted-Python] LoopingCalls and unclean reactor

Drew Smathers drew.smathers at gmail.com
Wed Mar 16 12:06:25 EDT 2011


On Tue, Mar 15, 2011 at 9:55 PM, Brad Milne
<brad.milne at devx.runthered.com> wrote:
> Hi
> I have a series of MultiService objects, with child Services. Some of these
> services are TCPServers, for example, and others are my own objects
> (extending from Service).
> In the instance that I have a Service which controls a LoopingCall, I am
> getting intermittent 'unclean reactor' errors during tests. I feel I might
> be missing some handling of deferreds, perhaps.
> (using 8.2.0 - looking to migrate to 10.2.0 soon)
> Here is an example of the approach being used:
> class AdapterQueue(service.MultiService):
>     def startService(self):
>         service.Service.startService(self)
>         self._looping_controller = LoopingCall(self._action)
>         d = self._looping_controller.start(self.delay, False)
>         d.addErrback(self._errorInScheduler)
>     def stopService(self):
>         service.Service.stopService(self)
>         d = self._looping_controller.deferred
>         self._looping_controller.stop()
>         return d


I'm not sure if this is part of the issue or not, but it seems odd
that you may have accidentally inherited from MultiService instead of
Service.


> And an example error (happens about 1/3 of the time):
> DirtyReactorAggregateError: Reactor was unclean.
> DelayedCalls: (set twisted.internet.base.DelayedCall.debug = True to debug)
> <DelayedCall 30800112 [0.0189974308014s] called=0 cancelled=0
> LoopingCall<0.033333333333333333>(AdapterQueue._action, *(), **{})()
> traceback at creation:
>   File "C:\Python26\lib\threading.py", line 497, in __bootstrap
>     self.__bootstrap_inner()
>       File "C:\Python26\lib\threading.py", line 525, in __bootstrap_inner
>     self.run()
>       File "C:\Python26\lib\threading.py", line 477, in run
>     self.__target(*self.__args, **self.__kwargs)
>       File "D:\dev\eggs\nose-0.11.3-py2.6.egg\nose\twistedtools.py", line
> 57, in <lambda>
>     installSignalHandlers=False))
>       File
> "D:\dev\eggs\twisted-8.2.0-py2.6-win32.egg\twisted\internet\base.py", line
> 1128, in run
>     self.mainLoop()
>       File
> "D:\dev\eggs\twisted-8.2.0-py2.6-win32.egg\twisted\internet\base.py", line
> 1137, in mainLoop
>     self.runUntilCurrent()
>       File
> "D:\dev\eggs\twisted-8.2.0-py2.6-win32.egg\twisted\internet\base.py", line
> 757, in runUntilCurrent
>     call.func(*call.args, **call.kw)
>       File
> "D:\dev\eggs\twisted-8.2.0-py2.6-win32.egg\twisted\internet\task.py", line
> 115, in __call__
>     d.addCallback(cb)
>       File
> "D:\dev\eggs\twisted-8.2.0-py2.6-win32.egg\twisted\internet\defer.py", line
> 195, in addCallback
>     callbackKeywords=kw)
>       File
> "D:\dev\eggs\twisted-8.2.0-py2.6-win32.egg\twisted\internet\defer.py", line
> 186, in addCallbacks
>     self._runCallbacks()
>       File
> "D:\dev\eggs\twisted-8.2.0-py2.6-win32.egg\twisted\internet\defer.py", line
> 328, in _runCallbacks
>     self.result = callback(self.result, *args, **kw)
>       File
> "D:\dev\eggs\twisted-8.2.0-py2.6-win32.egg\twisted\internet\task.py", line
> 103, in cb
>     self._reschedule()
>       File
> "D:\dev\eggs\twisted-8.2.0-py2.6-win32.egg\twisted\internet\task.py", line
> 139, in _reschedule
>     self.call = self.clock.callLater(nextTime - currentTime, self)
>>
>


Can you post code for the test?  This means generally (as you
suggested) that you haven't waited for all related deferreds to fire
before ending the test. Return the deferred returned by stopService(),
for example, and make final assertions in a callback; but I'm guessing
you already know this.


-Drew



More information about the Twisted-Python mailing list