def raise_exception(self): thread_id = self.get_id() res = pythonapi.PyThreadState_SetAsyncExc(thread_id, py_object(SystemExit)) if res > 1: pythonapi.PyThreadState_SetAsyncExc(thread_id, 0) print('Exception raise failure')
def _async_raise(self, tid, exctype): """raises the exception, performs cleanup if needed""" tid = c_long(tid) if not isclass(exctype): exctype = type(exctype) res = pythonapi.PyThreadState_SetAsyncExc(tid, py_object(exctype)) if res == 0: raise ValueError("invalid thread id") elif res != 1: pythonapi.PyThreadState_SetAsyncExc(tid, None) raise SystemError("PyThreadState_SetAsyncExc failed")
def interrupt(self): if not self.isAlive(): return tid = self._get_thread_id() threads_affected = pythonapi.PyThreadState_SetAsyncExc( c_long(tid), py_object(TimeoutException)) if threads_affected != 1: # if it returns a number greater than one, you're in trouble, # and you should call it again with exc=NULL to revert the effect pythonapi.PyThreadState_SetAsyncExc(c_long(tid), None) raise SystemError("PyThreadState_SetAsyncExc failed")
def _async_raise(tid, exctype): if not isclass(exctype): raise TypeError("Only types can be raised (not instances)") res = pythonapi.PyThreadState_SetAsyncExc(c_long(tid), py_object(exctype)) if res == 0: raise ValueError("invalid thread id") elif res != 1: pythonapi.PyThreadState_SetAsyncExc(tid, 0) raise SystemError("PyThreadState_SetAsyncExc failed")
def _async_raise(tid, exctype): """raises the exception, performs cleanup if needed""" tid = c_long(tid) if not isclass(exctype): exctype = type(exctype) res = pythonapi.PyThreadState_SetAsyncExc(tid, py_object(exctype)) if res == 0: raise ValueError("invalid thread id") elif res != 1: # """if it returns a number greater than one, you're in trouble, # and you should call it again with exc=NULL to revert the effect""" pythonapi.PyThreadState_SetAsyncExc(tid, None) raise SystemError("PyThreadState_SetAsyncExc failed")
def _kill_thread(cls, tid, exctype): '''Raises an exception in the threads with id tid''' if not isclass(exctype): raise TypeError("Need an Exception Class") res = pythonapi.PyThreadState_SetAsyncExc(c_long(tid), py_object(exctype)) if res == 0: raise ValueError("invalid thread id") elif res != 1: # "if it returns a number greater than one, you're in trouble, # and you should call it again with exc=NULL to revert the effect" pythonapi.PyThreadState_SetAsyncExc(c_long(tid), None) raise SystemError("PyThreadState_SetAsyncExc failed")
def raise_exc(self, exctype=TaskInterrupt): """Raises the given Exception type in the context of the loop thread regardless of which thread calls the method.""" if not isclass(exctype): raise TypeError("Only types can be raised (not instances)") tid = self._thread_id if tid is None: raise RuntimeError("Event loop is not running.") # raise the exception and perform cleanup if needed res = pythonapi.PyThreadState_SetAsyncExc(tid, py_object(exctype)) if res is not 1: if res == 0: raise ValueError("Invalid thread id." ) # did the thread stop right before raising? else: # if it returns a number greater than one, you're in trouble, # and you should call it again with exc=NULL to roll back the effect pythonapi.PyThreadState_SetAsyncExc(tid, None) raise SystemError("PyThreadState_SetAsyncExc failed")
def async_raise(tid, exctype=Exception): """ Raise an Exception in the Thread with id `tid`. Perform cleanup if needed. Based on Killable Threads By Tomer Filiba from http://tomerfiliba.com/recipes/Thread2/ license: public domain. """ assert isinstance(tid, int), 'Invalid thread id: must an integer' tid = c_long(tid) exception = py_object(Exception) res = pythonapi.PyThreadState_SetAsyncExc(tid, exception) if res == 0: raise ValueError('Invalid thread id.') elif res != 1: # if it returns a number greater than one, you're in trouble, # and you should call it again with exc=NULL to revert the effect pythonapi.PyThreadState_SetAsyncExc(tid, 0) raise SystemError('PyThreadState_SetAsyncExc failed.')
def abort(self, exception=ThreadAbortedError): """Abort the current thread by raising an exception in its context. A return value of one means the thread was successfully aborted, a value of zero means the thread could not be found, any other value indicates that an error has occurred. """ if debug: print "Aborting worker thread..." try: processing = self.isAlive() and self._processing except AttributeError: processing = False if not processing: if debug: print "Error: Thread is not working." threadID = self.threadID() if threadID is None: if debug: print "Error: Worker thread id not found" return 0 if debug: print "Worker thread id is", threadID try: ret = pythonapi.PyThreadState_SetAsyncExc( c_long(threadID), py_object(exception)) # If it returns a number greater than one, we're in trouble, # and should call it again with exc=NULL to revert the effect if ret > 1: pythonapi.PyThreadState_SetAsyncExc( c_long(threadID), py_object()) except Exception: ret = -1 if debug: if ret == 0: print "Error: Could not find thread", threadID elif ret != 1: print "Error: Could not abort thread", threadID return ret
def test_async(n_inner=200, n_repeat=1000): """ n_inner should be larger than check interval by at around 20. It returns a list of for loop count. The first one could be anything below check interval The other ones should be similar. Anything bigger is bad. """ check_interval = sys.getcheckinterval() print 'current check interval', check_interval result = [] for i in range(n_repeat): j = -99 pythonapi.PyThreadState_SetAsyncExc(c_long(thread.get_ident()), py_object(KeyboardInterrupt)) try: for j in range(n_inner): pass except KeyboardInterrupt: result.append(j) for r in result: if r > check_interval: print ' WARNING found: %i > check interval', r return result
def run_one_step(self): self.print_game() bot0_runner = SnakeRunner(self.bot0, self.snake0, self.snake1, self.maze_size, self.apple_coordinate) bot1_runner = SnakeRunner(self.bot1, self.snake1, self.snake0, self.maze_size, self.apple_coordinate) s0_timeout = False s1_timeout = False bot0_runner.start() bot0_runner.join(timeout=self.TIMEOUT_THRESHOLD) if bot0_runner.is_alive(): pythonapi.PyThreadState_SetAsyncExc(c_long(bot0_runner)) s0_timeout = True print("Bot " + self.bot0.name + " took too long to make a decision") bot1_runner.start() bot1_runner.join(timeout=self.TIMEOUT_THRESHOLD) if bot1_runner.is_alive(): pythonapi.PyThreadState_SetAsyncExc(c_long(bot1_runner)) s1_timeout = True print("Bot " + self.bot1.name + " took too long to make a decision") bot0_direction = bot0_runner.chosen_direction bot1_direction = bot1_runner.chosen_direction if s0_timeout or s1_timeout: self.game_result = ('0' if s0_timeout else '1') + " - " + ('0' if s1_timeout else '1') return False grow0 = self.snake0.get_head().move_to( bot1_direction) == self.apple_coordinate grow1 = self.snake1.get_head().move_to( bot1_direction) == self.apple_coordinate s0_dead = not self.snake0.move_to(bot0_direction, grow0) s1_dead = not self.snake1.move_to(bot1_direction, grow1) s0_dead |= self.snake0.head_collides_with(self.snake1) s1_dead |= self.snake1.head_collides_with(self.snake0) if grow0 or grow1 or self.apple_coordinate is None: self.apple_eaten0 = len(self.snake0.body) - self.snake_size self.apple_eaten1 = len(self.snake1.body) - self.snake_size self.apple_coordinate = self.random_non_occupied_cell() print("snake0 -> " + bot0_direction.name + " snake1 -> " + bot1_direction.name) print("Apples eaten: " + self.bot0.name + " : " + str(self.apple_eaten0) + " " + self.bot1.name + " : " + str(self.apple_eaten1)) cont = not (s0_dead or s1_dead) if not cont: if s0_dead ^ s1_dead: self.game_result = ('0' if s0_dead else '1') + " - " + ('0' if s1_dead else '1') elif s0_dead and s1_dead: self.game_result = ( '1' if self.apple_eaten0 > self.apple_eaten1 else '0') + " - " + ( '1' if self.apple_eaten1 > self.apple_eaten0 else '0') print("Result: " + self.game_result) return cont