Background
I’ve recently been a part of a project where twisted was used. We utilized a TimerService to daemonize a process. And yes, I realize that this approach may have been overkill, but we’re trying to stay consistent and use a proven framework. Yesterday, an exception went unhandled within the LoopingCall which caused the TimerService to fail, but the twistd application was still running (see twisted enhancement request). To avoid this, we would like to stop the service at the end of a catch-all exception handler.
Question
How to stop both the TimerService and the Twistd application from within the LoopingCall callable method? My concern is that the linux process keeps running when the TimerService is unable to handle an exception, even though the TimerService isn’t looping anymore.
For example:
def some_callable():
try:
# do stuff
except SomeSpecificError ex:
# handle & log error
except SomeOtherSpecificError ex:
# handle & log error
except:
# log sys.exc_info() details
# stop service.
NOTE: The following does not work within the callable.
from twisted.internet import reactor
reactor.stop()
You can’t stop the reactor before it starts:
However, as long as the reactor is running already,
reactor.stopworks fine:TimerServiceis a wrapper aroundLoopingCall. And more specifically, when it starts itsLoopingCall, it passesnow=Truetorun. That causes the function to be called the first time immediately, rather than after the specified interval elapses once.So when
TimerService.startServiceis called, your function is called. And the reactor isn’t running yet. On that first call to your function, you can’t stop the reactor, because it hasn’t been started.This program:
produces these results:
However, this one works fine:
And slightly less grossly, so does this one: