[Twisted-Python] signal handlers and threads

Scott Lamb slamb at slamb.org
Fri May 12 14:33:46 MDT 2006


On May 12, 2006, at 11:56 AM, Manlio Perillo wrote:
> Hi.
>
> I have written a small module for sending signals to a "foreign"  
> Python
> process on Windows 2000/XP.
>
> The trunk is on
> http://svn.berlios.de/svnroot/repos/pykill32/trunk
>
> In this way I can send KILL, TERM and so, like in a POSIX system.
>
> This works by creating a thread on the remote process (yes, Windows
> allow this...) and let it call the function "raise" from the  
> MSVCR71 DLL.

Wow, that is sick! I thought _I_ did weird stuff with signals!

So Windows provides signal(), raise(), and the usual signal numbers,  
but no kill()? Weird! Does it have pthread_kill()? sigprocmask()?  
pthread_sigprocmask()? sigaction()? Do the semantics differ from the  
usual ones?

Interesting when compared to the Cygwin stuff: <http://cygwin.com/cgi- 
bin/cvsweb.cgi/src/winsup/cygwin/sigproc.cc?cvsroot=src>

> This seems to work fine, and now I can stop a Twisted process with
> kill.py TERM pid
> (does twistd save the pid in a file on Windows?)
>
> but I'm not sure if signal handlers are thread safe.

In Twisted's case, it sure looks to be. See twisted/internet/base.py:

     def sigTerm(self, *args):
         """Handle a SIGTERM interrupt.
         """
         log.msg("Received SIGTERM, shutting down.")
         self.callFromThread(self.stop)

Actually, <http://docs.python.org/lib/module-signal.html> says this:

     "Some care must be taken if both signals and threads are used in  
the same program. The fundamental thing to remember in using signals  
and threads simultaneously is: always perform signal() operations in  
the main thread of execution. Any thread can perform an alarm(),  
getsignal(), or pause(); only the main thread can set a new signal  
handler, and the main thread will be the only one to receive signals  
(this is enforced by the Python signal module, even if the underlying  
thread implementation supports sending signals to individual  
threads). This means that signals can't be used as a means of inter- 
thread communication. Use locks instead."

so the self.callFromThread() only matters if the reactor thread is  
not Python's main thread.

And Python does seem to provide this guarantee even with your thing.  
See signal_handler in <http://svn.python.org/projects/python/trunk/ 
Modules/signalmodule.c>. It just sets a flag to be picked up later,  
and only the main thread does that apparently.

Now, I don't see any guarantee that signals always handled before  
entering blocking calls, so they can be delayed forever if nothing  
else wakes it up. (This is like their documented note about long  
computations but worse.) It does the "normal syscall + flag handler"  
stuff I describe at <http://www.slamb.org/projects/sigsafe/api/>.  
That's a problem with Python's signal handling everywhere, not with  
your thing or Twisted.

Regards,
Scott

-- 
Scott Lamb <http://www.slamb.org/>






More information about the Twisted-Python mailing list