Twisted reactor is stopped, but program doesn’t end?

So I’m writing a small script to use with Deluge. Deluge uses Twisted, and I really don’t have a firm grasp on how it works. Normally I’d just look up more info on it, but getting started with Twisted would take a long time and is beyond the scope of this little project. So I figured I would just ask here.

Now, I have this code. I’ll try to explain the specifig parts I need help with

import base64

import processargs

from deluge.ui.client import client
from twisted.internet import reactor

from deluge.log import setupLogger

options = processargs.readConfig(os.path.expanduser("~/.deluge-automator"))

d = client.connect(

def start():
    #other code

    t = client.core.add_torrent_file(tfile,
                                     base64.encodestring(data), None)

    t.addCallback(on_torrent_added_success, tfile)

def handle_stop_signal(SIGNAL, stack):

def on_torrent_added_success(result, tfile):
    #other code

def on_torrent_added_fail(result):
    print "Add torrent failed!"
    print "result: ", result

def on_connect_success(result):
    #other code


def on_connect_fail(result):
    print "Connection failed!"
    print "result: ", result


signal.signal(signal.SIGTERM, handle_stop_signal)
signal.signal(signal.SIGINT, handle_stop_signal)

When a torrent is successfully added, it should go back to start(), and it does, but I think it loses the reactor or something. Because now whenever it recieves a SIGTERM or SIGINT, the reactor closes, but doesn’t quit the program:

± % python2
Connection was successful!
result:  10
^C^CConnection failed!
result:  [Failure instance: Traceback: <class 'twisted.internet.error.ReactorNotRunning'>: Can't stop reactor that isn't running.
--- <exception caught here> ---

So the reactor gets stopped, but it doesn’t quit the program. I have to keyboard interrupt twice. Once to stop the reactor, and a second time to throw the error. Is there a certain way to set up a loop like this?

Best answer

reactor handles sigint, sigterm itself (there might be a parameter of that disables that). Install reactor.addSystemEventTrigger('before', 'shutdown', client.disconnect) instead.

See twisted: catch keyboardinterrupt and shutdown properly.