[Twisted-Python] Twisted.web signal handling

Jp Calderone exarkun at divmod.com
Sat Sep 24 11:25:04 EDT 2005

On Sat, 24 Sep 2005 14:43:09 +0200, Krzysztof Nowak <pegazik at gmail.com> wrote:
>Hello. I wrote a simple application using twisted.web. One of activity
>of my program is to contacting with some other processes. I need some
>timeout to perform this activity. The structure of my program looks
>like this:

Timeouts should be managed using twisted.internet.reactor.callLater().

>def TimeoutHandler(pid):
>    os.kill(pid, signal.SIGUSR1)

twistd uses SIGUSR1 for logfile rotation.  Your handler is probably getting clobbered.

>def handler():
>    raise ConnectionError
>signal.signal(signal.SIGUSR1, handler)
>MyPID = os.getpid()

Depending on exactly where this code is run, this is probably the wrong PID.  twistd daemonizes, which involves forking and exiting in the parent.  If your code is imported before daemonization happens, the above will retrieve the PID of the parent, which will not be your PID at any time during the actual operation of your program.

>def HistosRendering:
>        timer = threading.Timer(0.001, TimeoutHandler, [MyPID])
>        timer.start()
>        try:
>            <Some activity that need timeout>
>        except ConnectionError:
>            <In case of timeout>
>            return
>        else:
>            timer.cancel()

Why aren't you using Twisted to handle this connection attempt?  The threading.Timer/signal/raise combo is a very bad way to manage timeouts.  Twisted provides much better ways.

Also, there is a race condition between the end of your try suite and the timer.cancel() call.  The exception could be raised after the else suite is entered but before the timer is actually cancelled.

>class Resource(resource.Resource):
>    def render(self, request):
>        HistosRender()

You are blocking the entire process for the during of the render() call.  This is another reason not to make whatever synchronous connection attempt you are making and instead use something Twisted provides.  No other activities can occur, process-wide, while your code is running.  If this is a multiuser application, *everyone* using it will experience periods of unresponsiveness when *anyone* causes blocking code to run.

>resource = Resource()
>Unfortunately, there is something wrong, cause in case of timeout I am
>receiving error message, the TimeoutHandler is activated (in the Timer
>thread), but handler() in the main thread is not activated.
>I am using this kind of commands to start a server:
>> mktap web --path /www/ --port 8081
>> twistd -f web.tap
>Maybe I should somehow "turn on" handling of signals?
>Do you see any solution?

The main thing to figure out is how to rewrite the operation which you wish to timeout so that it is asynchronous and easily cancellable.  Then all the signal related difficulties will disappear.


More information about the Twisted-Python mailing list