From 1d523139ec14876d5b772acb0c058892e8697357 Mon Sep 17 00:00:00 2001 From: Thomas Thrainer Date: Wed, 16 Apr 2014 17:07:09 +0200 Subject: [PATCH] Add an exception-trapping thread class To have better control over threads, this patch adds a helper Thread subclass which captures any exceptions occurring for later use. Signed-off-by: Hrvoje Ribicic Reviewed-by: Petr Pudlak Signed-off-by: Thomas Thrainer Reviewed-by: Helga Velroyen (cherry picked from commit e677d5e8e1c0ea7ef24e78f9ae842c9371449a77) --- qa/qa_job_utils.py | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/qa/qa_job_utils.py b/qa/qa_job_utils.py index 5f3fbf4..22e8743 100644 --- a/qa/qa_job_utils.py +++ b/qa/qa_job_utils.py @@ -24,6 +24,7 @@ """ import re +import sys import threading import time @@ -220,6 +221,40 @@ def _GetBlockingLocks(): return blocking_locks +class QAThread(threading.Thread): + """ An exception-preserving thread that executes a given function. + + """ + def __init__(self, fn, args, kwargs): + """ Constructor accepting the function to be invoked later. + + """ + threading.Thread.__init__(self) + self._fn = fn + self._args = args + self._kwargs = kwargs + self._exc_info = None + + def run(self): + """ Executes the function, preserving exception info if necessary. + + """ + # pylint: disable=W0702 + # We explicitly want to catch absolutely anything + try: + self._fn(*self._args, **self._kwargs) + except: + self._exc_info = sys.exc_info() + # pylint: enable=W0702 + + def reraise(self): + """ Reraises any exceptions that might have occured during thread execution. + + """ + if self._exc_info is not None: + raise self._exc_info[0], self._exc_info[1], self._exc_info[2] + + # TODO: Can this be done as a decorator? Implement as needed. def RunWithLocks(fn, locks, timeout, block, *args, **kwargs): """ Runs the given function, acquiring a set of locks beforehand. -- 1.7.10.4