7

I am building an application that needs to run a TCP server on a thread other than the main. When trying to run the following code:

reactor.listenTCP(ServerConfiguration.tcpport, TcpCommandFactory())
reactor.run()

I get the following error

exceptions.ValueError: signal only works in main thread

Can I run the twisted servers on threads other than the main one?

JS.
  • 14,781
  • 13
  • 63
  • 75
Eden
  • 3,696
  • 2
  • 24
  • 24
  • 1
    Twisted is non-blocking by nature. See http://stackoverflow.com/questions/4263059/python-erlang-whats-the-difference-between-twisted-stackless-greenlet-event – scape Oct 16 '12 at 15:25
  • 1
    From the tests I conducted it does block the main thread, if you put a print message before and after the "reactor.run()" command you will see that the after message will never print. – Eden Oct 16 '12 at 15:37
  • reactor.run() runs twisted until twisted is complete and shutdown, which then code after reactor.run would be run. You could integrate your code with the twisted functions/callbacks and thus achieve non-blocking. I chose to drop twisted and use gevent for most things. I hear zeroMQ is also great. – scape Oct 16 '12 at 15:50
  • 1
    [twisted tutorial](http://krondo.com/blog/?p=1209) might help if you are new to the asynchronous programming – jfs Oct 16 '12 at 16:32
  • 1
    Can you explain why you've decided you need threads? Chances are there is an API somewhere in Twisted that will help you accomplish your goal without threads. – Jean-Paul Calderone Oct 16 '12 at 16:41
  • @Jean-PaulCalderone - Thanks. But I'll just say that my application is not a "sub-class" of Twisted. It just makes use of it. So it will be wrong to look for a Twisted oriented API to solve potential problems. – Eden Oct 17 '12 at 11:11
  • @Eden - subclassing is not an appropriate metaphor; your application does not need to be intimately tied to Twisted in order to make good use of Twisted's facilities. Can you explain why you needed threads? Threads are usually the wrong choice. You can probably use Twisted in a more straightforward way to get the same thing done. – Glyph Oct 18 '12 at 17:45

1 Answers1

21

Twisted can run in any thread - but only one thread at a time. If you want to run in the non-main thread, simply do reactor.run(installSignalHandlers=False). However, you cannot use a reactor on the non-main thread to spawn subprocesses, because their termination will never be detected. (This is a limitation of UNIX, really, not of Twisted.)

Glyph
  • 31,152
  • 11
  • 87
  • 129
  • 1
    Thank you very much, I didn't find this earlier but Twisted FAQ has an entry on this subject! http://twistedmatrix.com/trac/wiki/FrequentlyAskedQuestions#Igetexceptions.ValueError:signalonlyworksinmainthreadwhenItrytorunmyTwistedprogramWhatswrong – Eden Oct 17 '12 at 11:15
  • 1
    you saved my day sir – Amin Etesamian May 30 '18 at 00:47
  • Glad we could help! – Glyph May 31 '18 at 05:30
  • @Glyph Is there a way to use this within the confines of [`react`](https://twistedmatrix.com/documents/current/api/twisted.internet.task.react.html) – Grr Oct 09 '18 at 15:35
  • No; `react` is designed to give you sensible defaults for the main-point of your program. If you want to carefully manage the reactor yourself with custom flags, you'll need to call `reactor.run` yourself and manage its lifecycle. – Glyph Oct 10 '18 at 16:41
  • What does linux have to do with this limitation? I run any kind of thread - including `http` listeners on any other thread on the `jvm`. I do that all the time. This is a python thing that I never ran into until trying to run multiple http listeners in one **python** program – WestCoastProjects Apr 03 '20 at 03:29
  • The limitation of UNIX (not "Linux") is that the signal that indicates the termination of a process, SIGCHLD, is delivered via a signal handler, so you need explicit coordination among multiple threads to dispatch the signal to the appropriate one. Twisted doesn't implement such signal-routing among multiple reactors, although in principle it is possible that it could; as long as no *other* library wanted to own SIGCHLD, which is what I was alluding to. – Glyph Apr 04 '20 at 06:07