from thread import start_new_thread, allocate_lock import time class _Thread_return_value_holder: pass def timeout_2s_catch(self, *args, **keyw): """ This function implements 2 second timeout advice that catches exceptions raised by the thread. The advice equals to the one you get by a = create_timeout_advice( 2.0, 1 ) """ # Initialise tflock that is locked until thread # finishes execution tflock = allocate_lock() tflock.acquire() ret = _Thread_return_value_holder() ret.value = None def save_retval( ret ): try: ret.value = self.__proceed(*args, **keyw) except: pass tflock.release() start_new_thread( save_retval, (ret,) ) if _wait_timeout( 2.0, tflock ): return None return ret.value _num_of_advices = 0 def create_timeout_advice( timeout = 1.0, catch_exceptions = 1 ): global _num_of_advices _num_of_advices = _num_of_advices + 1 py = "def timeout_advice" + str( _num_of_advices ) + \ "(self, *args, **keyw):\n" + \ " tflock = allocate_lock()\n" + \ " tflock.acquire()\n" + \ " ret = _Thread_return_value_holder()\n" + \ " ret.value = None\n" + \ " def save_retval( ret ):\n" if catch_exceptions: py = py + " try: ret.value = self.__proceed(*args,**keyw)\n" + \ " except: pass\n" else: py = py + " ret.value = self.__proceed(*args,**keyw)\n" py = py + " tflock.release()\n" + \ " start_new_thread( save_retval, (ret,) )\n" + \ " if _wait_timeout( "+str(timeout)+", tflock):\n" + \ " return None\n" + \ " return ret.value\n" return _create_function( py, "timeout_advice"+str(_num_of_advices) ) def _create_function( function_code, function_name ): # compile code codeobj = compile( function_code, "", "exec" ) # execute code, new function is added to local name space exec( codeobj ) return eval( function_name ) def _wait_timeout( max_time, lock ): """ Return 1 if lock is not released before max_time seconds have elapsed. """ start_time = time.time() while time.time() - start_time < max_time: time.sleep( 0.01 ) if lock.acquire(0): return 0 return 1