def test_kill_during_cPickle_stack_switch(self): # this test kills the main/current tasklet of a other-thread, # which is fast-pickling a recursive structure. This leads to an # infinite recursion, which gets interrupted by a bomb thrown from # main-thread. Until issue #98 got fixed, this caused a crash. # See https://bitbucket.org/stackless-dev/stackless/issues/98 buf = BytesIO() import cPickle as pickle pickler = pickle.Pickler(buf, protocol=-1) pickler.fast = 1 started = threading.Event() c = TestCPickleBombHandling_Cls() c.started = started d = TestCPickleBombHandling_Dict() d[1] = d c.recursive = d self.killed = "undefined" t = threading.Thread(target=self.other_thread, name="other_thread", args=(pickler, c)) t.start() started.wait() stackless.get_thread_info(t.ident)[0].kill(pending=True) # print("killing") t.join() if isinstance(self.killed, tuple): raise (self.killed[0], self.killed[1], self.killed[2]) self.assertIsNone(self.killed)
def testAllThreads(self): for threadid in sys._current_frames(): info = stackless.get_thread_info(threadid) self.assertIsInstance(info, tuple) self.assertEqual(len(info), 3) self.assertIsInstance(info[0], stackless.tasklet) self.assertIs(info[0], info[1]) self.assertEqual(info[2], 1)
def get_watchdog_list(threadid): """Get the watchdog list of a thread. Contrary to :func:`get_current_watchdog_list` this function does not create a watchdog list, if it does not already exist. """ # The second argument of get_thread_info() is intentionally undocumented. # See C source. return stackless.get_thread_info(threadid, 1 << 31)[3]
def current_initial_stub(threadid=-1): """Get the initial stub of the given thread. """ # The second argument of get_thread_info() is intentionally undocumented. # See C source. return stackless.get_thread_info(threadid, 1 << 30)[5]
def f(): info.extend(stackless.get_thread_info(threadid))
def _schedule_callback(prev, next): ''' Called when a context is stopped or a new context is made runnable. ''' try: if not prev and not next: return current_frame = sys._getframe() if next: register_tasklet_info(next) # Ok, making next runnable: set the tracing facility in it. debugger = get_global_debugger() if debugger is not None: next.trace_function = debugger.get_thread_local_trace_func() frame = next.frame if frame is current_frame: frame = frame.f_back if hasattr(frame, 'f_trace'): # Note: can be None (but hasattr should cover for that too). frame.f_trace = debugger.get_thread_local_trace_func() debugger = None if prev: register_tasklet_info(prev) try: for tasklet_ref, tasklet_info in dict_items(_weak_tasklet_registered_to_info): # Make sure it's a copy! tasklet = tasklet_ref() if tasklet is None or not tasklet.alive: # Garbage-collected already! try: del _weak_tasklet_registered_to_info[tasklet_ref] except KeyError: pass if tasklet_info.frame_id is not None: remove_custom_frame(tasklet_info.frame_id) else: is_running = stackless.get_thread_info(tasklet.thread_id)[1] is tasklet if tasklet is prev or (tasklet is not next and not is_running): # the tasklet won't run after this scheduler action: # - the tasklet is the previous tasklet # - it is not the next tasklet and it is not an already running tasklet frame = tasklet.frame if frame is current_frame: frame = frame.f_back if frame is not None: abs_real_path_and_base = get_abs_path_real_path_and_base_from_frame(frame) # print >>sys.stderr, "SchedCB: %r, %d, '%s', '%s'" % (tasklet, frame.f_lineno, _filename, base) if debugger.get_file_type(abs_real_path_and_base) is None: tasklet_info.update_name() if tasklet_info.frame_id is None: tasklet_info.frame_id = add_custom_frame(frame, tasklet_info.tasklet_name, tasklet.thread_id) else: update_custom_frame(tasklet_info.frame_id, frame, tasklet.thread_id, name=tasklet_info.tasklet_name) elif tasklet is next or is_running: if tasklet_info.frame_id is not None: # Remove info about stackless suspended when it starts to run. remove_custom_frame(tasklet_info.frame_id) tasklet_info.frame_id = None finally: tasklet = None tasklet_info = None frame = None except: import traceback;traceback.print_exc() if _application_set_schedule_callback is not None: return _application_set_schedule_callback(prev, next)
def get_serial_last_jump(threadid=-1): """Get the current serial_last_jump of the given thread. """ # The second argument of get_thread_info() is intentionally undocumented. # See C source. return stackless.get_thread_info(threadid, 1 << 30)[4]