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