Milan Lakhani
Milan Lakhani

Reputation: 379

How can I make my Twisted 'reactor' stop?

hoping you can figure out why my reactor won't stop? In my thread constructor I have tried reactor.startRunning(False) and reactor.run(). In the run command for this thread I use reactor.iterate() periodically and then have tried reactor.stop() and reactor.callFromThread(reactor.stop) but the reactor doesn't stop, even once. Any feedback on this would be awesome :)

Alternatively, what else can I replace this with that is compatible with using twisted.internet server&resource to set up / listen to the port? Or maybe something that can replace both the reactor and twisted.internet?

    class DatePage(resource.Resource):
        def __init__(self, date_string):
            resource.Resource.__init__(self)
            self.date_str = str(date_string)

        def render_GET(self, request):
            request.responseHeaders.addRawHeader(b"content-type", b"application/json")
            return get_json().encode('utf-8')

    class PageFactory(resource.Resource):
      def getChild(self, date_string, request):
          return DatePage(date_string)

    class ControlThread(threading.Thread):
        def __init__(self, control_queue, stop_event):
            threading.Thread.__init__(self)
            self.control_queue = control_queue
            self.stop_event = stop_event
            self.site = server.Site(PageFactory())
            self.port = reactor.listenTCP(host_port, self.site)
            reactor.startRunning(False)

        def run(self):
            while not self.stop_event.is_set():
                try:
                    self.process_command(self.control_queue.get_nowait())
                    reactor.iterate()
                except queue.Empty:
                    pass
                time.sleep(0.001)
                reactor.iterate()
            sys.stderr.write("reactor.stop()\n")
            self.port.stopListening()
            reactor.callFromThread(reactor.stop)
            # reactor_thread.join()
            while reactor.running:
                print("running")
                time.sleep(0.1)
            if not reactor.running:
                print("STOPPED!!")

Edit: Added example. Problem is in ControlThread, other classes are for background.

Upvotes: 0

Views: 2641

Answers (2)

In my app, I am able to close the app with this code

from twisted.internet import reactor

# execute this in my fucntion
reactor.stop()

It will be equivalent to finis the app with code 0. I am still looking for an alternative, because I need to stop my app with an error in order to docker compose will restart my container automatically.

Upvotes: 0

Jean-Paul Calderone
Jean-Paul Calderone

Reputation: 48345

It looks like you are trying to run the Twisted reactor in a non-main thread and then send messages to it (a stop message and, it looks like, some other messages as well).

Twisted has a thread-safe message passing API already - and you're even using it: reactor.callFromThread. You should just use this to communicate with the reactor. This removes the need to call the non-interface methods startRunning and iterate and use the confusing and complicated running attribute (all of which you should avoid in any Twisted-based program you write).

So:

class ReactorThread(Thread):
    def __init__(self, reactor):
        Thread.__init__(self)
        self.reactor = reactor

    def listen(self):
        self.reactor.callFromThread(self._listen)

    def _listen(self):
        self.site = server.Site(PageFactory())
        self.port = reactor.listenTCP(host_port, self.site)

    def run(self):
        self.reactor.run(installSignalHandlers=False)

# later ...
from twisted.internet import reactor
t = ReactorThread(reactor)
t.start()
# ...
t.reactor.callFromThread(t.reactor.stop)
t.join()

You can also use t.reactor.callFromThread to send whatever other messages you like, in the form of a function that will be called in the reactor thread.

You may also want to look at https://crochet.readthedocs.io/en/stable/ for managing Twisted in a thread.

Upvotes: 1

Related Questions