Twisted reactor 'signal only works in main thread' error?
Andrew Bennetts
andrew-pythonlist at puzzling.org
Thu Jun 5 06:50:08 EDT 2003
On Thu, Jun 05, 2003 at 10:52:51AM +0100, Richard wrote:
> Hi,
>
> I am using execfile inside a Thread derived class to run another Python
> script. The source for this script is below. The problem is, when I try to
> run it I get the following error message:
>
> Exception in thread Thread-1:
> Traceback (most recent call last):
[...]
> File "URFParser.py", line 32, in start
> reactor.run()
[...]
> signal.signal(signal.SIGINT, self.sigInt)
> ValueError: signal only works in main thread
>
> ####
>
> I've had a look at the Twisted docs but am only very new to Twisted and so
> can't really figure out how to fix this, am I right in thinking that a
> reactor can only operate inside the main thread of a program due to some
> signalling it uses? If so, is there any way around it?
Use reactor.run(installSignalHandlers=0). By default, the Twisted reactor
will install signal handlers so that it can shutdown cleanly given SIGTERM,
etc.
> The source for TestServer.py is here:
I've made a couple of quick comments.
> ####
>
> from twisted.internet.protocol import Protocol, ServerFactory
> from twisted.internet import reactor
>
> class ConnectionEndpoint(Protocol):
>
> def connectionMade(self):
> #Executed in a new thread for every incoming connection
> self.transport.write(self.factory.m_TestString)
This comment is wrong; Twisted is asynchronous, and processes all the
connections in the same thread.
> def dataReceived(self, data):
> print data
>
> class ConnectionEndpointFactory(ServerFactory):
> protocol = ConnectionEndpoint
> m_FrameQueue = None
> m_TestString = "Test"
>
> def setQ(self, q):
> self.m_FrameQueue = q
>
>
> class URFServer:
> m_Address = []
Having a mutable class attribute is usually a bad idea; it probably doesn't do
what you think it does...
> m_Factory = ConnectionEndpointFactory()
>
> def __init__(self, q, address):
> self.m_Factory.setQ(q)
> self.m_Address = address
...although your constructor immediately assigns an instance attribute with
the same name, so the earlier "m_Address = []" line is completely redundant
(and misleading!).
> def start(self):
> reactor.listenTCP(int(self.m_Address[1]), self.m_Factory)
> reactor.run()
So this is the line you need to replace with
reactor.run(installSignalHandlers=0).
I hope this helps!
-Andrew.
More information about the Python-list
mailing list