def add_custom_frame(frame, name, thread_id):
    '''
    It's possible to show paused frames by adding a custom frame through this API (it's
    intended to be used for coroutines, but could potentially be used for generators too).

    :param frame:
        The topmost frame to be shown paused when a thread with thread.ident == thread_id is paused.

    :param name:
        The name to be shown for the custom thread in the UI.

    :param thread_id:
        The thread id to which this frame is related (must match thread.ident).

    :return: str
        Returns the custom thread id which will be used to show the given frame paused.
    '''
    with CustomFramesContainer.custom_frames_lock:
        curr_thread_id = get_current_thread_id(threading.current_thread())
        next_id = CustomFramesContainer._next_frame_id = CustomFramesContainer._next_frame_id + 1

        # Note: the frame id kept contains an id and thread information on the thread where the frame was added
        # so that later on we can check if the frame is from the current thread by doing frame_id.endswith('|'+thread_id).
        frame_custom_thread_id = '__frame__:%s|%s' % (next_id, curr_thread_id)
        if DEBUG:
            sys.stderr.write(
                'add_custom_frame: %s (%s) %s %s\n' %
                (frame_custom_thread_id,
                 get_abs_path_real_path_and_base_from_frame(frame)[-1],
                 frame.f_lineno, frame.f_code.co_name))

        CustomFramesContainer.custom_frames[
            frame_custom_thread_id] = CustomFrame(name, frame, thread_id)
        CustomFramesContainer._py_db_command_thread_event.set()
        return frame_custom_thread_id
Esempio n. 2
0
def _pydev_needs_stop_at_break(line):
    '''
    We separate the functionality into 2 functions so that we can generate a bytecode which
    generates a spurious line change so that we can do:

    if _pydev_needs_stop_at_break():
        # Set line to line -1
        _pydev_stop_at_break()
        # then, proceed to go to the current line
        # (which will then trigger a line event).
    '''
    t = threading.current_thread()
    try:
        additional_info = t.additional_info
    except:
        additional_info = set_additional_thread_info(t)

    if additional_info.is_tracing:
        return False

    additional_info.is_tracing += 1
    try:
        frame = sys._getframe(1)
        # print('pydev needs stop at break?', line, 'curr line', frame.f_lineno, 'curr trace', frame.f_trace)
        if frame.f_trace is not None:
            # i.e.: this frame is already being traced, thus, we don't need to use programmatic breakpoints.
            return False

        py_db = get_global_debugger()
        if py_db is None:
            return False

        try:
            abs_path_real_path_and_base = NORM_PATHS_AND_BASE_CONTAINER[
                frame.f_code.co_filename]
        except:
            abs_path_real_path_and_base = get_abs_path_real_path_and_base_from_frame(
                frame)
        canonical_normalized_filename = abs_path_real_path_and_base[1]

        try:
            python_breakpoint = py_db.breakpoints[
                canonical_normalized_filename][line]
        except:
            # print("Couldn't find breakpoint in the file %s on line %s" % (frame.f_code.co_filename, line))
            # Could be KeyError if line is not there or TypeError if breakpoints_for_file is None.
            # Note: using catch-all exception for performance reasons (if the user adds a breakpoint
            # and then removes it after hitting it once, this method added for the programmatic
            # breakpoint will keep on being called and one of those exceptions will always be raised
            # here).
            return False

        if python_breakpoint:
            # print('YES')
            return True

    finally:
        additional_info.is_tracing -= 1

    return False
Esempio n. 3
0
def _pydev_stop_at_break(line):
    frame = sys._getframe(1)
    # print('pydevd SET TRACING at ', line, 'curr line', frame.f_lineno)
    t = threading.current_thread()
    try:
        additional_info = t.additional_info
    except:
        additional_info = set_additional_thread_info(t)

    if additional_info.is_tracing:
        return

    additional_info.is_tracing += 1
    try:
        py_db = get_global_debugger()
        if py_db is None:
            return

        pydev_log.debug(
            "Setting f_trace due to frame eval mode in file: %s on line %s",
            frame.f_code.co_filename, line)
        additional_info.trace_suspend_type = 'frame_eval'

        pydevd_frame_eval_cython_wrapper = sys.modules[
            '_pydevd_frame_eval.pydevd_frame_eval_cython_wrapper']
        thread_info = pydevd_frame_eval_cython_wrapper.get_thread_info_py()
        if thread_info.thread_trace_func is not None:
            frame.f_trace = thread_info.thread_trace_func
        else:
            frame.f_trace = py_db.get_thread_local_trace_func()
    finally:
        additional_info.is_tracing -= 1
Esempio n. 4
0
def dump_frames(thread_id):
    sys.stdout.write('dumping frames\n')
    if thread_id != get_current_thread_id(threading.current_thread()):
        raise VariableError("find_frame: must execute on same thread")

    frame = get_frame()
    for frame in iter_frames(frame):
        sys.stdout.write('%s\n' % pickle.dumps(frame))
Esempio n. 5
0
def get_interpreter():
    try:
        interpreterInterface = getattr(__builtin__, 'interpreter')
    except AttributeError:
        interpreterInterface = InterpreterInterface(None, None,
                                                    threading.current_thread())
        __builtin__.interpreter = interpreterInterface
        sys.stderr.write(interpreterInterface.get_greeting_msg())
        sys.stderr.flush()

    return interpreterInterface
Esempio n. 6
0
def start_server(host, port, client_port):
    # replace exit (see comments on method)
    # note that this does not work in jython!!! (sys method can't be replaced).
    sys.exit = do_exit

    interpreter = InterpreterInterface(host, client_port,
                                       threading.current_thread())

    start_new_thread(start_console_server, (host, port, interpreter))

    process_exec_queue(interpreter)
Esempio n. 7
0
        def do_connect_to_debugger():
            try:
                # Try to import the packages needed to attach the debugger
                import pydevd
                from _pydev_bundle._pydev_saved_modules import threading
            except:
                # This happens on Jython embedded in host eclipse
                traceback.print_exc()
                sys.stderr.write('pydevd is not available, cannot connect\n')

            from _pydevd_bundle.pydevd_constants import set_thread_id
            from _pydev_bundle import pydev_localhost
            set_thread_id(threading.current_thread(), "console_main")

            VIRTUAL_FRAME_ID = "1"  # matches PyStackFrameConsole.java
            VIRTUAL_CONSOLE_ID = "console_main"  # matches PyThreadConsole.java
            f = FakeFrame()
            f.f_back = None
            f.f_globals = {
            }  # As globals=locals here, let's simply let it empty (and save a bit of network traffic).
            f.f_locals = self.get_namespace()

            self.debugger = pydevd.PyDB()
            self.debugger.add_fake_frame(thread_id=VIRTUAL_CONSOLE_ID,
                                         frame_id=VIRTUAL_FRAME_ID,
                                         frame=f)
            try:
                pydevd.apply_debugger_options(debugger_options)
                self.debugger.connect(pydev_localhost.get_localhost(),
                                      debuggerPort)
                self.debugger.prepare_to_run()
                self.debugger.disable_tracing()
            except:
                traceback.print_exc()
                sys.stderr.write('Failed to connect to target debugger.\n')

            # Register to process commands when idle
            self.debugrunning = False
            try:
                import pydevconsole
                pydevconsole.set_debug_hook(
                    self.debugger.process_internal_commands)
            except:
                traceback.print_exc()
                sys.stderr.write(
                    'Version of Python does not support debuggable Interactive Console.\n'
                )
Esempio n. 8
0
    def new_func(py_db, frame, expression, is_exec):
        if py_db is None:
            # Only for testing...
            pydev_log.critical('_evaluate_with_timeouts called without py_db!')
            return original_func(py_db, frame, expression, is_exec)
        warn_evaluation_timeout = pydevd_constants.PYDEVD_WARN_EVALUATION_TIMEOUT
        curr_thread = threading.current_thread()

        def on_warn_evaluation_timeout():
            py_db.writer.add_command(
                py_db.cmd_factory.make_evaluation_timeout_msg(
                    py_db, expression, curr_thread))

        timeout_tracker = py_db.timeout_tracker  # : :type timeout_tracker: TimeoutTracker
        with timeout_tracker.call_on_timeout(warn_evaluation_timeout,
                                             on_warn_evaluation_timeout):
            return _run_with_unblock_threads(original_func, py_db, curr_thread,
                                             frame, expression, is_exec)
Esempio n. 9
0
    def run(self):
        created_pydb_daemon = self.py_db.created_pydb_daemon_threads
        created_pydb_daemon[self] = 1
        try:
            try:
                if IS_JYTHON and not isinstance(threading.current_thread(),
                                                threading._MainThread):
                    # we shouldn't update sys.modules for the main thread, cause it leads to the second importing 'threading'
                    # module, and the new instance of main thread is created
                    ss = JyCore.PySystemState()
                    # Note: Py.setSystemState() affects only the current thread.
                    JyCore.Py.setSystemState(ss)

                self._stop_trace()
                self._on_run()
            except:
                if sys is not None and pydev_log_exception is not None:
                    pydev_log_exception()
        finally:
            del created_pydb_daemon[self]
Esempio n. 10
0
    def __call__(self):
        # We monkey-patch the thread creation so that this function is called in the new thread. At this point
        # we notify of its creation and start tracing it.
        py_db = get_global_debugger()

        thread_id = None
        if py_db is not None:
            # Note: if this is a thread from threading.py, we're too early in the boostrap process (because we mocked
            # the start_new_thread internal machinery and thread._bootstrap has not finished), so, the code below needs
            # to make sure that we use the current thread bound to the original function and not use
            # threading.current_thread() unless we're sure it's a dummy thread.
            t = getattr(self.original_func, '__self__',
                        getattr(self.original_func, 'im_self', None))
            if not isinstance(t, threading.Thread):
                # This is not a threading.Thread but a Dummy thread (so, get it as a dummy thread using
                # currentThread).
                t = threading.current_thread()

            if not getattr(t, 'is_pydev_daemon_thread', False):
                thread_id = get_current_thread_id(t)
                py_db.notify_thread_created(thread_id, t)
                _on_set_trace_for_new_thread(py_db)

            if getattr(py_db, 'thread_analyser', None) is not None:
                try:
                    from _pydevd_bundle.pydevd_concurrency_analyser.pydevd_concurrency_logger import log_new_thread
                    log_new_thread(py_db, t)
                except:
                    sys.stderr.write(
                        "Failed to detect new thread for visualization")
        try:
            ret = self.original_func(*self.args, **self.kwargs)
        finally:
            if thread_id is not None:
                if py_db is not None:
                    # At thread shutdown we only have pydevd-related code running (which shouldn't
                    # be tracked).
                    py_db.disable_tracing()
                    py_db.notify_thread_not_alive(thread_id)

        return ret
Esempio n. 11
0
def create_interrupt_this_thread_callback():
    '''
    The idea here is returning a callback that when called will generate a KeyboardInterrupt
    in the thread that called this function.

    If this is the main thread, this means that it'll emulate a Ctrl+C (which may stop I/O
    and sleep operations).

    For other threads, this will call PyThreadState_SetAsyncExc to raise
    a KeyboardInterrupt before the next instruction (so, it won't really interrupt I/O or
    sleep operations).

    :return callable:
        Returns a callback that will interrupt the current thread (this may be called
        from an auxiliary thread).
    '''
    tid = thread_get_ident()

    if is_current_thread_main_thread():
        main_thread = threading.current_thread()

        def raise_on_this_thread():
            pydev_log.debug('Callback to interrupt main thread.')
            pydevd_utils.interrupt_main_thread(main_thread)

    else:

        # Note: this works in the sense that it can stop some cpu-intensive slow operation,
        # but we can't really interrupt the thread out of some sleep or I/O operation
        # (this will only be raised when Python is about to execute the next instruction).
        def raise_on_this_thread():
            if IS_CPYTHON:
                pydev_log.debug('Interrupt thread: %s', tid)
                ctypes.pythonapi.PyThreadState_SetAsyncExc(
                    ctypes.c_long(tid), ctypes.py_object(KeyboardInterrupt))
            else:
                pydev_log.debug(
                    'It is only possible to interrupt non-main threads in CPython.'
                )

    return raise_on_this_thread
Esempio n. 12
0
def getVariable(dbg, thread_id, frame_id, scope, attrs):
    """
    returns the value of a variable

    :scope: can be BY_ID, EXPRESSION, GLOBAL, LOCAL, FRAME

    BY_ID means we'll traverse the list of all objects alive to get the object.

    :attrs: after reaching the proper scope, we have to get the attributes until we find
            the proper location (i.e.: obj\tattr1\tattr2)

    :note: when BY_ID is used, the frame_id is considered the id of the object to find and
           not the frame (as we don't care about the frame in this case).
    """
    if scope == 'BY_ID':
        if thread_id != get_current_thread_id(threading.current_thread()):
            raise VariableError("getVariable: must execute on same thread")

        try:
            import gc
            objects = gc.get_objects()
        except:
            pass  # Not all python variants have it.
        else:
            frame_id = int(frame_id)
            for var in objects:
                if id(var) == frame_id:
                    if attrs is not None:
                        attrList = attrs.split('\t')
                        for k in attrList:
                            _type, _type_name, resolver = get_type(var)
                            var = resolver.resolve(var, k)

                    return var

        # If it didn't return previously, we coudn't find it by id (i.e.: alrceady garbage collected).
        sys.stderr.write('Unable to find object with id: %s\n' % (frame_id, ))
        return None

    frame = dbg.find_frame(thread_id, frame_id)
    if frame is None:
        return {}

    if attrs is not None:
        attrList = attrs.split('\t')
    else:
        attrList = []

    for attr in attrList:
        attr.replace("@_@TAB_CHAR@_@", '\t')

    if scope == 'EXPRESSION':
        for count in range(len(attrList)):
            if count == 0:
                # An Expression can be in any scope (globals/locals), therefore it needs to evaluated as an expression
                var = evaluate_expression(dbg, frame, attrList[count], False)
            else:
                _type, _type_name, resolver = get_type(var)
                var = resolver.resolve(var, attrList[count])
    else:
        if scope == "GLOBAL":
            var = frame.f_globals
            del attrList[
                0]  # globals are special, and they get a single dummy unused attribute
        else:
            # in a frame access both locals and globals as Python does
            var = {}
            var.update(frame.f_globals)
            var.update(frame.f_locals)

        for k in attrList:
            _type, _type_name, resolver = get_type(var)
            var = resolver.resolve(var, k)

    return var
def set_trace_in_qt():
    from _pydevd_bundle.pydevd_comm import get_global_debugger
    py_db = get_global_debugger()
    if py_db is not None:
        threading.current_thread()  # Create the dummy thread for qt.
        py_db.enable_tracing()
Esempio n. 14
0
    if int(port) == 0 and int(client_port) == 0:
        (h, p) = pydev_localhost.get_socket_name()
        client_port = p

    host = pydev_localhost.get_localhost()

    #replace exit (see comments on method)
    #note that this does not work in jython!!! (sys method can't be replaced).
    sys.exit = skip_successful_exit

    connect_status_queue = _queue.Queue()
    interpreter = InterpreterInterface(
        host,
        int(client_port),
        threading.current_thread(),
        connect_status_queue=connect_status_queue)

    server_thread = threading.Thread(target=start_console_server,
                                     name='ServerThread',
                                     args=(host, int(port), interpreter))
    server_thread.daemon = True
    server_thread.start()

    sys.stdin = StdIn(interpreter, host, client_port, sys.stdin)

    init_mpl_in_console(interpreter)

    try:
        success = connect_status_queue.get(True, 60)
        if not success:
Esempio n. 15
0
def is_current_thread_main_thread():
    if hasattr(threading, 'main_thread'):
        return threading.current_thread() is threading.main_thread()
    else:
        return isinstance(threading.current_thread(), threading._MainThread)