[Twisted-web] Reactor in a multithreaded program
Ellers
ellers at ellerton.net
Mon May 23 15:08:29 MDT 2005
> Are you sure reactor.callFromThread(reactor.stop) is being called?
Yes and no - I was sure it was being called (a print statement before) BUT
it turns out it was actually calling and returning ok.
But I found the problem! I needed this at the start:
from twisted.python import threadable
threadable.init( with_threads=1)
DOH!
> And make sure you aren't accidentally doing
> "reactor.callFromThread(reactor.stop())",
> which is a common mistake!
When I first read this I thought "damn thats what I've done" but I wasn't.
>> Is there an advised pattern for working with the reactor with multiple
>> threads?
>
> Yes: use callFromThread everytime you need to call a Twisted function
from a thread :)
;)
The following is more what I meant by a discussion of patterns. (These are
NOT real.. just designed to illustrate for discussion):
The wxwidgets pattern: simple case is to use the wxreactor.
However, you COULD run the GUI normally and run the reactor in a
non-main thread. Be sure to communicate with the reactor using
callFromThread or having a protocol reading a Queue.Queue() object.
The readline pattern: you have a shell-like interface and need to call
the blocking function raw_input(). (Sure, you can use the stdin protocol
in normal twisted but that won't play with readline).
You run the reactor in a non-main thread and communicate with it as above.
And the pattern could come with a simple proof-of-concept program, like
this one...
I also have a readline example working now. I can post it to the list if
anyone is interested.
>8 --- >8 ---
#!/bin/env python
"""Trivial demo - demonstrate the reactor in a NON main thread.
You can telnet to port 7001 and see echos of everything you type for
10 seconds. After that it should close cleanly. But it doesn't - yet.
"""
import sys
import time
import threading
from twisted.internet import reactor
from twisted.protocols import wire
from twisted.internet.protocol import Factory
from twisted.python import threadable
threadable.init( with_threads=1)
class ReactorFacade:
def __init__( self ):
self.reactorThread = threading.Thread(
target=reactor.run,
name="ReactorThread",
kwargs={'installSignalHandlers':0},
)
def start(self):
# assume not yet started
print "Facade: starting..."
self.reactorThread.start()
print "Facade: started ok"
def stop(self):
# assume already running
print "Facade: request stop"
reactor.callFromThread(reactor.stop)
print "Facade: request stopped ok"
self.reactorThread.join()
factory = Factory()
factory.protocol = wire.Echo
reactor.listenTCP( 7001, factory ) # <-- you don't NEED a protocol, but
for example...
print "Echo on 7001"
facade = ReactorFacade()
print "Main: Starting..."
facade.start()
print "Main: Sleeping..."
time.sleep(10)
print "Main: Stopping..."
facade.stop()
print "Main: Finished" # <-- will hang here
>8 --- >8 ---
More information about the Twisted-web
mailing list