Reputation: 379
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
Reputation: 51
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
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