#IMPORTANT: pydevd_constants must be the 1st thing defined because it'll keep a reference to the original sys._getframe
from __future__ import nested_scopes # Jython 2.1 support
from pydevd_constants import * # @UnusedWildImport

import pydev_monkey_qt
pydev_monkey_qt.patch_qt()

import traceback

from django_debug import DjangoLineBreakpoint
from pydevd_frame import add_exception_to_frame
import pydev_imports
from pydevd_breakpoints import * #@UnusedWildImport
import fix_getpass
from pydevd_comm import  CMD_CHANGE_VARIABLE, \
                         CMD_EVALUATE_EXPRESSION, \
                         CMD_EXEC_EXPRESSION, \
                         CMD_GET_COMPLETIONS, \
                         CMD_GET_FRAME, \
                         CMD_GET_VARIABLE, \
                         CMD_LIST_THREADS, \
                         CMD_REMOVE_BREAK, \
                         CMD_RUN, \
                         CMD_SET_BREAK, \
                         CMD_SET_NEXT_STATEMENT,\
                         CMD_STEP_INTO, \
                         CMD_STEP_OVER, \
                         CMD_STEP_RETURN, \
                         CMD_THREAD_CREATE, \
                         CMD_THREAD_KILL, \
                         CMD_THREAD_RUN, \
                         CMD_THREAD_SUSPEND, \
                         CMD_RUN_TO_LINE, \
                         CMD_RELOAD_CODE, \
                         CMD_VERSION, \
                         CMD_CONSOLE_EXEC, \
                         CMD_ADD_EXCEPTION_BREAK, \
                         CMD_REMOVE_EXCEPTION_BREAK, \
                         CMD_LOAD_SOURCE, \
                         CMD_ADD_DJANGO_EXCEPTION_BREAK, \
                         CMD_REMOVE_DJANGO_EXCEPTION_BREAK, \
                         CMD_SMART_STEP_INTO,\
                         InternalChangeVariable, \
                         InternalGetCompletions, \
                         InternalEvaluateExpression, \
                         InternalConsoleExec, \
                         InternalGetFrame, \
                         InternalGetVariable, \
                         InternalTerminateThread, \
                         InternalRunThread, \
                         InternalStepThread, \
                         NetCommand, \
                         NetCommandFactory, \
                         PyDBDaemonThread, \
                         _queue, \
                         ReaderThread, \
                         SetGlobalDebugger, \
                         WriterThread, \
                         PydevdFindThreadById, \
                         PydevdLog, \
                         StartClient, \
                         StartServer, \
                         InternalSetNextStatementThread, \
                         ReloadCodeCommand, \
                         ID_TO_MEANING,\
                         CMD_SET_PY_EXCEPTION, \
                         CMD_IGNORE_THROWN_EXCEPTION_AT,\
                         InternalGetBreakpointException, \
                         InternalSendCurrExceptionTrace,\
                         InternalSendCurrExceptionTraceProceeded,\
                         CMD_ENABLE_DONT_TRACE, \
                         CMD_GET_FILE_CONTENTS,\
                         CMD_SET_PROPERTY_TRACE, CMD_RUN_CUSTOM_OPERATION,\
                         InternalRunCustomOperation, CMD_EVALUATE_CONSOLE_EXPRESSION, InternalEvaluateConsoleExpression,\
                         InternalConsoleGetCompletions

from pydevd_file_utils import NormFileToServer, GetFilenameAndBase
import pydevd_file_utils
import pydevd_vars
import pydevd_vm_type
import pydevd_tracing
import pydevd_io
from pydevd_additional_thread_info import PyDBAdditionalThreadInfo
from pydevd_custom_frames import CustomFramesContainer, CustomFramesContainerInit
import pydevd_dont_trace
import pydevd_traceproperty

from _pydev_imps import _pydev_time as time, _pydev_thread

import _pydev_threading as threading

import os
import atexit


threadingEnumerate = threading.enumerate
threadingCurrentThread = threading.currentThread

try:
    'dummy'.encode('utf-8') # Added because otherwise Jython 2.2.1 wasn't finding the encoding (if it wasn't loaded in the main thread).
except:
    pass

DONT_TRACE = {
              # commonly used things from the stdlib that we don't want to trace
              'Queue.py':1,
              'queue.py':1,
              'socket.py':1,
              'weakref.py':1,
              'linecache.py':1,
              'threading.py':1,

              #things from pydev that we don't want to trace
              '_pydev_execfile.py':1,
              '_pydev_jython_execfile.py':1,
              '_pydev_threading':1,
              '_pydev_Queue':1,
              'django_debug.py':1,
              'django_frame.py':1,
              'pydev_log.py':1,
              'pydev_monkey.py':1 ,
              'pydevd.py':1 ,
              'pydevd_additional_thread_info.py':1,
              'pydevd_comm.py':1,
              'pydevd_console.py':1 ,
              'pydevd_constants.py':1,
              'pydevd_custom_frames.py':1,
              'pydevd_dont_trace.py':1,
              'pydevd_exec.py':1,
              'pydevd_exec2.py':1,
              'pydevd_file_utils.py':1,
              'pydevd_frame.py':1,
              'pydevd_import_class.py':1 ,
              'pydevd_io.py':1 ,
              'pydevd_psyco_stub.py':1,
              'pydevd_referrers.py':1 ,
              'pydevd_reload.py':1 ,
              'pydevd_resolver.py':1 ,
              'pydevd_save_locals.py':1 ,
              'pydevd_signature.py':1,
              'pydevd_stackless.py':1 ,
              'pydevd_traceproperty.py':1,
              'pydevd_tracing.py':1 ,
              'pydevd_utils.py':1,
              'pydevd_vars.py':1,
              'pydevd_vm_type.py':1,
              'pydevd_xml.py':1,
            }

if IS_PY3K:
    # if we try to trace io.py it seems it can get halted (see http://bugs.python.org/issue4716)
    DONT_TRACE['io.py'] = 1

    # Don't trace common encodings too
    DONT_TRACE['cp1252.py'] = 1
    DONT_TRACE['utf_8.py'] = 1


connected = False
bufferStdOutToServer = False
bufferStdErrToServer = False
remote = False

from _pydev_filesystem_encoding import getfilesystemencoding
file_system_encoding = getfilesystemencoding()


# Hack for https://sw-brainwy.rhcloud.com/tracker/PyDev/363 (i.e.: calling isAlive() can throw AssertionError under some circumstances)
# It is required to debug threads started by start_new_thread in Python 3.4
_temp = threading.Thread()
if hasattr(_temp, '_is_stopped'): # Python 3.4 has this
    def isThreadAlive(t):
        try:
            return not t._is_stopped
        except:
            return t.isAlive()
    
elif hasattr(_temp, '_Thread__stopped'): # Python 2.7 has this
    def isThreadAlive(t):
        try:
            return not t._Thread__stopped
        except:
            return t.isAlive()
    
else: # Haven't checked all other versions, so, let's use the regular isAlive call in this case.
    def isThreadAlive(t):
        return t.isAlive()
del _temp

#=======================================================================================================================
# PyDBCommandThread
#=======================================================================================================================
class PyDBCommandThread(PyDBDaemonThread):

    def __init__(self, pyDb):
        PyDBDaemonThread.__init__(self)
        self._py_db_command_thread_event = pyDb._py_db_command_thread_event
        self.pyDb = pyDb
        self.setName('pydevd.CommandThread')

    def OnRun(self):
        for i in xrange(1, 10):
            time.sleep(0.5) #this one will only start later on (because otherwise we may not have any non-daemon threads
            if self.killReceived:
                return

        if self.dontTraceMe:
            self.pyDb.SetTrace(None) # no debugging on this thread

        try:
            while not self.killReceived:
                try:
                    self.pyDb.processInternalCommands()
                except:
                    PydevdLog(0, 'Finishing debug communication...(2)')
                self._py_db_command_thread_event.clear()
                self._py_db_command_thread_event.wait(0.5)
        except:
            pydev_log.debug(sys.exc_info()[0])

            #only got this error in interpreter shutdown
            #PydevdLog(0, 'Finishing debug communication...(3)')


def killAllPydevThreads():
    threads = DictKeys(PyDBDaemonThread.created_pydb_daemon_threads)
    for t in threads:
        if hasattr(t, 'doKillPydevThread'):
            t.doKillPydevThread()


#=======================================================================================================================
# PyDBCheckAliveThread
#=======================================================================================================================
class PyDBCheckAliveThread(PyDBDaemonThread):

    def __init__(self, pyDb):
        PyDBDaemonThread.__init__(self)
        self.pyDb = pyDb
        self.setName('pydevd.CheckAliveThread')

    def OnRun(self):
            if self.dontTraceMe:

                disable_tracing = True
        
                if pydevd_vm_type.GetVmType() == pydevd_vm_type.PydevdVmType.JYTHON and sys.hexversion <= 0x020201f0:
                    # don't run untraced threads if we're in jython 2.2.1 or lower
                    # jython bug: if we start a thread and another thread changes the tracing facility
                    # it affects other threads (it's not set only for the thread but globally)
                    # Bug: http://sourceforge.net/tracker/index.php?func=detail&aid=1870039&group_id=12867&atid=112867
                    disable_tracing = False
        
                if disable_tracing:
                    pydevd_tracing.SetTrace(None)  # no debugging on this thread
                    
            while not self.killReceived:
                if not self.pyDb.haveAliveThreads():
                    try:
                        pydev_log.debug("No alive threads, finishing debug session")
                        self.pyDb.FinishDebuggingSession()
                        killAllPydevThreads()
                    except:
                        traceback.print_exc()

                    self.killReceived = True
                    return

                time.sleep(0.3)

    def doKillPydevThread(self):
        pass



#=======================================================================================================================
# PyDB
#=======================================================================================================================
class PyDB:
    """ Main debugging class
    Lots of stuff going on here:

    PyDB starts two threads on startup that connect to remote debugger (RDB)
    The threads continuously read & write commands to RDB.
    PyDB communicates with these threads through command queues.
       Every RDB command is processed by calling processNetCommand.
       Every PyDB net command is sent to the net by posting NetCommand to WriterThread queue

       Some commands need to be executed on the right thread (suspend/resume & friends)
       These are placed on the internal command queue.
    """


    def __init__(self):
        SetGlobalDebugger(self)
        pydevd_tracing.ReplaceSysSetTraceFunc()
        self.reader = None
        self.writer = None
        self.quitting = None
        self.cmdFactory = NetCommandFactory()
        self._cmd_queue = {}  # the hash of Queues. Key is thread id, value is thread

        self.breakpoints = {}
        self.django_breakpoints = {}

        self.file_to_id_to_line_breakpoint = {}
        self.file_to_id_to_django_breakpoint = {}

        # Note: breakpoints dict should not be mutated: a copy should be created
        # and later it should be assigned back (to prevent concurrency issues).
        self.break_on_uncaught_exceptions = {}
        self.break_on_caught_exceptions = {}

        self.django_exception_break = {}
        self.readyToRun = False
        self._main_lock = _pydev_thread.allocate_lock()
        self._lock_running_thread_ids = _pydev_thread.allocate_lock()
        self._py_db_command_thread_event = threading.Event()
        CustomFramesContainer._py_db_command_thread_event = self._py_db_command_thread_event
        self._finishDebuggingSession = False
        self._terminationEventSent = False
        self.signature_factory = None
        self.SetTrace = pydevd_tracing.SetTrace
        self.break_on_exceptions_thrown_in_same_context = False
        self.ignore_exceptions_thrown_in_lines_with_ignore_exception = True

        # Suspend debugger even if breakpoint condition raises an exception
        SUSPEND_ON_BREAKPOINT_EXCEPTION = True
        self.suspend_on_breakpoint_exception = SUSPEND_ON_BREAKPOINT_EXCEPTION

        # By default user can step into properties getter/setter/deleter methods
        self.disable_property_trace = False
        self.disable_property_getter_trace = False
        self.disable_property_setter_trace = False
        self.disable_property_deleter_trace = False

        #this is a dict of thread ids pointing to thread ids. Whenever a command is passed to the java end that
        #acknowledges that a thread was created, the thread id should be passed here -- and if at some time we do not
        #find that thread alive anymore, we must remove it from this list and make the java side know that the thread
        #was killed.
        self._running_thread_ids = {}
        self._set_breakpoints_with_id = False

        # This attribute holds the file-> lines which have an @IgnoreException.
        self.filename_to_lines_where_exceptions_are_ignored = {}


    def haveAliveThreads(self):
        for t in threadingEnumerate():
            if isinstance(t, PyDBDaemonThread):
                pydev_log.error_once(
                    'Error in debugger: Found PyDBDaemonThread through threading.enumerate().\n')
                
            if getattr(t, 'is_pydev_daemon_thread', False):
                #Important: Jython 2.5rc4 has a bug where a thread created with thread.start_new_thread won't be
                #set as a daemon thread, so, we also have to check for the 'is_pydev_daemon_thread' flag.
                #See: https://github.com/fabioz/PyDev.Debugger/issues/11
                continue
            
            if isThreadAlive(t) and not t.isDaemon():
                return True

        return False

    def FinishDebuggingSession(self):
        self._finishDebuggingSession = True

    def acquire(self):
        if PyDBUseLocks:
            self.lock.acquire()
        return True

    def release(self):
        if PyDBUseLocks:
            self.lock.release()
        return True

    def initializeNetwork(self, sock):
        try:
            sock.settimeout(None)  # infinite, no timeouts from now on - jython does not have it
        except:
            pass
        self.writer = WriterThread(sock)
        self.reader = ReaderThread(sock)
        self.writer.start()
        self.reader.start()

        time.sleep(0.1)  # give threads time to start

    def connect(self, host, port):
        if host:
            s = StartClient(host, port)
        else:
            s = StartServer(port)

        self.initializeNetwork(s)


    def getInternalQueue(self, thread_id):
        """ returns internal command queue for a given thread.
        if new queue is created, notify the RDB about it """
        if thread_id.startswith('__frame__'):
            thread_id = thread_id[thread_id.rfind('|') + 1:]
        try:
            return self._cmd_queue[thread_id]
        except KeyError:
            return self._cmd_queue.setdefault(thread_id, _queue.Queue()) #@UndefinedVariable


    def postInternalCommand(self, int_cmd, thread_id):
        """ if thread_id is *, post to all """
        if thread_id == "*":
            threads = threadingEnumerate()
            for t in threads:
                thread_id = GetThreadId(t)
                queue = self.getInternalQueue(thread_id)
                queue.put(int_cmd)

        else:
            queue = self.getInternalQueue(thread_id)
            queue.put(int_cmd)

    def checkOutputRedirect(self):
        global bufferStdOutToServer
        global bufferStdErrToServer

        if bufferStdOutToServer:
            initStdoutRedirect()
            self.checkOutput(sys.stdoutBuf, 1) #@UndefinedVariable

        if bufferStdErrToServer:
            initStderrRedirect()
            self.checkOutput(sys.stderrBuf, 2) #@UndefinedVariable

    def checkOutput(self, out, outCtx):
        '''Checks the output to see if we have to send some buffered output to the debug server

        @param out: sys.stdout or sys.stderr
        @param outCtx: the context indicating: 1=stdout and 2=stderr (to know the colors to write it)
        '''

        try:
            v = out.getvalue()

            if v:
                self.cmdFactory.makeIoMessage(v, outCtx, self)
        except:
            traceback.print_exc()


    def processInternalCommands(self):
        '''This function processes internal commands
        '''
        self._main_lock.acquire()
        try:

            self.checkOutputRedirect()

            curr_thread_id = GetThreadId(threadingCurrentThread())
            program_threads_alive = {}
            all_threads = threadingEnumerate()
            program_threads_dead = []
            self._lock_running_thread_ids.acquire()
            try:
                for t in all_threads:
                    thread_id = GetThreadId(t)

                    if isinstance(t, PyDBDaemonThread):
                        pydev_log.error_once('Found PyDBDaemonThread in threading.enumerate.')
                        
                    elif getattr(t, 'is_pydev_daemon_thread', False):
                        pass # I.e.: skip the DummyThreads created from pydev daemon threads
                        
                    elif isThreadAlive(t):
                        program_threads_alive[thread_id] = t

                        if not DictContains(self._running_thread_ids, thread_id):
                            if not hasattr(t, 'additionalInfo'):
                                # see http://sourceforge.net/tracker/index.php?func=detail&aid=1955428&group_id=85796&atid=577329
                                # Let's create the additional info right away!
                                t.additionalInfo = PyDBAdditionalThreadInfo()
                            self._running_thread_ids[thread_id] = t
                            self.writer.addCommand(self.cmdFactory.makeThreadCreatedMessage(t))


                        queue = self.getInternalQueue(thread_id)
                        cmdsToReadd = []  # some commands must be processed by the thread itself... if that's the case,
                                            # we will re-add the commands to the queue after executing.
                        try:
                            while True:
                                int_cmd = queue.get(False)
                                if int_cmd.canBeExecutedBy(curr_thread_id):
                                    PydevdLog(2, "processing internal command ", str(int_cmd))
                                    int_cmd.doIt(self)
                                else:
                                    PydevdLog(2, "NOT processing internal command ", str(int_cmd))
                                    cmdsToReadd.append(int_cmd)

                        except _queue.Empty: #@UndefinedVariable
                            for int_cmd in cmdsToReadd:
                                queue.put(int_cmd)
                            # this is how we exit


                thread_ids = list(self._running_thread_ids.keys())
                for tId in thread_ids:
                    if not DictContains(program_threads_alive, tId):
                        program_threads_dead.append(tId)
            finally:
                self._lock_running_thread_ids.release()

            for tId in program_threads_dead:
                try:
                    self.processThreadNotAlive(tId)
                except:
                    sys.stderr.write('Error iterating through %s (%s) - %s\n' % (
                        program_threads_alive, program_threads_alive.__class__, dir(program_threads_alive)))
                    raise


            if len(program_threads_alive) == 0:
                self.FinishDebuggingSession()
                for t in all_threads:
                    if hasattr(t, 'doKillPydevThread'):
                        t.doKillPydevThread()

        finally:
            self._main_lock.release()


    def setTracingForUntracedContexts(self, ignore_frame=None, overwrite_prev_trace=False):
        # Enable the tracing for existing threads (because there may be frames being executed that
        # are currently untraced).
        threads = threadingEnumerate()
        try:
            for t in threads:
                # TODO: optimize so that we only actually add that tracing if it's in
                # the new breakpoint context.
                additionalInfo = None
                try:
                    additionalInfo = t.additionalInfo
                except AttributeError:
                    pass  # that's ok, no info currently set

                if additionalInfo is not None:
                    for frame in additionalInfo.IterFrames():
                        if frame is not ignore_frame:
                            self.SetTraceForFrameAndParents(frame, overwrite_prev_trace=overwrite_prev_trace)
        finally:
            frame = None
            t = None
            threads = None
            additionalInfo = None


    def consolidate_breakpoints(self, file, id_to_breakpoint, breakpoints):
        break_dict = {}
        for breakpoint_id, pybreakpoint in DictIterItems(id_to_breakpoint):
            break_dict[pybreakpoint.line] = pybreakpoint

        breakpoints[file] = break_dict


    def add_break_on_exception(
        self,
        exception,
        notify_always,
        notify_on_terminate,
        notify_on_first_raise_only,
        ):
        eb = ExceptionBreakpoint(
            exception,
            notify_always,
            notify_on_terminate,
            notify_on_first_raise_only,
        )

        if eb.notify_on_terminate:
            cp = self.break_on_uncaught_exceptions.copy()
            cp[exception] = eb
            if DebugInfoHolder.DEBUG_TRACE_BREAKPOINTS > 0:
                pydev_log.error("Exceptions to hook on terminate: %s\n" % (cp,))
            self.break_on_uncaught_exceptions = cp

        if eb.notify_always:
            cp = self.break_on_caught_exceptions.copy()
            cp[exception] = eb
            if DebugInfoHolder.DEBUG_TRACE_BREAKPOINTS > 0:
                pydev_log.error("Exceptions to hook always: %s\n" % (cp,))
            self.break_on_caught_exceptions = cp

        return eb

    def update_after_exceptions_added(self, added):
        updated_on_caught = False
        updated_on_uncaught = False

        for eb in added:
            if not updated_on_uncaught and eb.notify_on_terminate:
                updated_on_uncaught = True
                update_exception_hook(self)

            if not updated_on_caught and eb.notify_always:
                updated_on_caught = True
                self.setTracingForUntracedContexts()


    def processNetCommand(self, cmd_id, seq, text):
        '''Processes a command received from the Java side

        @param cmd_id: the id of the command
        @param seq: the sequence of the command
        @param text: the text received in the command

        @note: this method is run as a big switch... after doing some tests, it's not clear whether changing it for
        a dict id --> function call will have better performance result. A simple test with xrange(10000000) showed
        that the gains from having a fast access to what should be executed are lost because of the function call in
        a way that if we had 10 elements in the switch the if..elif are better -- but growing the number of choices
        makes the solution with the dispatch look better -- so, if this gets more than 20-25 choices at some time,
        it may be worth refactoring it (actually, reordering the ifs so that the ones used mostly come before
        probably will give better performance).
        '''
        #print(ID_TO_MEANING[str(cmd_id)], repr(text))

        self._main_lock.acquire()
        try:
            try:
                cmd = None
                if cmd_id == CMD_RUN:
                    self.readyToRun = True

                elif cmd_id == CMD_VERSION:
                    # response is version number
                    # ide_os should be 'WINDOWS' or 'UNIX'.
                    ide_os = 'WINDOWS'

                    # Breakpoints can be grouped by 'LINE' or by 'ID'.
                    breakpoints_by = 'LINE'

                    splitted = text.split('\t')
                    if len(splitted) == 1:
                        _local_version = splitted

                    elif len(splitted) == 2:
                        _local_version, ide_os = splitted

                    elif len(splitted) == 3:
                        _local_version, ide_os, breakpoints_by = splitted

                    if breakpoints_by == 'ID':
                        self._set_breakpoints_with_id = True
                    else:
                        self._set_breakpoints_with_id = False

                    pydevd_file_utils.set_ide_os(ide_os)

                    cmd = self.cmdFactory.makeVersionMessage(seq)

                elif cmd_id == CMD_LIST_THREADS:
                    # response is a list of threads
                    cmd = self.cmdFactory.makeListThreadsMessage(seq)

                elif cmd_id == CMD_THREAD_KILL:
                    int_cmd = InternalTerminateThread(text)
                    self.postInternalCommand(int_cmd, text)

                elif cmd_id == CMD_THREAD_SUSPEND:
                    # Yes, thread suspend is still done at this point, not through an internal command!
                    t = PydevdFindThreadById(text)
                    if t:
                        additionalInfo = None
                        try:
                            additionalInfo = t.additionalInfo
                        except AttributeError:
                            pass  # that's ok, no info currently set

                        if additionalInfo is not None:
                            for frame in additionalInfo.IterFrames():
                                self.SetTraceForFrameAndParents(frame)
                                del frame

                        self.setSuspend(t, CMD_THREAD_SUSPEND)
                    elif text.startswith('__frame__:'):
                        sys.stderr.write("Can't suspend tasklet: %s\n" % (text,))

                elif cmd_id == CMD_THREAD_RUN:
                    t = PydevdFindThreadById(text)
                    if t:
                        thread_id = GetThreadId(t)
                        int_cmd = InternalRunThread(thread_id)
                        self.postInternalCommand(int_cmd, thread_id)

                    elif text.startswith('__frame__:'):
                        sys.stderr.write("Can't make tasklet run: %s\n" % (text,))


                elif cmd_id == CMD_STEP_INTO or cmd_id == CMD_STEP_OVER or cmd_id == CMD_STEP_RETURN:
                    # we received some command to make a single step
                    t = PydevdFindThreadById(text)
                    if t:
                        thread_id = GetThreadId(t)
                        int_cmd = InternalStepThread(thread_id, cmd_id)
                        self.postInternalCommand(int_cmd, thread_id)

                    elif text.startswith('__frame__:'):
                        sys.stderr.write("Can't make tasklet step command: %s\n" % (text,))


                elif cmd_id == CMD_RUN_TO_LINE or cmd_id == CMD_SET_NEXT_STATEMENT or cmd_id == CMD_SMART_STEP_INTO:
                    # we received some command to make a single step
                    thread_id, line, func_name = text.split('\t', 2)
                    t = PydevdFindThreadById(thread_id)
                    if t:
                        int_cmd = InternalSetNextStatementThread(thread_id, cmd_id, line, func_name)
                        self.postInternalCommand(int_cmd, thread_id)
                    elif thread_id.startswith('__frame__:'):
                        sys.stderr.write("Can't set next statement in tasklet: %s\n" % (thread_id,))


                elif cmd_id == CMD_RELOAD_CODE:
                    # we received some command to make a reload of a module
                    module_name = text.strip()

                    thread_id = '*'  # Any thread

                    # Note: not going for the main thread because in this case it'd only do the load
                    # when we stopped on a breakpoint.
                    # for tid, t in self._running_thread_ids.items(): #Iterate in copy
                    #    thread_name = t.getName()
                    #
                    #    print thread_name, GetThreadId(t)
                    #    #Note: if possible, try to reload on the main thread
                    #    if thread_name == 'MainThread':
                    #        thread_id = tid

                    int_cmd = ReloadCodeCommand(module_name, thread_id)
                    self.postInternalCommand(int_cmd, thread_id)


                elif cmd_id == CMD_CHANGE_VARIABLE:
                    # the text is: thread\tstackframe\tFRAME|GLOBAL\tattribute_to_change\tvalue_to_change
                    try:
                        thread_id, frame_id, scope, attr_and_value = text.split('\t', 3)

                        tab_index = attr_and_value.rindex('\t')
                        attr = attr_and_value[0:tab_index].replace('\t', '.')
                        value = attr_and_value[tab_index + 1:]
                        int_cmd = InternalChangeVariable(seq, thread_id, frame_id, scope, attr, value)
                        self.postInternalCommand(int_cmd, thread_id)

                    except:
                        traceback.print_exc()

                elif cmd_id == CMD_GET_VARIABLE:
                    # we received some command to get a variable
                    # the text is: thread_id\tframe_id\tFRAME|GLOBAL\tattributes*
                    try:
                        thread_id, frame_id, scopeattrs = text.split('\t', 2)

                        if scopeattrs.find('\t') != -1:  # there are attributes beyond scope
                            scope, attrs = scopeattrs.split('\t', 1)
                        else:
                            scope, attrs = (scopeattrs, None)

                        int_cmd = InternalGetVariable(seq, thread_id, frame_id, scope, attrs)
                        self.postInternalCommand(int_cmd, thread_id)

                    except:
                        traceback.print_exc()

                elif cmd_id == CMD_GET_COMPLETIONS:
                    # we received some command to get a variable
                    # the text is: thread_id\tframe_id\tactivation token
                    try:
                        thread_id, frame_id, scope, act_tok = text.split('\t', 3)

                        int_cmd = InternalGetCompletions(seq, thread_id, frame_id, act_tok)
                        self.postInternalCommand(int_cmd, thread_id)

                    except:
                        traceback.print_exc()

                elif cmd_id == CMD_GET_FRAME:
                    thread_id, frame_id, scope = text.split('\t', 2)

                    int_cmd = InternalGetFrame(seq, thread_id, frame_id)
                    self.postInternalCommand(int_cmd, thread_id)

                elif cmd_id == CMD_SET_BREAK:
                    # func name: 'None': match anything. Empty: match global, specified: only method context.
                    # command to add some breakpoint.
                    # text is file\tline. Add to breakpoints dictionary
                    if self._set_breakpoints_with_id:
                        breakpoint_id, type, file, line, func_name, condition, expression = text.split('\t', 6)

                        breakpoint_id = int(breakpoint_id)
                        line = int(line)

                        # We must restore new lines and tabs as done in
                        # AbstractDebugTarget.breakpointAdded
                        condition = condition.replace("@_@NEW_LINE_CHAR@_@", '\n').\
                            replace("@_@TAB_CHAR@_@", '\t').strip()

                        expression = expression.replace("@_@NEW_LINE_CHAR@_@", '\n').\
                            replace("@_@TAB_CHAR@_@", '\t').strip()
                    else:
                        #Note: this else should be removed after PyCharm migrates to setting
                        #breakpoints by id (and ideally also provides func_name).
                        type, file, line, condition, expression = text.split('\t', 4)
                        # If we don't have an id given for each breakpoint, consider
                        # the id to be the line.
                        breakpoint_id = line = int(line)
                        if condition.startswith('**FUNC**'):
                            func_name, condition = condition.split('\t', 1)

                            # We must restore new lines and tabs as done in
                            # AbstractDebugTarget.breakpointAdded
                            condition = condition.replace("@_@NEW_LINE_CHAR@_@", '\n').\
                                replace("@_@TAB_CHAR@_@", '\t').strip()

                            func_name = func_name[8:]
                        else:
                            func_name = 'None'  # Match anything if not specified.

                    if not IS_PY3K:  # In Python 3, the frame object will have unicode for the file, whereas on python 2 it has a byte-array encoded with the filesystem encoding.
                        file = file.encode(file_system_encoding)

                    file = NormFileToServer(file)

                    if not pydevd_file_utils.exists(file):
                        sys.stderr.write('pydev debugger: warning: trying to add breakpoint'\
                            ' to file that does not exist: %s (will have no effect)\n' % (file,))
                        sys.stderr.flush()


                    if len(condition) <= 0 or condition is None or condition == "None":
                        condition = None

                    if len(expression) <= 0 or expression is None or expression == "None":
                        expression = None

                    if type == 'python-line':
                        breakpoint = LineBreakpoint(line, condition, func_name, expression)
                        breakpoints = self.breakpoints
                        file_to_id_to_breakpoint = self.file_to_id_to_line_breakpoint
                    elif type == 'django-line':
                        breakpoint = DjangoLineBreakpoint(file, line, condition, func_name, expression)
                        breakpoints = self.django_breakpoints
                        file_to_id_to_breakpoint = self.file_to_id_to_django_breakpoint
                    else:
                        raise NameError(type)

                    if DebugInfoHolder.DEBUG_TRACE_BREAKPOINTS > 0:
                        pydev_log.debug('Added breakpoint:%s - line:%s - func_name:%s\n' % (file, line, func_name.encode('utf-8')))
                        sys.stderr.flush()

                    if DictContains(file_to_id_to_breakpoint, file):
                        id_to_pybreakpoint = file_to_id_to_breakpoint[file]
                    else:
                        id_to_pybreakpoint = file_to_id_to_breakpoint[file] = {}

                    id_to_pybreakpoint[breakpoint_id] = breakpoint
                    self.consolidate_breakpoints(file, id_to_pybreakpoint, breakpoints)

                    self.setTracingForUntracedContexts(overwrite_prev_trace=True)

                elif cmd_id == CMD_REMOVE_BREAK:
                    #command to remove some breakpoint
                    #text is type\file\tid. Remove from breakpoints dictionary
                    breakpoint_type, file, breakpoint_id = text.split('\t', 2)

                    if not IS_PY3K:  # In Python 3, the frame object will have unicode for the file, whereas on python 2 it has a byte-array encoded with the filesystem encoding.
                        file = file.encode(file_system_encoding)

                    file = NormFileToServer(file)

                    try:
                        breakpoint_id = int(breakpoint_id)
                    except ValueError:
                        pydev_log.error('Error removing breakpoint. Expected breakpoint_id to be an int. Found: %s' % (breakpoint_id,))

                    else:
                        if breakpoint_type == 'python-line':
                            breakpoints = self.breakpoints
                            file_to_id_to_breakpoint = self.file_to_id_to_line_breakpoint
                        elif breakpoint_type == 'django-line':
                            breakpoints = self.django_breakpoints
                            file_to_id_to_breakpoint = self.file_to_id_to_django_breakpoint
                        else:
                            raise NameError(breakpoint_type)

                        try:
                            id_to_pybreakpoint = file_to_id_to_breakpoint.get(file, {})
                            if DebugInfoHolder.DEBUG_TRACE_BREAKPOINTS > 0:
                                existing = id_to_pybreakpoint[breakpoint_id]
                                sys.stderr.write('Removed breakpoint:%s - line:%s - func_name:%s (id: %s)\n' % (
                                    file, existing.line, existing.func_name.encode('utf-8'), breakpoint_id))

                            del id_to_pybreakpoint[breakpoint_id]
                            self.consolidate_breakpoints(file, id_to_pybreakpoint, breakpoints)
                        except KeyError:
                            pydev_log.error("Error removing breakpoint: Breakpoint id not found: %s id: %s. Available ids: %s\n" % (
                                file, breakpoint_id, DictKeys(id_to_pybreakpoint)))


                elif cmd_id == CMD_EVALUATE_EXPRESSION or cmd_id == CMD_EXEC_EXPRESSION:
                    #command to evaluate the given expression
                    #text is: thread\tstackframe\tLOCAL\texpression
                    thread_id, frame_id, scope, expression, trim = text.split('\t', 4)
                    int_cmd = InternalEvaluateExpression(seq, thread_id, frame_id, expression,
                        cmd_id == CMD_EXEC_EXPRESSION, int(trim) == 1)
                    self.postInternalCommand(int_cmd, thread_id)

                elif cmd_id == CMD_CONSOLE_EXEC:
                    #command to exec expression in console, in case expression is only partially valid 'False' is returned
                    #text is: thread\tstackframe\tLOCAL\texpression

                    thread_id, frame_id, scope, expression = text.split('\t', 3)

                    int_cmd = InternalConsoleExec(seq, thread_id, frame_id, expression)
                    self.postInternalCommand(int_cmd, thread_id)

                elif cmd_id == CMD_SET_PY_EXCEPTION:
                    # Command which receives set of exceptions on which user wants to break the debugger
                    # text is: break_on_uncaught;break_on_caught;TypeError;ImportError;zipimport.ZipImportError;
                    # This API is optional and works 'in bulk' -- it's possible
                    # to get finer-grained control with CMD_ADD_EXCEPTION_BREAK/CMD_REMOVE_EXCEPTION_BREAK
                    # which allows setting caught/uncaught per exception.
                    #
                    splitted = text.split(';')
                    self.break_on_uncaught_exceptions = {}
                    self.break_on_caught_exceptions = {}
                    added = []
                    if len(splitted) >= 4:
                        if splitted[0] == 'true':
                            break_on_uncaught = True
                        else:
                            break_on_uncaught = False

                        if splitted[1] == 'true':
                            break_on_caught = True
                        else:
                            break_on_caught = False

                        if splitted[2] == 'true':
                            self.break_on_exceptions_thrown_in_same_context = True
                        else:
                            self.break_on_exceptions_thrown_in_same_context = False

                        if splitted[3] == 'true':
                            self.ignore_exceptions_thrown_in_lines_with_ignore_exception = True
                        else:
                            self.ignore_exceptions_thrown_in_lines_with_ignore_exception = False

                        for exception_type in splitted[4:]:
                            exception_type = exception_type.strip()
                            if not exception_type:
                                continue

                            exception_breakpoint = self.add_break_on_exception(
                                exception_type,
                                notify_always=break_on_caught,
                                notify_on_terminate=break_on_uncaught,
                                notify_on_first_raise_only=False,
                            )
                            added.append(exception_breakpoint)

                        self.update_after_exceptions_added(added)

                    else:
                        sys.stderr.write("Error when setting exception list. Received: %s\n" % (text,))

                elif cmd_id == CMD_GET_FILE_CONTENTS:

                    if not IS_PY3K:  # In Python 3, the frame object will have unicode for the file, whereas on python 2 it has a byte-array encoded with the filesystem encoding.
                        text = text.encode(file_system_encoding)

                    if os.path.exists(text):
                        f = open(text, 'r')
                        try:
                            source = f.read()
                        finally:
                            f.close()
                        cmd = self.cmdFactory.makeGetFileContents(seq, source)

                elif cmd_id == CMD_SET_PROPERTY_TRACE:
                    # Command which receives whether to trace property getter/setter/deleter
                    # text is feature_state(true/false);disable_getter/disable_setter/disable_deleter
                    if text != "":
                        splitted = text.split(';')
                        if len(splitted) >= 3:
                            if self.disable_property_trace is False and splitted[0] == 'true':
                                # Replacing property by custom property only when the debugger starts
                                pydevd_traceproperty.replace_builtin_property()
                                self.disable_property_trace = True
                            # Enable/Disable tracing of the property getter
                            if splitted[1] == 'true':
                                self.disable_property_getter_trace = True
                            else:
                                self.disable_property_getter_trace = False
                            # Enable/Disable tracing of the property setter
                            if splitted[2] == 'true':
                                self.disable_property_setter_trace = True
                            else:
                                self.disable_property_setter_trace = False
                            # Enable/Disable tracing of the property deleter
                            if splitted[3] == 'true':
                                self.disable_property_deleter_trace = True
                            else:
                                self.disable_property_deleter_trace = False
                    else:
                        # User hasn't configured any settings for property tracing
                        pass

                elif cmd_id == CMD_ADD_EXCEPTION_BREAK:
                    exception, notify_always, notify_on_terminate = text.split('\t', 2)
                    exception_breakpoint = self.add_break_on_exception(
                        exception,
                        notify_always=int(notify_always) > 0,
                        notify_on_terminate = int(notify_on_terminate) == 1,
                        notify_on_first_raise_only=int(notify_always) == 2
                    )
                    self.update_after_exceptions_added([exception_breakpoint])

                elif cmd_id == CMD_REMOVE_EXCEPTION_BREAK:
                    exception = text
                    try:
                        cp = self.break_on_uncaught_exceptions.copy()
                        DictPop(cp, exception, None)
                        self.break_on_uncaught_exceptions = cp

                        cp = self.break_on_caught_exceptions.copy()
                        DictPop(cp, exception, None)
                        self.break_on_caught_exceptions = cp
                    except:
                        pydev_log.debug("Error while removing exception %s"%sys.exc_info()[0]);
                    update_exception_hook(self)

                elif cmd_id == CMD_LOAD_SOURCE:
                    path = text
                    try:
                        f = open(path, 'r')
                        source = f.read()
                        self.cmdFactory.makeLoadSourceMessage(seq, source, self)
                    except:
                        return self.cmdFactory.makeErrorMessage(seq, pydevd_tracing.GetExceptionTracebackStr())

                elif cmd_id == CMD_ADD_DJANGO_EXCEPTION_BREAK:
                    exception = text

                    self.django_exception_break[exception] = True
                    self.setTracingForUntracedContexts()

                elif cmd_id == CMD_REMOVE_DJANGO_EXCEPTION_BREAK:
                    exception = text

                    try:
                        del self.django_exception_break[exception]
                    except :
                        pass

                elif cmd_id == CMD_EVALUATE_CONSOLE_EXPRESSION:
                    # Command which takes care for the debug console communication
                    if text != "":
                        thread_id, frame_id, console_command = text.split('\t', 2)
                        console_command, line = console_command.split('\t')
                        if console_command == 'EVALUATE':
                            int_cmd = InternalEvaluateConsoleExpression(seq, thread_id, frame_id, line)
                        elif console_command == 'GET_COMPLETIONS':
                            int_cmd = InternalConsoleGetCompletions(seq, thread_id, frame_id, line)
                        self.postInternalCommand(int_cmd, thread_id)

                elif cmd_id == CMD_RUN_CUSTOM_OPERATION:
                    # Command which runs a custom operation
                    if text != "":
                        try:
                            location, custom = text.split('||', 1)
                        except:
                            sys.stderr.write('Custom operation now needs a || separator. Found: %s\n' % (text,))
                            raise

                        thread_id, frame_id, scopeattrs = location.split('\t', 2)

                        if scopeattrs.find('\t') != -1:  # there are attributes beyond scope
                            scope, attrs = scopeattrs.split('\t', 1)
                        else:
                            scope, attrs = (scopeattrs, None)

                        # : style: EXECFILE or EXEC
                        # : encoded_code_or_file: file to execute or code
                        # : fname: name of function to be executed in the resulting namespace
                        style, encoded_code_or_file, fnname = custom.split('\t', 3)
                        int_cmd = InternalRunCustomOperation(seq, thread_id, frame_id, scope, attrs,
                                                             style, encoded_code_or_file, fnname)
                        self.postInternalCommand(int_cmd, thread_id)

                elif cmd_id == CMD_IGNORE_THROWN_EXCEPTION_AT:
                    if text:
                        replace = 'REPLACE:'  # Not all 3.x versions support u'REPLACE:', so, doing workaround.
                        if not IS_PY3K:
                            replace = unicode(replace)

                        if text.startswith(replace):
                            text = text[8:]
                            self.filename_to_lines_where_exceptions_are_ignored.clear()

                        if text:
                            for line in text.split('||'):  # Can be bulk-created (one in each line)
                                filename, line_number = line.split('|')
                                if not IS_PY3K:
                                    filename = filename.encode(file_system_encoding)

                                filename = NormFileToServer(filename)

                                if os.path.exists(filename):
                                    lines_ignored = self.filename_to_lines_where_exceptions_are_ignored.get(filename)
                                    if lines_ignored is None:
                                        lines_ignored = self.filename_to_lines_where_exceptions_are_ignored[filename] = {}
                                    lines_ignored[int(line_number)] = 1
                                else:
                                    sys.stderr.write('pydev debugger: warning: trying to ignore exception thrown'\
                                        ' on file that does not exist: %s (will have no effect)\n' % (filename,))

                elif cmd_id == CMD_ENABLE_DONT_TRACE:
                    if text:
                        true_str = 'true'  # Not all 3.x versions support u'str', so, doing workaround.
                        if not IS_PY3K:
                            true_str = unicode(true_str)

                        mode = text.strip() == true_str
                        pydevd_dont_trace.trace_filter(mode)

                else:
                    #I have no idea what this is all about
                    cmd = self.cmdFactory.makeErrorMessage(seq, "unexpected command " + str(cmd_id))

                if cmd is not None:
                    self.writer.addCommand(cmd)
                    del cmd

            except Exception:
                traceback.print_exc()
                cmd = self.cmdFactory.makeErrorMessage(seq,
                    "Unexpected exception in processNetCommand.\nInitial params: %s" % ((cmd_id, seq, text),))

                self.writer.addCommand(cmd)
        finally:
            self._main_lock.release()

    def processThreadNotAlive(self, threadId):
        """ if thread is not alive, cancel trace_dispatch processing """
        self._lock_running_thread_ids.acquire()
        try:
            thread = self._running_thread_ids.pop(threadId, None)
            if thread is None:
                return

            wasNotified = thread.additionalInfo.pydev_notify_kill
            if not wasNotified:
                thread.additionalInfo.pydev_notify_kill = True

        finally:
            self._lock_running_thread_ids.release()

        cmd = self.cmdFactory.makeThreadKilledMessage(threadId)
        self.writer.addCommand(cmd)


    def setSuspend(self, thread, stop_reason):
        thread.additionalInfo.suspend_type = PYTHON_SUSPEND
        thread.additionalInfo.pydev_state = STATE_SUSPEND
        thread.stop_reason = stop_reason

        # If conditional breakpoint raises any exception during evaluation send details to Java
        if stop_reason == CMD_SET_BREAK and self.suspend_on_breakpoint_exception:
            self.sendBreakpointConditionException(thread)


    def sendBreakpointConditionException(self, thread):
        """If conditional breakpoint raises an exception during evaluation
        send exception details to java
        """
        thread_id = GetThreadId(thread)
        conditional_breakpoint_exception_tuple = thread.additionalInfo.conditional_breakpoint_exception
        # conditional_breakpoint_exception_tuple - should contain 2 values (exception_type, stacktrace)
        if conditional_breakpoint_exception_tuple and len(conditional_breakpoint_exception_tuple) == 2:
            exc_type, stacktrace = conditional_breakpoint_exception_tuple
            int_cmd = InternalGetBreakpointException(thread_id, exc_type, stacktrace)
            # Reset the conditional_breakpoint_exception details to None
            thread.additionalInfo.conditional_breakpoint_exception = None
            self.postInternalCommand(int_cmd, thread_id)


    def sendCaughtExceptionStack(self, thread, arg, curr_frame_id):
        """Sends details on the exception which was caught (and where we stopped) to the java side.

        arg is: exception type, description, traceback object
        """
        thread_id = GetThreadId(thread)
        int_cmd = InternalSendCurrExceptionTrace(thread_id, arg, curr_frame_id)
        self.postInternalCommand(int_cmd, thread_id)


    def sendCaughtExceptionStackProceeded(self, thread):
        """Sends that some thread was resumed and is no longer showing an exception trace.
        """
        thread_id = GetThreadId(thread)
        int_cmd = InternalSendCurrExceptionTraceProceeded(thread_id)
        self.postInternalCommand(int_cmd, thread_id)
        self.processInternalCommands()


    def doWaitSuspend(self, thread, frame, event, arg): #@UnusedVariable
        """ busy waits until the thread state changes to RUN
        it expects thread's state as attributes of the thread.
        Upon running, processes any outstanding Stepping commands.
        """
        self.processInternalCommands()

        message = getattr(thread.additionalInfo, "message", None)

        cmd = self.cmdFactory.makeThreadSuspendMessage(GetThreadId(thread), frame, thread.stop_reason, message)
        self.writer.addCommand(cmd)

        CustomFramesContainer.custom_frames_lock.acquire()
        try:
            from_this_thread = []

            for frame_id, custom_frame in DictIterItems(CustomFramesContainer.custom_frames):
                if custom_frame.thread_id == thread.ident:
                    # print >> sys.stderr, 'Frame created: ', frame_id
                    self.writer.addCommand(self.cmdFactory.makeCustomFrameCreatedMessage(frame_id, custom_frame.name))
                    self.writer.addCommand(self.cmdFactory.makeThreadSuspendMessage(frame_id, custom_frame.frame, CMD_THREAD_SUSPEND, ""))

                from_this_thread.append(frame_id)

        finally:
            CustomFramesContainer.custom_frames_lock.release()



        info = thread.additionalInfo
        while info.pydev_state == STATE_SUSPEND and not self._finishDebuggingSession:
            self.processInternalCommands()
            time.sleep(0.01)

        # process any stepping instructions
        if info.pydev_step_cmd == CMD_STEP_INTO:
            info.pydev_step_stop = None
            info.pydev_smart_step_stop = None

        elif info.pydev_step_cmd == CMD_STEP_OVER:
            info.pydev_step_stop = frame
            info.pydev_smart_step_stop = None
            self.SetTraceForFrameAndParents(frame)

        elif info.pydev_step_cmd == CMD_SMART_STEP_INTO:
            self.SetTraceForFrameAndParents(frame)
            info.pydev_step_stop = None
            info.pydev_smart_step_stop = frame

        elif info.pydev_step_cmd == CMD_RUN_TO_LINE or info.pydev_step_cmd == CMD_SET_NEXT_STATEMENT :
            self.SetTraceForFrameAndParents(frame)

            if event == 'line' or event == 'exception':
                #If we're already in the correct context, we have to stop it now, because we can act only on
                #line events -- if a return was the next statement it wouldn't work (so, we have this code
                #repeated at pydevd_frame).
                stop = False
                curr_func_name = frame.f_code.co_name

                #global context is set with an empty name
                if curr_func_name in ('?', '<module>'):
                    curr_func_name = ''

                if curr_func_name == info.pydev_func_name:
                    line = info.pydev_next_line
                    if frame.f_lineno == line:
                        stop = True
                    else :
                        if frame.f_trace is None:
                            frame.f_trace = self.trace_dispatch
                        frame.f_lineno = line
                        frame.f_trace = None
                        stop = True
                if stop:
                    info.pydev_state = STATE_SUSPEND
                    self.doWaitSuspend(thread, frame, event, arg)
                    return


        elif info.pydev_step_cmd == CMD_STEP_RETURN:
            back_frame = frame.f_back
            if back_frame is not None:
                # steps back to the same frame (in a return call it will stop in the 'back frame' for the user)
                info.pydev_step_stop = frame
                self.SetTraceForFrameAndParents(frame)
            else:
                # No back frame?!? -- this happens in jython when we have some frame created from an awt event
                # (the previous frame would be the awt event, but this doesn't make part of 'jython', only 'java')
                # so, if we're doing a step return in this situation, it's the same as just making it run
                info.pydev_step_stop = None
                info.pydev_step_cmd = None
                info.pydev_state = STATE_RUN

        del frame
        cmd = self.cmdFactory.makeThreadRunMessage(GetThreadId(thread), info.pydev_step_cmd)
        self.writer.addCommand(cmd)

        CustomFramesContainer.custom_frames_lock.acquire()
        try:
            # The ones that remained on last_running must now be removed.
            for frame_id in from_this_thread:
                # print >> sys.stderr, 'Removing created frame: ', frame_id
                self.writer.addCommand(self.cmdFactory.makeThreadKilledMessage(frame_id))

        finally:
            CustomFramesContainer.custom_frames_lock.release()

    def handle_post_mortem_stop(self, additionalInfo, t):
        pydev_log.debug("We are stopping in post-mortem\n")
        frame, frames_byid = additionalInfo.pydev_force_stop_at_exception
        thread_id = GetThreadId(t)
        pydevd_vars.addAdditionalFrameById(thread_id, frames_byid)
        try:
            try:
                add_exception_to_frame(frame, additionalInfo.exception)
                self.setSuspend(t, CMD_ADD_EXCEPTION_BREAK)
                self.doWaitSuspend(t, frame, 'exception', None)
            except:
                pydev_log.error("We've got an error while stopping in post-mortem: %s\n"%sys.exc_info()[0])
        finally:
            additionalInfo.pydev_force_stop_at_exception = None
            pydevd_vars.removeAdditionalFrameById(thread_id)

    def trace_dispatch(self, frame, event, arg):
        ''' This is the callback used when we enter some context in the debugger.

        We also decorate the thread we are in with info about the debugging.
        The attributes added are:
            pydev_state
            pydev_step_stop
            pydev_step_cmd
            pydev_notify_kill
        '''
        try:
            if self._finishDebuggingSession and not self._terminationEventSent:
                #that was not working very well because jython gave some socket errors
                try:
                    threads = DictKeys(PyDBDaemonThread.created_pydb_daemon_threads)
                    for t in threads:
                        if hasattr(t, 'doKillPydevThread'):
                            t.doKillPydevThread()
                except:
                    traceback.print_exc()
                self._terminationEventSent = True
                return None

            filename, base = GetFilenameAndBase(frame)

            is_file_to_ignore = DictContains(DONT_TRACE, base) #we don't want to debug threading or anything related to pydevd

            #print('trace_dispatch', base, frame.f_lineno, event, frame.f_code.co_name, is_file_to_ignore)
            if is_file_to_ignore:
                return None

            try:
                #this shouldn't give an exception, but it could happen... (python bug)
                #see http://mail.python.org/pipermail/python-bugs-list/2007-June/038796.html
                #and related bug: http://bugs.python.org/issue1733757
                t = threadingCurrentThread()
            except:
                frame.f_trace = self.trace_dispatch
                return self.trace_dispatch

            try:
                additionalInfo = t.additionalInfo
                if additionalInfo is None:
                    raise AttributeError()
            except:
                t.additionalInfo = PyDBAdditionalThreadInfo()
                additionalInfo = t.additionalInfo

            if additionalInfo is None:
                return None

            if additionalInfo.is_tracing:
                f = frame
                while f is not None:
                    if 'trace_dispatch' == f.f_code.co_name:
                        _fname, bs = GetFilenameAndBase(f)
                        if bs == 'pydevd_frame.py':
                            return None  #we don't wan't to trace code invoked from pydevd_frame.trace_dispatch
                    f = f.f_back

            # if thread is not alive, cancel trace_dispatch processing
            if not isThreadAlive(t):
                self.processThreadNotAlive(GetThreadId(t))
                return None  # suspend tracing

            # each new frame...
            return additionalInfo.CreateDbFrame((self, filename, additionalInfo, t, frame)).trace_dispatch(frame, event, arg)

        except SystemExit:
            return None

        except Exception:
            # Log it
            try:
                if traceback is not None:
                    # This can actually happen during the interpreter shutdown in Python 2.7
                    traceback.print_exc()
            except:
                # Error logging? We're really in the interpreter shutdown...
                # (https://github.com/fabioz/PyDev.Debugger/issues/8) 
                pass
            return None

    if USE_PSYCO_OPTIMIZATION:
        try:
            import psyco
            trace_dispatch = psyco.proxy(trace_dispatch)
            processNetCommand = psyco.proxy(processNetCommand)
            processInternalCommands = psyco.proxy(processInternalCommands)
            doWaitSuspend = psyco.proxy(doWaitSuspend)
            getInternalQueue = psyco.proxy(getInternalQueue)
        except ImportError:
            if hasattr(sys, 'exc_clear'):  # jython does not have it
                sys.exc_clear()  # don't keep the traceback (let's keep it clear for when we go to the point of executing client code)

            if not IS_PY3K and not IS_PY27 and not IS_64_BITS and not sys.platform.startswith("java") and not sys.platform.startswith("cli"):
                sys.stderr.write("pydev debugger: warning: psyco not available for speedups (the debugger will still work correctly, but a bit slower)\n")
                sys.stderr.flush()



    def SetTraceForFrameAndParents(self, frame, also_add_to_passed_frame=True, overwrite_prev_trace=False, dispatch_func=None):
        if dispatch_func is None:
            dispatch_func = self.trace_dispatch

        if also_add_to_passed_frame:
            self.update_trace(frame, dispatch_func, overwrite_prev_trace)

        frame = frame.f_back
        while frame:
            self.update_trace(frame, dispatch_func, overwrite_prev_trace)

            frame = frame.f_back
        del frame

    def update_trace(self, frame, dispatch_func, overwrite_prev):
        if frame.f_trace is None:
            frame.f_trace = dispatch_func
        else:
            if overwrite_prev:
                frame.f_trace = dispatch_func
            else:
                try:
                    #If it's the trace_exception, go back to the frame trace dispatch!
                    if frame.f_trace.im_func.__name__ == 'trace_exception':
                        frame.f_trace = frame.f_trace.im_self.trace_dispatch
                except AttributeError:
                    pass
                frame = frame.f_back
        del frame

    def prepareToRun(self):
        ''' Shared code to prepare debugging by installing traces and registering threads '''
        self.patch_threads()
        pydevd_tracing.SetTrace(self.trace_dispatch)


        PyDBCommandThread(self).start()
        PyDBCheckAliveThread(self).start()


    def patch_threads(self):
        try:
            # not available in jython!
            threading.settrace(self.trace_dispatch)  # for all future threads
        except:
            pass

        from pydev_monkey import patch_thread_modules
        patch_thread_modules()


    def run(self, file, globals=None, locals=None, set_trace=True):
        if os.path.isdir(file):
            new_target = os.path.join(file, '__main__.py')
            if os.path.isfile(new_target):
                file = new_target

        if globals is None:
            # patch provided by: Scott Schlesier - when script is run, it does not
            # use globals from pydevd:
            # This will prevent the pydevd script from contaminating the namespace for the script to be debugged

            # pretend pydevd is not the main module, and
            # convince the file to be debugged that it was loaded as main
            sys.modules['pydevd'] = sys.modules['__main__']
            sys.modules['pydevd'].__name__ = 'pydevd'

            from imp import new_module
            m = new_module('__main__')
            sys.modules['__main__'] = m
            if hasattr(sys.modules['pydevd'], '__loader__'):
                setattr(m, '__loader__', getattr(sys.modules['pydevd'], '__loader__'))

            m.__file__ = file
            globals = m.__dict__
            try:
                globals['__builtins__'] = __builtins__
            except NameError:
                pass  # Not there on Jython...

        if locals is None:
            locals = globals

        if set_trace:
            # Predefined (writable) attributes: __name__ is the module's name;
            # __doc__ is the module's documentation string, or None if unavailable;
            # __file__ is the pathname of the file from which the module was loaded,
            # if it was loaded from a file. The __file__ attribute is not present for
            # C modules that are statically linked into the interpreter; for extension modules
            # loaded dynamically from a shared library, it is the pathname of the shared library file.


            # I think this is an ugly hack, bug it works (seems to) for the bug that says that sys.path should be the same in
            # debug and run.
            if m.__file__.startswith(sys.path[0]):
                # print >> sys.stderr, 'Deleting: ', sys.path[0]
                del sys.path[0]

            # now, the local directory has to be added to the pythonpath
            # sys.path.insert(0, os.getcwd())
            # Changed: it's not the local directory, but the directory of the file launched
            # The file being run ust be in the pythonpath (even if it was not before)
            sys.path.insert(0, os.path.split(file)[0])

            self.prepareToRun()

            while not self.readyToRun:
                time.sleep(0.1)  # busy wait until we receive run command


        pydev_imports.execfile(file, globals, locals)  # execute the script

        return globals

    def exiting(self):
        sys.stdout.flush()
        sys.stderr.flush()
        self.checkOutputRedirect()
        cmd = self.cmdFactory.makeExitMessage()
        self.writer.addCommand(cmd)

    def wait_for_commands(self, globals):
        thread = threading.currentThread()
        import pydevd_frame_utils
        frame = pydevd_frame_utils.Frame(None, -1, pydevd_frame_utils.FCode("Console",
                                                                            os.path.abspath(os.path.dirname(__file__))), globals, globals)
        thread_id = GetThreadId(thread)
        import pydevd_vars
        pydevd_vars.addAdditionalFrameById(thread_id, {id(frame): frame})

        cmd = self.cmdFactory.makeShowConsoleMessage(thread_id, frame)
        self.writer.addCommand(cmd)

        while True:
            self.processInternalCommands()
            time.sleep(0.01)

def set_debug(setup):
    setup['DEBUG_RECORD_SOCKET_READS'] = True
    setup['DEBUG_TRACE_BREAKPOINTS'] = 1
    setup['DEBUG_TRACE_LEVEL'] = 3


def processCommandLine(argv):
    """ parses the arguments.
        removes our arguments from the command line """
    setup = {}
    setup['client'] = ''
    setup['server'] = False
    setup['port'] = 0
    setup['file'] = ''
    setup['multiproc'] = False #Used by PyCharm (reuses connection: ssh tunneling)
    setup['multiprocess'] = False # Used by PyDev (creates new connection to ide)
    setup['save-signatures'] = False
    setup['print-in-debugger-startup'] = False
    setup['cmd-line'] = False
    i = 0
    del argv[0]
    while (i < len(argv)):
        if argv[i] == '--port':
            del argv[i]
            setup['port'] = int(argv[i])
            del argv[i]
        elif argv[i] == '--vm_type':
            del argv[i]
            setup['vm_type'] = argv[i]
            del argv[i]
        elif argv[i] == '--client':
            del argv[i]
            setup['client'] = argv[i]
            del argv[i]
        elif argv[i] == '--server':
            del argv[i]
            setup['server'] = True
        elif argv[i] == '--file':
            del argv[i]
            setup['file'] = argv[i]
            i = len(argv) # pop out, file is our last argument
        elif argv[i] == '--DEBUG_RECORD_SOCKET_READS':
            del argv[i]
            setup['DEBUG_RECORD_SOCKET_READS'] = True
        elif argv[i] == '--DEBUG':
            del argv[i]
            set_debug(setup)
        elif argv[i] == '--multiproc':
            del argv[i]
            setup['multiproc'] = True
        elif argv[i] == '--multiprocess':
            del argv[i]
            setup['multiprocess'] = True
        elif argv[i] == '--save-signatures':
            del argv[i]
            setup['save-signatures'] = True
        elif argv[i] == '--print-in-debugger-startup':
            del argv[i]
            setup['print-in-debugger-startup'] = True
        elif (argv[i] == '--cmd-line'):
            del argv[i]
            setup['cmd-line'] = True
        else:
            raise ValueError("unexpected option " + argv[i])
    return setup

def usage(doExit=0):
    sys.stdout.write('Usage:\n')
    sys.stdout.write('pydevd.py --port=N [(--client hostname) | --server] --file executable [file_options]\n')
    if doExit:
        sys.exit(0)


def initStdoutRedirect():
    if not getattr(sys, 'stdoutBuf', None):
        sys.stdoutBuf = pydevd_io.IOBuf()
        sys.stdout = pydevd_io.IORedirector(sys.stdout, sys.stdoutBuf) #@UndefinedVariable

def initStderrRedirect():
    if not getattr(sys, 'stderrBuf', None):
        sys.stderrBuf = pydevd_io.IOBuf()
        sys.stderr = pydevd_io.IORedirector(sys.stderr, sys.stderrBuf) #@UndefinedVariable

#=======================================================================================================================
# settrace
#=======================================================================================================================
def settrace(
    host=None,
    stdoutToServer=False,
    stderrToServer=False,
    port=5678,
    suspend=True,
    trace_only_current_thread=False,
    overwrite_prev_trace=False,
    patch_multiprocessing=False,
    ):
    '''Sets the tracing function with the pydev debug function and initializes needed facilities.

    @param host: the user may specify another host, if the debug server is not in the same machine (default is the local
        host)

    @param stdoutToServer: when this is true, the stdout is passed to the debug server

    @param stderrToServer: when this is true, the stderr is passed to the debug server
        so that they are printed in its console and not in this process console.

    @param port: specifies which port to use for communicating with the server (note that the server must be started
        in the same port). @note: currently it's hard-coded at 5678 in the client

    @param suspend: whether a breakpoint should be emulated as soon as this function is called.

    @param trace_only_current_thread: determines if only the current thread will be traced or all current and future
        threads will also have the tracing enabled.

    @param overwrite_prev_trace: if True we'll reset the frame.f_trace of frames which are already being traced

    @param patch_multiprocessing: if True we'll patch the functions which create new processes so that launched
        processes are debugged.
    '''
    _set_trace_lock.acquire()
    try:
        _locked_settrace(
            host,
            stdoutToServer,
            stderrToServer,
            port,
            suspend,
            trace_only_current_thread,
            overwrite_prev_trace,
            patch_multiprocessing,
        )
    finally:
        _set_trace_lock.release()



_set_trace_lock = _pydev_thread.allocate_lock()

def _locked_settrace(
    host,
    stdoutToServer,
    stderrToServer,
    port,
    suspend,
    trace_only_current_thread,
    overwrite_prev_trace,
    patch_multiprocessing,
    ):
    if patch_multiprocessing:
        try:
            import pydev_monkey #Jython 2.1 can't use it...
        except:
            pass
        else:
            pydev_monkey.patch_new_process_functions()

    if host is None:
        import pydev_localhost
        host = pydev_localhost.get_localhost()

    global connected
    global bufferStdOutToServer
    global bufferStdErrToServer

    if not connected :
        pydevd_vm_type.SetupType()

        debugger = PyDB()
        debugger.connect(host, port)  # Note: connect can raise error.

        # Mark connected only if it actually succeeded.
        connected = True
        bufferStdOutToServer = stdoutToServer
        bufferStdErrToServer = stderrToServer

        if bufferStdOutToServer:
            initStdoutRedirect()

        if bufferStdErrToServer:
            initStderrRedirect()

        debugger.SetTraceForFrameAndParents(GetFrame(), False, overwrite_prev_trace=overwrite_prev_trace)


        CustomFramesContainer.custom_frames_lock.acquire()
        try:
            for _frameId, custom_frame in DictIterItems(CustomFramesContainer.custom_frames):
                debugger.SetTraceForFrameAndParents(custom_frame.frame, False)
        finally:
            CustomFramesContainer.custom_frames_lock.release()


        t = threadingCurrentThread()
        try:
            additionalInfo = t.additionalInfo
        except AttributeError:
            additionalInfo = PyDBAdditionalThreadInfo()
            t.additionalInfo = additionalInfo

        while not debugger.readyToRun:
            time.sleep(0.1)  # busy wait until we receive run command

        # note that we do that through pydevd_tracing.SetTrace so that the tracing
        # is not warned to the user!
        pydevd_tracing.SetTrace(debugger.trace_dispatch)

        if not trace_only_current_thread:
            # Trace future threads?
            debugger.patch_threads()

            # As this is the first connection, also set tracing for any untraced threads
            debugger.setTracingForUntracedContexts(ignore_frame=GetFrame(), overwrite_prev_trace=overwrite_prev_trace)

        # Stop the tracing as the last thing before the actual shutdown for a clean exit.
        atexit.register(stoptrace)
        
        #Suspend as the last thing after all tracing is in place.
        if suspend:
            debugger.setSuspend(t, CMD_SET_BREAK)

        PyDBCommandThread(debugger).start()
        PyDBCheckAliveThread(debugger).start()

    else:
        # ok, we're already in debug mode, with all set, so, let's just set the break
        debugger = GetGlobalDebugger()

        debugger.SetTraceForFrameAndParents(GetFrame(), False)

        t = threadingCurrentThread()
        try:
            additionalInfo = t.additionalInfo
        except AttributeError:
            additionalInfo = PyDBAdditionalThreadInfo()
            t.additionalInfo = additionalInfo

        pydevd_tracing.SetTrace(debugger.trace_dispatch)

        if not trace_only_current_thread:
            # Trace future threads?
            debugger.patch_threads()


        if suspend:
            debugger.setSuspend(t, CMD_SET_BREAK)


def stoptrace():
    global connected
    if connected:
        pydevd_tracing.RestoreSysSetTraceFunc()
        sys.settrace(None)
        try:
            #not available in jython!
            threading.settrace(None) # for all future threads
        except:
            pass

        from pydev_monkey import undo_patch_thread_modules
        undo_patch_thread_modules()
 
        debugger = GetGlobalDebugger()
 
        if debugger:
  
            debugger.SetTraceForFrameAndParents(
                GetFrame(), also_add_to_passed_frame=True, overwrite_prev_trace=True, dispatch_func=lambda *args:None)
            debugger.exiting()
  
            killAllPydevThreads()

        connected = False

class Dispatcher(object):
    def __init__(self):
        self.port = None

    def connect(self, host, port):
        self.host  = host
        self.port = port
        self.client = StartClient(self.host, self.port)
        self.reader = DispatchReader(self)
        self.reader.dontTraceMe = False #we run reader in the same thread so we don't want to loose tracing
        self.reader.run()

    def close(self):
        try:
            self.reader.doKillPydevThread()
        except :
            pass

class DispatchReader(ReaderThread):
    def __init__(self, dispatcher):
        self.dispatcher = dispatcher
        ReaderThread.__init__(self, self.dispatcher.client)

    def OnRun(self):
        dummy_thread = threading.currentThread()
        dummy_thread.is_pydev_daemon_thread = False
        return ReaderThread.OnRun(self)
        
    def handleExcept(self):
        ReaderThread.handleExcept(self)

    def processCommand(self, cmd_id, seq, text):
        if cmd_id == 99:
            self.dispatcher.port = int(text)
            self.killReceived = True


DISPATCH_APPROACH_NEW_CONNECTION = 1 # Used by PyDev
DISPATCH_APPROACH_EXISTING_CONNECTION = 2 # Used by PyCharm
DISPATCH_APPROACH = DISPATCH_APPROACH_NEW_CONNECTION

def dispatch():
    setup = SetupHolder.setup
    host = setup['client']
    port = setup['port']
    if DISPATCH_APPROACH == DISPATCH_APPROACH_EXISTING_CONNECTION:
        dispatcher = Dispatcher()
        try:
            dispatcher.connect(host, port)
            port = dispatcher.port
        finally:
            dispatcher.close()
    return host, port


def settrace_forked():
    '''
    When creating a fork from a process in the debugger, we need to reset the whole debugger environment!
    '''
    host, port = dispatch()

    import pydevd_tracing
    pydevd_tracing.RestoreSysSetTraceFunc()

    if port is not None:
        global connected
        connected = False

        CustomFramesContainerInit()

        settrace(
            host,
            port=port,
            suspend=False,
            trace_only_current_thread=False,
            overwrite_prev_trace=True,
            patch_multiprocessing=True,
            )

#=======================================================================================================================
# SetupHolder
#=======================================================================================================================
class SetupHolder:

    setup = None


#=======================================================================================================================
# main
#=======================================================================================================================
if __name__ == '__main__':
    
    # parse the command line. --file is our last argument that is required
    try:
        sys.original_argv = sys.argv[:]
        setup = processCommandLine(sys.argv)
        SetupHolder.setup = setup
    except ValueError:
        traceback.print_exc()
        usage(1)

    if setup['print-in-debugger-startup']:
        try:
            pid = ' (pid: %s)' % os.getpid()
        except:
            pid = ''
        sys.stderr.write("pydev debugger: starting%s\n" % pid)

    fix_getpass.fixGetpass()

    pydev_log.debug("Executing file %s" % setup['file'])
    pydev_log.debug("arguments: %s"% str(sys.argv))


    pydevd_vm_type.SetupType(setup.get('vm_type', None))

    if os.getenv('PYCHARM_DEBUG'):
        set_debug(setup)

    DebugInfoHolder.DEBUG_RECORD_SOCKET_READS = setup.get('DEBUG_RECORD_SOCKET_READS', False)
    DebugInfoHolder.DEBUG_TRACE_BREAKPOINTS = setup.get('DEBUG_TRACE_BREAKPOINTS', -1)
    DebugInfoHolder.DEBUG_TRACE_LEVEL = setup.get('DEBUG_TRACE_LEVEL', -1)

    port = setup['port']
    host = setup['client']
    f = setup['file']
    fix_app_engine_debug = False


    try:
        import pydev_monkey
    except:
        pass #Not usable on jython 2.1
    else:
        if setup['multiprocess']: # PyDev
            pydev_monkey.patch_new_process_functions()

        elif setup['multiproc']: # PyCharm
            pydev_log.debug("Started in multiproc mode\n")
            # Note: we're not inside method, so, no need for 'global'
            DISPATCH_APPROACH = DISPATCH_APPROACH_EXISTING_CONNECTION

            dispatcher = Dispatcher()
            try:
                dispatcher.connect(host, port)
                if dispatcher.port is not None:
                    port = dispatcher.port
                    pydev_log.debug("Received port %d\n" %port)
                    pydev_log.info("pydev debugger: process %d is connecting\n"% os.getpid())

                    try:
                        pydev_monkey.patch_new_process_functions()
                    except:
                        pydev_log.error("Error patching process functions\n")
                        traceback.print_exc()
                else:
                    pydev_log.error("pydev debugger: couldn't get port for new debug process\n")
            finally:
                dispatcher.close()
        else:
            pydev_log.info("pydev debugger: starting\n")

            try:
                pydev_monkey.patch_new_process_functions_with_warning()
            except:
                pydev_log.error("Error patching process functions\n")
                traceback.print_exc()

            # Only do this patching if we're not running with multiprocess turned on.
            if f.find('dev_appserver.py') != -1:
                if os.path.basename(f).startswith('dev_appserver.py'):
                    appserver_dir = os.path.dirname(f)
                    version_file = os.path.join(appserver_dir, 'VERSION')
                    if os.path.exists(version_file):
                        try:
                            stream = open(version_file, 'r')
                            try:
                                for line in stream.read().splitlines():
                                    line = line.strip()
                                    if line.startswith('release:'):
                                        line = line[8:].strip()
                                        version = line.replace('"', '')
                                        version = version.split('.')
                                        if int(version[0]) > 1:
                                            fix_app_engine_debug = True

                                        elif int(version[0]) == 1:
                                            if int(version[1]) >= 7:
                                                # Only fix from 1.7 onwards
                                                fix_app_engine_debug = True
                                        break
                            finally:
                                stream.close()
                        except:
                            traceback.print_exc()

    try:
        # In the default run (i.e.: run directly on debug mode), we try to patch stackless as soon as possible
        # on a run where we have a remote debug, we may have to be more careful because patching stackless means
        # that if the user already had a stackless.set_schedule_callback installed, he'd loose it and would need
        # to call it again (because stackless provides no way of getting the last function which was registered
        # in set_schedule_callback).
        #
        # So, ideally, if there's an application using stackless and the application wants to use the remote debugger
        # and benefit from stackless debugging, the application itself must call:
        #
        # import pydevd_stackless
        # pydevd_stackless.patch_stackless()
        #
        # itself to be able to benefit from seeing the tasklets created before the remote debugger is attached.
        import pydevd_stackless
        pydevd_stackless.patch_stackless()
    except:
        pass  # It's ok not having stackless there...

    debugger = PyDB()

    if setup['cmd-line']:
        debugger.cmd_line = True


    if fix_app_engine_debug:
        sys.stderr.write("pydev debugger: google app engine integration enabled\n")
        curr_dir = os.path.dirname(__file__)
        app_engine_startup_file = os.path.join(curr_dir, 'pydev_app_engine_debug_startup.py')

        sys.argv.insert(1, '--python_startup_script=' + app_engine_startup_file)
        import json
        setup['pydevd'] = __file__
        sys.argv.insert(2, '--python_startup_args=%s' % json.dumps(setup),)
        sys.argv.insert(3, '--automatic_restart=no')
        sys.argv.insert(4, '--max_module_instances=1')

        # Run the dev_appserver
        debugger.run(setup['file'], None, None, set_trace=False)
    else:
        # as to get here all our imports are already resolved, the psyco module can be
        # changed and we'll still get the speedups in the debugger, as those functions
        # are already compiled at this time.
        try:
            import psyco
        except ImportError:
            if hasattr(sys, 'exc_clear'):  # jython does not have it
                sys.exc_clear()  # don't keep the traceback -- clients don't want to see it
            pass  # that's ok, no need to mock psyco if it's not available anyways
        else:
            # if it's available, let's change it for a stub (pydev already made use of it)
            import pydevd_psyco_stub
            sys.modules['psyco'] = pydevd_psyco_stub

        if setup['save-signatures']:
            if pydevd_vm_type.GetVmType() == pydevd_vm_type.PydevdVmType.JYTHON:
                sys.stderr.write("Collecting run-time type information is not supported for Jython\n")
            else:
                # Only import it if we're going to use it!
                from pydevd_signature import SignatureFactory
                debugger.signature_factory = SignatureFactory()

        try:
            debugger.connect(host, port)
        except:
            sys.stderr.write("Could not connect to %s: %s\n" % (host, port))
            traceback.print_exc()
            sys.exit(1)

        connected = True  # Mark that we're connected when started from inside ide.

        globals = debugger.run(setup['file'], None, None)

        if setup['cmd-line']:
            debugger.wait_for_commands(globals)


