This command will either wait for a given thread to be paused to get its stack or will provide it anyways after a timeout (in which case the stack will be gotten but local variables won't be available and it'll not be possible to interact with the frame as it's not actually stopped
| 656 | |
| 657 | |
| 658 | class InternalGetThreadStack(InternalThreadCommand): |
| 659 | """ |
| 660 | This command will either wait for a given thread to be paused to get its stack or will provide |
| 661 | it anyways after a timeout (in which case the stack will be gotten but local variables won't |
| 662 | be available and it'll not be possible to interact with the frame as it's not actually |
| 663 | stopped in a breakpoint). |
| 664 | """ |
| 665 | |
| 666 | def __init__(self, seq, thread_id, py_db, set_additional_thread_info, fmt, timeout=0.5, start_frame=0, levels=0): |
| 667 | InternalThreadCommand.__init__(self, thread_id) |
| 668 | self._py_db = weakref.ref(py_db) |
| 669 | self._timeout = time.time() + timeout |
| 670 | self.seq = seq |
| 671 | self._cmd = None |
| 672 | self._fmt = fmt |
| 673 | self._start_frame = start_frame |
| 674 | self._levels = levels |
| 675 | |
| 676 | # Note: receives set_additional_thread_info to avoid a circular import |
| 677 | # in this module. |
| 678 | self._set_additional_thread_info = set_additional_thread_info |
| 679 | |
| 680 | @overrides(InternalThreadCommand.can_be_executed_by) |
| 681 | def can_be_executed_by(self, _thread_id): |
| 682 | timed_out = time.time() >= self._timeout |
| 683 | |
| 684 | py_db = self._py_db() |
| 685 | t = pydevd_find_thread_by_id(self.thread_id) |
| 686 | frame = None |
| 687 | if t and not getattr(t, "pydev_do_not_trace", None): |
| 688 | additional_info = self._set_additional_thread_info(t) |
| 689 | frame = additional_info.get_topmost_frame(t) |
| 690 | try: |
| 691 | self._cmd = py_db.cmd_factory.make_get_thread_stack_message( |
| 692 | py_db, |
| 693 | self.seq, |
| 694 | self.thread_id, |
| 695 | frame, |
| 696 | self._fmt, |
| 697 | must_be_suspended=not timed_out, |
| 698 | start_frame=self._start_frame, |
| 699 | levels=self._levels, |
| 700 | ) |
| 701 | finally: |
| 702 | frame = None |
| 703 | t = None |
| 704 | |
| 705 | return self._cmd is not None or timed_out |
| 706 | |
| 707 | @overrides(InternalThreadCommand.do_it) |
| 708 | def do_it(self, dbg): |
| 709 | if self._cmd is not None: |
| 710 | dbg.writer.add_command(self._cmd) |
| 711 | self._cmd = None |
| 712 | |
| 713 | |
| 714 | def internal_step_in_thread(py_db, thread_id, cmd_id, set_additional_thread_info): |