Python ignores SIGINT in multithreaded programs - how to fix that?
I have Python 2开发者_开发技巧.6 on MacOS X and a multithread operation. Following test code works fine and shuts down app on Ctrl-C:
import threading, time, os, sys, signal
def SigIntHandler( signum, frame ) :
sys.exit( 0 )
signal.signal( signal.SIGINT, SigIntHandler )
class WorkThread( threading.Thread ) :
def run( self ) :
while True :
time.sleep( 1 )
thread = WorkThread()
thread.start()
time.sleep( 1000 )
But if i change only one string, adding some real work to worker thread, the app will never terminate on Ctrl-C:
import threading, time, os, sys, signal
def SigIntHandler( signum, frame ) :
sys.exit( 0 )
signal.signal( signal.SIGINT, SigIntHandler )
class WorkThread( threading.Thread ) :
def run( self ) :
while True :
os.system( "svn up" ) # This is really slow and can fail.
time.sleep( 1 )
thread = WorkThread()
thread.start()
time.sleep( 1000 )
Is it possible to fix it, or python is not intended to be used with threading?
A couple of things which may be causing your problem:
- The Ctrl-C is perhaps being caught by
svn
, which is ignoring it. - You are creating a thread which is a non-daemon thread, then just exiting the process. This will cause the process to wait until the thread exits - which it never will. You need to either make the thread a daemon or give it a way to terminate it and
join()
it before exiting. While it always seems to stop on my Linux system, MacOS X behaviour may be different.
Python works well enough with threads :-)
Update: You could try using subprocess
, setting up the child process so that file handles are not inherited, and setting the child's stdin to subprocess.PIPE.
You likely do not need threads at all.
Try using Python's subprocess
module, or even Twisted's process support.
I'm not an expert on Threads with Python but quickly reading the docs leads to a few conclusions.
1) Calling os.system()
spawns a new subshell and is not encouraged. Instead the subprocess module should be used. http://docs.python.org/release/2.6.6/library/os.html?highlight=os.system#os.system
2) The threading
module doesn't seem to give a whole lot of control to the threads, maybe try using the thread
module, at least there is a thread.exit()
function. Also from the threading
docs here it says that dummy threads may be created, which are always alive and daemonic, furthermore
"… the entire Python program exits when only daemon threads are left."
So, I would imagine that the least you need to do is signal the currently running threads that they need to exit, before exiting the main thread, or joining them on ctrl-c to allow them to finish (although this would obviously be contradictory to ctrl-c), or perhaps just using the subprocess
module to spawn the svn up
would do the trick.
精彩评论