PyDev: Don't use thread.ident because a new thread may end up having the same id of an old thread.

GitOrigin-RevId: 63fbcd2fe5ae1f46d93c496d1e7b2016f85a7d07
This commit is contained in:
Elizaveta Shashkova
2019-06-07 18:10:40 +03:00
committed by intellij-monorepo-bot
parent 5e42077a11
commit f8ef1eaa95
7 changed files with 23 additions and 54 deletions
@@ -713,9 +713,6 @@ class _NewThreadStartupWithTrace:
# This is not a threading.Thread but a Dummy thread (so, get it as a dummy thread using
# currentThread).
t = threading.currentThread()
if t.ident is None:
t._set_ident()
if not getattr(t, 'is_pydev_daemon_thread', False):
thread_id = get_current_thread_id(t)
@@ -5,18 +5,18 @@ use_cython = os.getenv('PYDEVD_USE_CYTHON', None)
if use_cython == 'YES':
# We must import the cython version if forcing cython
from _pydevd_bundle.pydevd_cython_wrapper import PyDBAdditionalThreadInfo, set_additional_thread_info, _set_additional_thread_info_lock, _thread_ident_to_additional_info # @UnusedImport
from _pydevd_bundle.pydevd_cython_wrapper import PyDBAdditionalThreadInfo, set_additional_thread_info, _set_additional_thread_info_lock # @UnusedImport
elif use_cython == 'NO':
# Use the regular version if not forcing cython
from _pydevd_bundle.pydevd_additional_thread_info_regular import PyDBAdditionalThreadInfo, set_additional_thread_info, _set_additional_thread_info_lock, _thread_ident_to_additional_info # @UnusedImport @Reimport
from _pydevd_bundle.pydevd_additional_thread_info_regular import PyDBAdditionalThreadInfo, set_additional_thread_info, _set_additional_thread_info_lock # @UnusedImport @Reimport
elif use_cython is None:
# Regular: use fallback if not found (message is already given elsewhere).
try:
from _pydevd_bundle.pydevd_cython_wrapper import PyDBAdditionalThreadInfo, set_additional_thread_info, _set_additional_thread_info_lock, _thread_ident_to_additional_info
from _pydevd_bundle.pydevd_cython_wrapper import PyDBAdditionalThreadInfo, set_additional_thread_info, _set_additional_thread_info_lock
except ImportError:
from _pydevd_bundle.pydevd_additional_thread_info_regular import PyDBAdditionalThreadInfo, set_additional_thread_info, _set_additional_thread_info_lock, _thread_ident_to_additional_info # @UnusedImport
from _pydevd_bundle.pydevd_additional_thread_info_regular import PyDBAdditionalThreadInfo, set_additional_thread_info, _set_additional_thread_info_lock # @UnusedImport
else:
raise RuntimeError('Unexpected value for PYDEVD_USE_CYTHON: %s (accepted: YES, NO)' % (use_cython,))
@@ -121,7 +121,6 @@ class PyDBAdditionalThreadInfo(object):
from _pydev_imps._pydev_saved_modules import threading
_set_additional_thread_info_lock = threading.Lock()
_thread_ident_to_additional_info = {}
def set_additional_thread_info(thread):
try:
@@ -132,13 +131,9 @@ def set_additional_thread_info(thread):
with _set_additional_thread_info_lock:
# If it's not there, set it within a lock to avoid any racing
# conditions.
thread_ident = thread.ident
if thread_ident is None:
sys.stderr.write('thread.ident *must* be set at this point (set_additional_thread_info).')
raise AssertionError('thread.ident *must* be set at this point (set_additional_thread_info).')
additional_info = _thread_ident_to_additional_info.get(thread_ident)
additional_info = getattr(thread, 'additional_info', None)
if additional_info is None:
additional_info = _thread_ident_to_additional_info[thread_ident] = PyDBAdditionalThreadInfo()
additional_info = PyDBAdditionalThreadInfo()
thread.additional_info = additional_info
return additional_info
@@ -291,9 +291,8 @@ def clear_cached_thread_id(thread):
pass
# Besides the cache in the thread, we create a cache from the thread ident -> thread id so that
# if we have a Thread and later a DummyThread for the same ident we can obtain the same id.
_thread_ident_to_thread_id = {}
# Don't let threads be collected (so that id(thread) is guaranteed to be unique).
_thread_id_to_thread_found = {}
def _get_or_compute_thread_id_with_lock(thread, is_current_thread):
@@ -303,26 +302,13 @@ def _get_or_compute_thread_id_with_lock(thread, is_current_thread):
if tid is not None:
return tid
try:
thread_ident = thread.ident
if thread_ident is None:
raise AttributeError()
except AttributeError:
if not is_current_thread:
# When getting from another thread (i.e.: not current), the thread.ident *must* be
# there (when it's made visible in the threading module the ident is already set).
raise AssertionError('Did not expect thread.ident to be None when gotten from another thread.')
_thread_id_to_thread_found[id(thread)] = thread
# If we're too early in the thread bootstrap process,
# the thread ident could be still unset in the Thread.
thread_ident = thread_get_ident()
try:
tid = _thread_ident_to_thread_id[thread_ident]
except KeyError:
pid = get_pid()
tid = 'pid_%s_id_%s' % (pid, id(thread))
# Note: don't use thread.ident because a new thread may have the
# same id from an old thread.
pid = get_pid()
tid = 'pid_%s_id_%s' % (pid, id(thread))
_thread_ident_to_thread_id[thread_ident] = tid
thread.__pydevd_id__ = tid
return tid
@@ -127,7 +127,6 @@ cdef class PyDBAdditionalThreadInfo:
from _pydev_imps._pydev_saved_modules import threading
_set_additional_thread_info_lock = threading.Lock()
_thread_ident_to_additional_info = {}
def set_additional_thread_info(thread):
try:
@@ -138,13 +137,9 @@ def set_additional_thread_info(thread):
with _set_additional_thread_info_lock:
# If it's not there, set it within a lock to avoid any racing
# conditions.
thread_ident = thread.ident
if thread_ident is None:
sys.stderr.write('thread.ident *must* be set at this point (set_additional_thread_info).')
raise AssertionError('thread.ident *must* be set at this point (set_additional_thread_info).')
additional_info = _thread_ident_to_additional_info.get(thread_ident)
additional_info = getattr(thread, 'additional_info', None)
if additional_info is None:
additional_info = _thread_ident_to_additional_info[thread_ident] = PyDBAdditionalThreadInfo()
additional_info = PyDBAdditionalThreadInfo()
thread.additional_info = additional_info
return additional_info
@@ -765,19 +760,19 @@ cdef class PyDBFrame:
# ok, hit breakpoint, now, we have to discover if it is a conditional breakpoint
# lets do the conditional stuff here
if stop or exist_result:
eval_result = False
if breakpoint.has_condition:
eval_result = handle_breakpoint_condition(main_debugger, info, breakpoint, new_frame)
if not eval_result:
# No need to reset frame.f_trace to keep the same trace function.
return self.trace_dispatch
if breakpoint.expression is not None:
handle_breakpoint_expression(breakpoint, info, new_frame)
if breakpoint.is_logpoint and info.pydev_message is not None and len(info.pydev_message) > 0:
cmd = main_debugger.cmd_factory.make_io_message(info.pydev_message + os.linesep, '1')
main_debugger.writer.add_command(cmd)
# No need to reset frame.f_trace to keep the same trace function.
return self.trace_dispatch
if breakpoint.has_condition and not eval_result:
# No need to reset frame.f_trace to keep the same trace function.
return self.trace_dispatch
if is_call and frame.f_code.co_name in ('<module>', '<lambda>'):
# If we find a call for a module, it means that the module is being imported/executed for the
@@ -1195,14 +1190,12 @@ cdef class TopLevelThreadTracerOnlyUnhandledExceptions:
# IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated)
cdef class TopLevelThreadTracerNoBackFrame:
#
cdef public object _frame_trace_dispatch;
cdef public tuple _args;
cdef public object _try_except_info;
cdef public object _last_exc_arg;
cdef public set _raise_lines;
cdef public int _last_raise_line;
#
def __init__(self, frame_trace_dispatch, tuple args):
self._frame_trace_dispatch = frame_trace_dispatch
self._args = args
@@ -47,8 +47,6 @@ global_cache_frame_skips = mod.global_cache_frame_skips
_set_additional_thread_info_lock = mod._set_additional_thread_info_lock
_thread_ident_to_additional_info = mod._thread_ident_to_additional_info
fix_top_level_trace_and_get_trace_func = mod.fix_top_level_trace_and_get_trace_func
version = getattr(mod, 'version', 0)
@@ -8,7 +8,7 @@ from _pydevd_frame_eval.pydevd_modify_bytecode import insert_code
from pydevd_file_utils import get_abs_path_real_path_and_base_from_file, NORM_PATHS_AND_BASE_CONTAINER
from _pydevd_bundle.pydevd_trace_dispatch import fix_top_level_trace_and_get_trace_func
from _pydevd_bundle.pydevd_additional_thread_info import _set_additional_thread_info_lock, _thread_ident_to_additional_info
from _pydevd_bundle.pydevd_additional_thread_info import _set_additional_thread_info_lock
from _pydevd_bundle.pydevd_cython cimport PyDBAdditionalThreadInfo
get_file_type = DONT_TRACE.get
@@ -55,9 +55,9 @@ cdef class ThreadInfo:
with _set_additional_thread_info_lock:
# If it's not there, set it within a lock to avoid any racing
# conditions.
additional_info = _thread_ident_to_additional_info.get(thread_ident)
additional_info = getattr(thread, 'additional_info', None)
if additional_info is None:
additional_info = _thread_ident_to_additional_info[thread_ident] = PyDBAdditionalThreadInfo()
additional_info = PyDBAdditionalThreadInfo()
t.additional_info = additional_info
self.additional_info = additional_info
self.fully_initialized = True