Skip to content

Commit

Permalink
wip - fix get current thread
Browse files Browse the repository at this point in the history
  • Loading branch information
fabioz committed Dec 17, 2023
1 parent 2df509c commit 3df52ec
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 15 deletions.
58 changes: 43 additions & 15 deletions _pydevd_sys_monitoring/pydevd_sys_monitoring.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
from _pydevd_bundle.pydevd_trace_dispatch import is_unhandled_exception
from _pydevd_bundle.pydevd_breakpoints import stop_on_unhandled_exception
from _pydevd_bundle.pydevd_utils import get_clsname_for_code
import weakref
from functools import partial

try:
from _pydevd_bundle.pydevd_bytecode_utils import get_smart_step_into_variant_from_frame_offset
Expand Down Expand Up @@ -178,30 +180,56 @@ def __init__(self, thread, trace, additional_info):
self.trace = trace


def _remove_dummy_from_thread_active(ref, thread, tident):
with threading._active_limbo_lock:
if _thread_active.get(tident) is thread:
_thread_active.pop(tident, None)


class _TrackRef:
'''
A helper class to track when a thread dies.
'''


def _create_thread_info(depth):
# Don't call threading.currentThread because if we're too early in the process
# we may create a dummy thread.
thread_ident = _get_ident()
t = _thread_active.get(thread_ident)
if t is None:
f_bootstrap_frame, is_bootstrap_frame_internal = _get_bootstrap_frame(depth + 1)
if f_bootstrap_frame is None:
return None

elif f_bootstrap_frame.f_code.co_name in ('__bootstrap_inner', '_bootstrap_inner'):
f_bootstrap_frame, is_bootstrap_frame_internal = _get_bootstrap_frame(depth + 1)
if f_bootstrap_frame is None:
return None # Case for threading when it's still in bootstrap or early in pydevd.

if is_bootstrap_frame_internal:
t = None
if f_bootstrap_frame.f_code.co_name in ('__bootstrap_inner', '_bootstrap_inner'):
# Note: be careful not to use threading.current_thread to avoid creating a dummy thread.
t = f_bootstrap_frame.f_locals.get('self')
if not isinstance(t, threading.Thread):
return None
t = None

else:
if not is_bootstrap_frame_internal:
# This means that the first frame is not in threading nor in pydev.
# In practice this means it's some unmanaged thread, so, creating
# a dummy thread is ok in this use-case.
t = threading.current_thread()
else:
return None
elif f_bootstrap_frame.f_code.co_name in ('_exec', '__call__'):
# Note: be careful not to use threading.current_thread to avoid creating a dummy thread.
t = f_bootstrap_frame.f_locals.get('t')
if not isinstance(t, threading.Thread):
t = None

else:
# This means that the first frame is not in threading nor in pydev.
# In practice this means it's some unmanaged thread, so, creating
# a dummy thread is ok in this use-case.
t = threading.current_thread()

if isinstance(t, threading._DummyThread):
_thread_local_info._ref = _TrackRef()
_thread_local_info._on_die_ref = weakref.ref(_thread_local_info._ref, partial(_remove_dummy_from_thread_active, thread=t, tident=t.ident))

if t is None:
t = _thread_active.get(thread_ident)

if t is None:
return None

if getattr(t, 'is_pydev_daemon_thread', False):
return ThreadInfo(t, False, None)
Expand Down
1 change: 1 addition & 0 deletions pydevd.py
Original file line number Diff line number Diff line change
Expand Up @@ -2592,6 +2592,7 @@ def _exec(self, is_module, entry_point_fn, module_name, file, globals, locals):
'''
This function should have frames tracked by unhandled exceptions (the `_exec` name is important).
'''
t = threading.current_thread(). # Keep in 't' local variable to be accessed afterwards from frame.f_locals.
if not is_module:
globals = pydevd_runpy.run_path(file, globals, '__main__')
else:
Expand Down

0 comments on commit 3df52ec

Please sign in to comment.