diff --git a/python/helpers/pydev/_pydev_bundle/pydev_monkey.py b/python/helpers/pydev/_pydev_bundle/pydev_monkey.py index 0a1de5a53cb7..c0124cce2d90 100644 --- a/python/helpers/pydev/_pydev_bundle/pydev_monkey.py +++ b/python/helpers/pydev/_pydev_bundle/pydev_monkey.py @@ -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) diff --git a/python/helpers/pydev/_pydevd_bundle/pydevd_additional_thread_info.py b/python/helpers/pydev/_pydevd_bundle/pydevd_additional_thread_info.py index 593940b11dc3..5e0d7dd77355 100644 --- a/python/helpers/pydev/_pydevd_bundle/pydevd_additional_thread_info.py +++ b/python/helpers/pydev/_pydevd_bundle/pydevd_additional_thread_info.py @@ -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,)) diff --git a/python/helpers/pydev/_pydevd_bundle/pydevd_additional_thread_info_regular.py b/python/helpers/pydev/_pydevd_bundle/pydevd_additional_thread_info_regular.py index a3761129339e..a5f6b90fd3ea 100644 --- a/python/helpers/pydev/_pydevd_bundle/pydevd_additional_thread_info_regular.py +++ b/python/helpers/pydev/_pydevd_bundle/pydevd_additional_thread_info_regular.py @@ -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 diff --git a/python/helpers/pydev/_pydevd_bundle/pydevd_constants.py b/python/helpers/pydev/_pydevd_bundle/pydevd_constants.py index 977d22a8221a..a08008242eb8 100644 --- a/python/helpers/pydev/_pydevd_bundle/pydevd_constants.py +++ b/python/helpers/pydev/_pydevd_bundle/pydevd_constants.py @@ -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 diff --git a/python/helpers/pydev/_pydevd_bundle/pydevd_cython.pyx b/python/helpers/pydev/_pydevd_bundle/pydevd_cython.pyx index a622d2fbd6c3..062825a90319 100644 --- a/python/helpers/pydev/_pydevd_bundle/pydevd_cython.pyx +++ b/python/helpers/pydev/_pydevd_bundle/pydevd_cython.pyx @@ -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 ('', ''): # 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 diff --git a/python/helpers/pydev/_pydevd_bundle/pydevd_cython_wrapper.py b/python/helpers/pydev/_pydevd_bundle/pydevd_cython_wrapper.py index e9d0d01e1145..1058519b3f7c 100644 --- a/python/helpers/pydev/_pydevd_bundle/pydevd_cython_wrapper.py +++ b/python/helpers/pydev/_pydevd_bundle/pydevd_cython_wrapper.py @@ -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) diff --git a/python/helpers/pydev/_pydevd_frame_eval/pydevd_frame_evaluator.pyx b/python/helpers/pydev/_pydevd_frame_eval/pydevd_frame_evaluator.pyx index 8116703f62f5..108aa6341be1 100644 --- a/python/helpers/pydev/_pydevd_frame_eval/pydevd_frame_evaluator.pyx +++ b/python/helpers/pydev/_pydevd_frame_eval/pydevd_frame_evaluator.pyx @@ -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