def switch_trap(): """ A context manager to temporarily increase the switch-trap level of the current thread. """ stackless.switch_trap(1) try: yield finally: stackless.switch_trap(-1)
def switch_trapped(): stackless.switch_trap(1) try: yield finally: stackless.switch_trap(-1)
def __exit__(self, exc, val, tb): stackless.switch_trap(-1)
def __enter__(self): stackless.switch_trap(1)
def tearDown(self): # Test that the C-stack didn't change self.assertEqual(self.__initial_cstack_serial, get_serial_last_jump()) # Test, that stackless errorhandler is None and reset it self.assertIsNone(stackless.set_error_handler(None)) # Test, that switch_trap level is 0 and set the level back to 0 try: # get the level without changing it st_level = stackless.switch_trap(0) self.assertEqual(st_level, 0, "switch_trap is %d" % (st_level, )) except AssertionError: # change the level so that the result is 0 stackless.switch_trap(-st_level) raise # Tasklets created in various tests can be left in the scheduler when they finish. We can feel free to # clean them up for the tests. Any tests that expect to exit with no leaked tasklets should do explicit # assertions to check. self.assertTrue( self.__setup_called, "Broken test case: it didn't call super(..., self).setUp()") self.__setup_called = False mainTasklet = stackless.getmain() current = mainTasklet.next while current is not None and current is not mainTasklet: next_ = current.next current.kill() current = next_ # Tasklets with C-stack can create reference leaks, if the C-stack holds a reference, # that keeps the tasklet-object alive. A common case is the call of a tasklet or channel method, # which causes a tasklet switch. The transient bound-method object keeps the tasklet alive. # Here we kill such tasklets. for current in get_tasklets_with_cstate(): if current.blocked: # print("Killing blocked tasklet", current, file=sys.stderr) current.kill() run_count = stackless.getruncount() self.assertEqual( run_count, 1, "Leakage from this test, with %d tasklets still in the scheduler" % (run_count - 1)) watchdog_list = get_watchdog_list(-1) if watchdog_list is not None: self.assertListEqual( watchdog_list, [None], "Watchdog list is not empty: " + repr(watchdog_list)) if withThreads: for (watchdog_list, tid) in [(get_watchdog_list(tid), tid) for tid in stackless.threads if tid != stackless.current.thread_id ]: if watchdog_list is None: continue self.assertListEqual( watchdog_list, [None], "Thread %d: watchdog list is not empty: %r" % (tid, watchdog_list)) preexisting_threads = self.__preexisting_threads self.__preexisting_threads = None # avoid pickling problems, see _addSkip expected_thread_count = len(preexisting_threads) active_count = threading.active_count() if active_count > expected_thread_count: activeThreads = set(threading.enumerate()) activeThreads -= preexisting_threads self.assertNotIn(threading.current_thread(), activeThreads, "tearDown runs on the wrong thread.") while activeThreads: activeThreads.pop().join(0.5) active_count = threading.active_count() self.assertEqual( active_count, expected_thread_count, "Leakage from other threads, with %d threads running (%d expected)" % (active_count, expected_thread_count)) gc.collect( ) # emits warnings about uncollectable objects after each test unexpected_uncollectable = [] for t in [t for t in gc.garbage if isinstance(t, stackless.tasklet)]: if id(t) not in self.__uncollectable_tasklets: unexpected_uncollectable.append(t) # clean up gc.garbage.remove(t) self.__expected_garbage.append(t) self.assertListEqual( unexpected_uncollectable, [], "New uncollectable tasklets: %r" % unexpected_uncollectable)