示例#1
0
    def __init__(self, thread_id, method=None, *args, **kwargs):
        assert thread_id == '*'

        InternalThreadCommand.__init__(self, thread_id, method, *args, **kwargs)

        self.executed = False
        self.lock = thread.allocate_lock()
示例#2
0
class TracingFunctionHolder:
    '''This class exists just to keep some variables (so that we don't keep them in the global namespace). 
    '''
    _original_tracing = None
    _warn = True
    _lock = thread.allocate_lock()
    _traceback_limit = 1
    _warnings_shown = {}
示例#3
0
        def _init(self):
            if self._rlock:
                self._lock = threading.RLock()
            else:
                self._lock = thread.allocate_lock()

            self.acquire = self._lock.acquire
            self.release = self._lock.release
            _fork_safe_locks.append(weakref.ref(self))
示例#4
0
def custom_frames_container_init(): #Note: no staticmethod on jython 2.1 (so, use free-function)

    CustomFramesContainer.custom_frames_lock = thread.allocate_lock()

    # custom_frames can only be accessed if properly locked with custom_frames_lock!
    # Key is a string identifying the frame (as well as the thread it belongs to).
    # Value is a CustomFrame.
    #
    CustomFramesContainer.custom_frames = {}

    # Only to be used in this module
    CustomFramesContainer._next_frame_id = 0

    # This is the event we must set to release an internal process events. It's later set by the actual debugger
    # when we do create the debugger.
    CustomFramesContainer._py_db_command_thread_event = Null()
    def __init__(self):
        PyDBAdditionalThreadInfoOriginal.__init__(self)
        #That's where the last frame entered is kept. That's needed so that we're able to
        #trace contexts that were previously untraced and are currently active. So, the bad thing
        #is that the frame may be kept alive longer than it would if we go up on the frame stack,
        #and is only disposed when some other frame is removed.
        #A better way would be if we could get the topmost frame for each thread, but that's
        #not possible (until python 2.5 -- which is the PyDBAdditionalThreadInfo version)
        #Or if the user compiled threadframe (from http://www.majid.info/mylos/stories/2004/06/10/threadframe.html)

        #NOT RLock!! (could deadlock if it was)
        self.lock = thread.allocate_lock()
        self._acquire_lock = self.lock.acquire
        self._release_lock = self.lock.release

        #collection with the refs
        d = {}
        self.pydev_existing_frames = d
        try:
            self._iter_frames = d.iterkeys
        except AttributeError:
            self._iter_frames = d.keys
    def __init__(self):
        PyDBAdditionalThreadInfoOriginal.__init__(self)
        #That's where the last frame entered is kept. That's needed so that we're able to
        #trace contexts that were previously untraced and are currently active. So, the bad thing
        #is that the frame may be kept alive longer than it would if we go up on the frame stack,
        #and is only disposed when some other frame is removed.
        #A better way would be if we could get the topmost frame for each thread, but that's
        #not possible (until python 2.5 -- which is the PyDBAdditionalThreadInfo version)
        #Or if the user compiled threadframe (from http://www.majid.info/mylos/stories/2004/06/10/threadframe.html)

        #NOT RLock!! (could deadlock if it was)
        self.lock = thread.allocate_lock()
        self._acquire_lock = self.lock.acquire
        self._release_lock = self.lock.release

        #collection with the refs
        d = {}
        self.pydev_existing_frames = d
        try:
            self._iter_frames = d.iterkeys
        except AttributeError:
            self._iter_frames = d.keys
示例#7
0
class AdditionalFramesContainer:
    lock = thread.allocate_lock()
    additional_frames = {}  # dict of dicts
示例#8
0
def set_trace_to_threads(tracing_func):
    lib = load_python_helper_lib()
    if lib is None:  # This is the case if it's not CPython.
        pydev_log.info(
            'Unable to load helper lib to set tracing to all threads (unsupported python vm).'
        )
        return -1

    pydev_log.info(
        'Successfully Loaded helper lib to set tracing to all threads.')

    ret = 0
    set_trace_func = TracingFunctionHolder._original_tracing or sys.settrace

    # Note: use sys._current_frames() keys to get the thread ids because it'll return
    # thread ids created in C/C++ where there's user code running, unlike the APIs
    # from the threading module which see only threads created through it (unless
    # a call for threading.current_thread() was previously done in that thread,
    # in which case a dummy thread would've been created for it).
    thread_idents = set(sys._current_frames().keys())
    thread_idents = thread_idents.difference(
        # Ignore pydevd threads.
        set(t.ident for t in threading.enumerate()
            if getattr(t, 'pydev_do_not_trace', False)))

    curr_ident = thread.get_ident()
    curr_thread = threading._active.get(curr_ident)

    for thread_ident in thread_idents:
        # If that thread is not available in the threading module we also need to create a
        # dummy thread for it (otherwise it'll be invisible to the debugger).
        if thread_ident not in threading._active:

            class _DummyThread(threading._DummyThread):
                def _set_ident(self):
                    # Note: Hack to set the thread ident that we want.
                    if IS_PY2:
                        self._Thread__ident = thread_ident
                    else:
                        self._ident = thread_ident

            t = _DummyThread()
            # Reset to the base class (don't expose our own version of the class).
            t.__class__ = threading._DummyThread

            with threading._active_limbo_lock:
                # On Py2 it'll put in active getting the current indent, not using the
                # ident that was set, so, we have to update it (should be harmless on Py3
                # so, do it always).
                threading._active[thread_ident] = t
                threading._active[curr_ident] = curr_thread

                if t.ident != thread_ident:
                    # Check if it actually worked.
                    pydev_log.critical(
                        'pydevd: creation of _DummyThread with fixed thread ident did not succeed.'
                    )

        # Some (ptvsd) tests failed because of this, so, leave it always disabled for now.
        # show_debug_info = 1 if DebugInfoHolder.DEBUG_TRACE_LEVEL >= 1 else 0
        show_debug_info = 0

        # Hack to increase _Py_TracingPossible.
        # See comments on py_custom_pyeval_settrace.hpp
        proceed = thread.allocate_lock()
        proceed.acquire()

        def dummy_trace(frame, event, arg):
            return dummy_trace

        def increase_tracing_count():
            SetTrace(dummy_trace)
            proceed.release()

        start_new_thread = pydev_monkey.get_original_start_new_thread(thread)
        start_new_thread(increase_tracing_count, ())
        proceed.acquire()  # Only proceed after the release() is done.
        proceed = None

        result = lib.AttachDebuggerTracing(
            ctypes.c_int(show_debug_info),
            ctypes.py_object(set_trace_func),
            ctypes.py_object(tracing_func),
            ctypes.c_uint(thread_ident),
            ctypes.py_object(None),
        )
        if result != 0:
            pydev_log.info(
                'Unable to set tracing for existing thread. Result: %s',
                result)
            ret = result

    return ret
    for name in patched_modules:
        del sys.modules[name]

    # import for side effects
    import _pydev_imps._pydev_saved_modules

    for name in patched_modules:
        sys.modules[name] = patched_modules[name]


if USE_LIB_COPY:
    protect_libraries_from_patching()


from _pydev_imps._pydev_saved_modules import thread
_nextThreadIdLock = thread.allocate_lock()

if IS_PY3K:
    def dict_keys(d):
        return list(d.keys())

    def dict_values(d):
        return list(d.values())

    dict_iter_values = dict.values

    def dict_iter_items(d):
        return d.items()

    def dict_items(d):
        return list(d.items())
    for name in patched_modules:
        del sys.modules[name]

    # import for side effects
    import _pydev_imps._pydev_saved_modules

    for name in patched_modules:
        sys.modules[name] = patched_modules[name]


if USE_LIB_COPY:
    protect_libraries_from_patching()

from _pydev_imps._pydev_saved_modules import thread
_thread_id_lock = thread.allocate_lock()
thread_get_ident = thread.get_ident

if IS_PY3K:

    def dict_keys(d):
        return list(d.keys())

    def dict_values(d):
        return list(d.values())

    dict_iter_values = dict.values

    def dict_iter_items(d):
        return d.items()
示例#11
0
def set_trace_to_threads(tracing_func):
    lib = load_python_helper_lib()
    if lib is None:  # This is the case if it's not CPython.
        return -1

    if hasattr(sys, 'getswitchinterval'):
        get_interval, set_interval = sys.getswitchinterval, sys.setswitchinterval
    else:
        get_interval, set_interval = sys.getcheckinterval, sys.setcheckinterval

    prev_value = get_interval()
    ret = 0
    try:
        if not IS_PY37_OR_GREATER:
            # Prevent going to any other thread... if we switch the thread during this operation we
            # could potentially corrupt the interpreter.
            # Note: on CPython 3.7 onwards this is not needed (we have a different implementation
            # for setting the tracing for other threads in this case).
            set_interval(2 ** 15)

        set_trace_func = TracingFunctionHolder._original_tracing or sys.settrace

        # Note: use sys._current_frames() keys to get the thread ids because it'll return
        # thread ids created in C/C++ where there's user code running, unlike the APIs
        # from the threading module which see only threads created through it (unless
        # a call for threading.current_thread() was previously done in that thread,
        # in which case a dummy thread would've been created for it).
        thread_idents = set(sys._current_frames().keys())
        thread_idents = thread_idents.difference(
            # Ignore pydevd threads.
            set(t.ident for t in threading.enumerate() if getattr(t, 'pydev_do_not_trace', False))
        )

        curr_ident = thread.get_ident()
        curr_thread = threading._active.get(curr_ident)

        for thread_ident in thread_idents:
            # If that thread is not available in the threading module we also need to create a
            # dummy thread for it (otherwise it'll be invisible to the debugger).
            if thread_ident not in threading._active:

                class _DummyThread(threading._DummyThread):

                    def _set_ident(self):
                        # Note: Hack to set the thread ident that we want.
                        if IS_PY2:
                            self._Thread__ident = thread_ident
                        else:
                            self._ident = thread_ident

                t = _DummyThread()
                # Reset to the base class (don't expose our own version of the class).
                t.__class__ = threading._DummyThread

                with threading._active_limbo_lock:
                    # On Py2 it'll put in active getting the current indent, not using the
                    # ident that was set, so, we have to update it (should be harmless on Py3
                    # so, do it always).
                    threading._active[thread_ident] = t
                    threading._active[curr_ident] = curr_thread

                    if t.ident != thread_ident:
                        # Check if it actually worked.
                        pydev_log.error('pydevd: creation of _DummyThread with fixed thread ident did not succeed.')

            # Some (ptvsd) tests failed because of this, so, leave it always disabled for now.
            # show_debug_info = 1 if DebugInfoHolder.DEBUG_TRACE_LEVEL >= 1 else 0
            show_debug_info = 0

            if IS_PY37_OR_GREATER:
                # Hack to increase _Py_TracingPossible.
                # See comments on py_settrace_37.hpp
                proceed = thread.allocate_lock()
                proceed.acquire()

                def dummy_trace_on_py37(frame, event, arg):
                    return dummy_trace_on_py37

                def increase_tracing_count_on_py37():
                    SetTrace(dummy_trace_on_py37)
                    proceed.release()

                start_new_thread = pydev_monkey.get_original_start_new_thread(thread)
                start_new_thread(increase_tracing_count_on_py37, ())
                proceed.acquire()  # Only proceed after the release() is done.
                proceed = None

            result = lib.AttachDebuggerTracing(
                ctypes.c_int(show_debug_info),
                ctypes.py_object(set_trace_func),
                ctypes.py_object(tracing_func),
                ctypes.c_uint(thread_ident),
                ctypes.py_object(None),
            )
            if result != 0:
                pydev_log.info('Unable to set tracing for existing threads. Result: %s' % result)
                ret = result
    finally:
        if not IS_PY37_OR_GREATER:
            set_interval(prev_value)

    return ret
    for name in patched_modules:
        del sys.modules[name]

    # import for side effects
    import _pydev_imps._pydev_saved_modules

    for name in patched_modules:
        sys.modules[name] = patched_modules[name]


if USE_LIB_COPY:
    protect_libraries_from_patching()


from _pydev_imps._pydev_saved_modules import thread
_nextThreadIdLock = thread.allocate_lock()

#=======================================================================================================================
# Jython?
#=======================================================================================================================
try:
    dict_contains = dict.has_key
except:
    try:
        #Py3k does not have has_key anymore, and older versions don't have __contains__
        dict_contains = dict.__contains__
    except:
        try:
            dict_contains = dict.has_key
        except NameError:
            def dict_contains(d, key):
示例#13
0
    for name in patched_modules:
        del sys.modules[name]

    # import for side effects
    import _pydev_imps._pydev_saved_modules

    for name in patched_modules:
        sys.modules[name] = patched_modules[name]


if USE_LIB_COPY:
    protect_libraries_from_patching()

from _pydev_imps._pydev_saved_modules import thread
_thread_id_lock = thread.allocate_lock()
thread_get_ident = thread.get_ident

if IS_PY3K:

    def dict_keys(d):
        return list(d.keys())

    def dict_values(d):
        return list(d.values())

    dict_iter_values = dict.values

    def dict_iter_items(d):
        return d.items()
示例#14
0
def set_trace_to_threads(tracing_func,
                         thread_idents=None,
                         create_dummy_thread=True):
    assert tracing_func is not None

    ret = 0

    # Note: use sys._current_frames() keys to get the thread ids because it'll return
    # thread ids created in C/C++ where there's user code running, unlike the APIs
    # from the threading module which see only threads created through it (unless
    # a call for threading.current_thread() was previously done in that thread,
    # in which case a dummy thread would've been created for it).
    if thread_idents is None:
        thread_idents = set(sys._current_frames().keys())

        for t in threading.enumerate():
            # PY-44778: ignore pydevd threads and also add any thread that wasn't found on
            # sys._current_frames() as some existing threads may not appear in
            # sys._current_frames() but may be available through the `threading` module.
            if getattr(t, 'pydev_do_not_trace', False):
                thread_idents.discard(t.ident)
            else:
                thread_idents.add(t.ident)

    curr_ident = thread.get_ident()
    curr_thread = threading._active.get(curr_ident)

    if curr_ident in thread_idents and len(thread_idents) != 1:
        # The current thread must be updated first (because we need to set
        # the reference to `curr_thread`).
        thread_idents = list(thread_idents)
        thread_idents.remove(curr_ident)
        thread_idents.insert(0, curr_ident)

    for thread_ident in thread_idents:
        # If that thread is not available in the threading module we also need to create a
        # dummy thread for it (otherwise it'll be invisible to the debugger).
        if create_dummy_thread:
            if thread_ident not in threading._active:

                class _DummyThread(threading._DummyThread):
                    def _set_ident(self):
                        # Note: Hack to set the thread ident that we want.
                        if IS_PY2:
                            self._Thread__ident = thread_ident
                        else:
                            self._ident = thread_ident

                t = _DummyThread()
                # Reset to the base class (don't expose our own version of the class).
                t.__class__ = threading._DummyThread

                if thread_ident == curr_ident:
                    curr_thread = t

                with threading._active_limbo_lock:
                    # On Py2 it'll put in active getting the current indent, not using the
                    # ident that was set, so, we have to update it (should be harmless on Py3
                    # so, do it always).
                    threading._active[thread_ident] = t
                    threading._active[curr_ident] = curr_thread

                    if t.ident != thread_ident:
                        # Check if it actually worked.
                        pydev_log.critical(
                            'pydevd: creation of _DummyThread with fixed thread ident did not succeed.'
                        )

        # Some (ptvsd) tests failed because of this, so, leave it always disabled for now.
        # show_debug_info = 1 if DebugInfoHolder.DEBUG_TRACE_LEVEL >= 1 else 0
        show_debug_info = 0

        # Hack to increase _Py_TracingPossible.
        # See comments on py_custom_pyeval_settrace.hpp
        proceed = thread.allocate_lock()
        proceed.acquire()

        def dummy_trace(frame, event, arg):
            return dummy_trace

        def increase_tracing_count():
            set_trace = TracingFunctionHolder._original_tracing or sys.settrace
            set_trace(dummy_trace)
            proceed.release()

        start_new_thread = pydev_monkey.get_original_start_new_thread(thread)
        start_new_thread(increase_tracing_count, ())
        proceed.acquire()  # Only proceed after the release() is done.
        proceed = None

        # Note: The set_trace_func is not really used anymore in the C side.
        set_trace_func = TracingFunctionHolder._original_tracing or sys.settrace

        lib = _load_python_helper_lib()
        if lib is None:  # This is the case if it's not CPython.
            pydev_log.info(
                'Unable to load helper lib to set tracing to all threads (unsupported python vm).'
            )
            ret = -1
        else:
            try:
                result = lib.AttachDebuggerTracing(
                    ctypes.c_int(show_debug_info),
                    ctypes.py_object(set_trace_func),
                    ctypes.py_object(tracing_func),
                    ctypes.c_uint(thread_ident),
                    ctypes.py_object(None),
                )
            except:
                if DebugInfoHolder.DEBUG_TRACE_LEVEL >= 1:
                    # There is no need to show this unless debug tracing is enabled.
                    pydev_log.exception('Error attaching debugger tracing')
                ret = -1
            else:
                if result != 0:
                    pydev_log.info(
                        'Unable to set tracing for existing thread. Result: %s',
                        result)
                    ret = result

    return ret