Cause python to exit if any thread has an exception
Well, you could simply raise an error in your thread and have the main thread handle and report that error. From there you could even terminate the program.
For example on your worker thread:
try: self.result = self.do_something_dangerous()except Exception as e: import sys self.exc_info = sys.exc_info()
and on main thread:
if self.exc_info: raise self.exc_info[1].with_traceback(self.exc_info[2])return self.result
So to give you a more complete picture, your code might look like this:
import threadingclass ExcThread(threading.Thread): def excRun(self): pass #Where your core program will run def run(self): self.exc = None try: # Possibly throws an exception self.excRun() except: import sys self.exc = sys.exc_info() # Save details of the exception thrown # DON'T rethrow, # just complete the function such as storing # variables or states as needed def join(self): threading.Thread.join(self) if self.exc: msg = "Thread '%s' threw an exception: %s" % (self.getName(), self.exc[1]) new_exc = Exception(msg) raise new_exc.with_traceback(self.exc[2])
(I added an extra line to keep track of which thread is causing the error in case you have multiple threads, it's also good practice to name them)
My solution ended up being a happy marriage between the solution posted here and the SIGKILL
solution piece from above. I added the following killall.py
submodule to my package:
import threadingimport sysimport tracebackimport osimport signaldef sendKillSignal(etype, value, tb): print('KILL ALL') traceback.print_exception(etype, value, tb) os.kill(os.getpid(), signal.SIGKILL)original_init = threading.Thread.__init__def patched_init(self, *args, **kwargs): print("thread init'ed") original_init(self, *args, **kwargs) original_run = self.run def patched_run(*args, **kw): try: original_run(*args, **kw) except: sys.excepthook(*sys.exc_info()) self.run = patched_rundef install(): sys.excepthook = sendKillSignal threading.Thread.__init__ = patched_init
And then ran the install
right away before any other threads are launched (of my own creation or from other imported libraries).