Updates from PyDev.Debugger

This commit is contained in:
Elizaveta Shashkova
2015-11-23 19:37:05 +03:00
parent 7ac2ffe72d
commit d9e2d895eb
+101 -51
View File
@@ -1,16 +1,62 @@
# License: EPL
import os
import sys
import traceback
import pydev_log
try:
xrange
except:
xrange = range
#===============================================================================
# Things that are dependent on having the pydevd debugger
#===============================================================================
def log_debug(msg):
import pydev_log
pydev_log.debug(msg)
def log_error_once(msg):
import pydev_log
pydev_log.error_once(msg)
pydev_src_dir = os.path.dirname(__file__)
from pydevd_constants import xrange
def _get_python_c_args(host, port, indC, args):
return ("import sys; sys.path.append(r'%s'); import pydevd; "
"pydevd.settrace(host='%s', port=%s, suspend=False, trace_only_current_thread=False, patch_multiprocessing=True); %s"
) % (
pydev_src_dir,
host,
port,
args[indC + 1])
def _get_host_port():
import pydevd
host, port = pydevd.dispatch()
return host, port
def _is_managed_arg(arg):
if arg.endswith('pydevd.py'):
return True
return False
def _on_forked_process():
import pydevd
pydevd.threadingCurrentThread().__pydevd_main_thread = True
pydevd.settrace_forked()
def _on_set_trace_for_new_thread():
from pydevd_comm import GetGlobalDebugger
global_debugger = GetGlobalDebugger()
if global_debugger is not None:
global_debugger.SetTrace(global_debugger.trace_dispatch)
#===============================================================================
# Things related to monkey-patching
#===============================================================================
def is_python(path):
if path.endswith("'") or path.endswith('"'):
path = path[1:len(path)-1]
path = path[1:len(path) - 1]
filename = os.path.basename(path).lower()
for name in ['python', 'jython', 'pypy']:
if filename.find(name) != -1:
@@ -20,7 +66,7 @@ def is_python(path):
def patch_args(args):
try:
pydev_log.debug("Patching args: %s"% str(args))
log_debug("Patching args: %s"% str(args))
import sys
new_args = []
@@ -35,19 +81,16 @@ def patch_args(args):
indC = -1
if indC != -1:
import pydevd
host, port = pydevd.dispatch()
host, port = _get_host_port()
if port is not None:
new_args.extend(args)
new_args[indC + 1] = ("import sys; sys.path.append(r'%s'); import pydevd; "
"pydevd.settrace(host='%s', port=%s, suspend=False, trace_only_current_thread=False, patch_multiprocessing=True); %s") % (
pydev_src_dir, host, port, args[indC + 1])
new_args[indC + 1] = _get_python_c_args(host, port, indC, args)
return new_args
else:
new_args.append(args[0])
else:
pydev_log.debug("Process is not python, returning.")
log_debug("Process is not python, returning.")
return args
i = 1
@@ -58,7 +101,7 @@ def patch_args(args):
break
i += 1
if i < len(args) and args[i].endswith('pydevd.py'): #no need to add pydevd twice
if i < len(args) and _is_managed_arg(args[i]): # no need to add pydevd twice
return args
for x in sys.original_argv:
@@ -108,7 +151,7 @@ def str_to_args_windows(args):
for i in xrange(args_len):
ch = args[i]
if (ch == '\\'):
backslashes+=1
backslashes += 1
continue
elif (backslashes != 0):
if ch == '"':
@@ -122,16 +165,16 @@ def str_to_args_windows(args):
buf += '"'
backslashes = 0
continue
# else fall through to switch
# else fall through to switch
else:
# false alarm, treat passed backslashes literally...
if (state == DEFAULT):
state = ARG
while backslashes > 0:
backslashes-=1
backslashes -= 1
buf += '\\'
# fall through to switch
# fall through to switch
if ch in (' ', '\t'):
if (state == DEFAULT):
# skip
@@ -156,9 +199,10 @@ def str_to_args_windows(args):
# Two consecutive double quotes inside a double-quoted argument are interpreted as
# a single double quote.
buf += '"'
i+=1
i += 1
elif len(buf) == 0:
# empty string on Windows platform. Account for bug in constructor of JDK's java.lang.ProcessImpl.
# empty string on Windows platform. Account for bug in constructor of
# JDK's java.lang.ProcessImpl.
result.append("\"\"")
state = DEFAULT
else:
@@ -180,7 +224,7 @@ def patch_arg_str_win(arg_str):
if not is_python(args[0]):
return arg_str
arg_str = args_to_str(patch_args(args))
pydev_log.debug("New args: %s" % arg_str)
log_debug("New args: %s" % arg_str)
return arg_str
def monkey_patch_module(module, funcname, create_func):
@@ -196,11 +240,9 @@ def monkey_patch_os(funcname, create_func):
def warn_multiproc():
import pydev_log
pydev_log.error_once(
"pydev debugger: New process is launching (breakpoints won't work in the new process).\n"
"pydev debugger: To debug that process please enable 'Attach to subprocess automatically while debugging?' option in the debugger settings.\n")
log_error_once(
"pydev debugger: New process is launching (breakpoints won't work in the new process).\n"
"pydev debugger: To debug that process please enable 'Attach to subprocess automatically while debugging?' option in the debugger settings.\n")
def create_warn_multiproc(original_name):
@@ -226,6 +268,7 @@ os.execlpe(file, arg0, arg1, ..., env)
return getattr(os, original_name)(path, *args)
return new_execl
def create_execv(original_name):
def new_execv(path, args):
'''
@@ -236,6 +279,7 @@ os.execvp(file, args)
return getattr(os, original_name)(path, patch_args(args))
return new_execv
def create_execve(original_name):
"""
os.execve(path, args, env)
@@ -258,6 +302,7 @@ os.spawnlp(mode, file, arg0, arg1, ...)
return getattr(os, original_name)(mode, path, *args)
return new_spawnl
def create_spawnv(original_name):
def new_spawnv(mode, path, args):
'''
@@ -268,6 +313,7 @@ os.spawnvp(mode, file, args)
return getattr(os, original_name)(mode, path, patch_args(args))
return new_spawnv
def create_spawnve(original_name):
"""
os.spawnve(mode, path, args, env)
@@ -278,6 +324,7 @@ os.spawnvpe(mode, file, args, env)
return getattr(os, original_name)(mode, path, patch_args(args), env)
return new_spawnve
def create_fork_exec(original_name):
"""
_posixsubprocess.fork_exec(args, executable_list, close_fds, ... (13 more))
@@ -288,6 +335,7 @@ _posixsubprocess.fork_exec(args, executable_list, close_fds, ... (13 more))
return getattr(_posixsubprocess, original_name)(args, *other_args)
return new_fork_exec
def create_CreateProcess(original_name):
"""
CreateProcess(*args, **kwargs)
@@ -300,6 +348,7 @@ CreateProcess(*args, **kwargs)
return getattr(_subprocess, original_name)(appName, patch_arg_str_win(commandLine), *args)
return new_CreateProcess
def create_CreateProcessWarnMultiproc(original_name):
"""
CreateProcess(*args, **kwargs)
@@ -313,27 +362,26 @@ CreateProcess(*args, **kwargs)
return getattr(_subprocess, original_name)(*args)
return new_CreateProcess
def create_fork(original_name):
def new_fork():
import os
child_process = getattr(os, original_name)() # fork
child_process = getattr(os, original_name)() # fork
if not child_process:
import pydevd
pydevd.threadingCurrentThread().__pydevd_main_thread = True
pydevd.settrace_forked()
_on_forked_process()
return child_process
return new_fork
def patch_new_process_functions():
#os.execl(path, arg0, arg1, ...)
#os.execle(path, arg0, arg1, ..., env)
#os.execlp(file, arg0, arg1, ...)
#os.execlpe(file, arg0, arg1, ..., env)
#os.execv(path, args)
#os.execve(path, args, env)
#os.execvp(file, args)
#os.execvpe(file, args, env)
# os.execl(path, arg0, arg1, ...)
# os.execle(path, arg0, arg1, ..., env)
# os.execlp(file, arg0, arg1, ...)
# os.execlpe(file, arg0, arg1, ..., env)
# os.execv(path, args)
# os.execve(path, args, env)
# os.execvp(file, args)
# os.execvpe(file, args, env)
monkey_patch_os('execl', create_execl)
monkey_patch_os('execle', create_execl)
monkey_patch_os('execlp', create_execl)
@@ -343,14 +391,14 @@ def patch_new_process_functions():
monkey_patch_os('execvp', create_execv)
monkey_patch_os('execvpe', create_execve)
#os.spawnl(mode, path, ...)
#os.spawnle(mode, path, ..., env)
#os.spawnlp(mode, file, ...)
#os.spawnlpe(mode, file, ..., env)
#os.spawnv(mode, path, args)
#os.spawnve(mode, path, args, env)
#os.spawnvp(mode, file, args)
#os.spawnvpe(mode, file, args, env)
# os.spawnl(mode, path, ...)
# os.spawnle(mode, path, ..., env)
# os.spawnlp(mode, file, ...)
# os.spawnlpe(mode, file, ..., env)
# os.spawnv(mode, path, args)
# os.spawnve(mode, path, args, env)
# os.spawnvp(mode, file, args)
# os.spawnvpe(mode, file, args, env)
monkey_patch_os('spawnl', create_spawnl)
monkey_patch_os('spawnle', create_spawnl)
@@ -369,7 +417,7 @@ def patch_new_process_functions():
except ImportError:
pass
else:
#Windows
# Windows
try:
import _subprocess
except ImportError:
@@ -403,7 +451,7 @@ def patch_new_process_functions_with_warning():
except ImportError:
pass
else:
#Windows
# Windows
try:
import _subprocess
except ImportError:
@@ -411,7 +459,6 @@ def patch_new_process_functions_with_warning():
monkey_patch_module(_subprocess, 'CreateProcess', create_CreateProcessWarnMultiproc)
class _NewThreadStartupWithTrace:
def __init__(self, original_func, args, kwargs):
@@ -420,10 +467,9 @@ class _NewThreadStartupWithTrace:
self.kwargs = kwargs
def __call__(self):
_on_set_trace_for_new_thread()
from pydevd_comm import GetGlobalDebugger
global_debugger = GetGlobalDebugger()
if global_debugger is not None:
global_debugger.SetTrace(global_debugger.trace_dispatch)
if global_debugger.thread_analyser is not None:
# we can detect start_new_thread only here
@@ -435,6 +481,7 @@ class _NewThreadStartupWithTrace:
return self.original_func(*self.args, **self.kwargs)
class _NewThreadStartupWithoutTrace:
def __init__(self, original_func, args, kwargs):
@@ -447,6 +494,7 @@ class _NewThreadStartupWithoutTrace:
_UseNewThreadStartup = _NewThreadStartupWithTrace
def _get_threading_modules_to_patch():
threading_modules_to_patch = []
try:
@@ -460,7 +508,6 @@ def _get_threading_modules_to_patch():
threading_modules_to_patch = _get_threading_modules_to_patch()
def patch_thread_module(thread):
if getattr(thread, '_original_start_new_thread', None) is None:
@@ -468,7 +515,6 @@ def patch_thread_module(thread):
else:
_original_start_new_thread = thread._original_start_new_thread
class ClassWithPydevStartNewThread:
def pydev_start_new_thread(self, function, args=(), kwargs={}):
@@ -496,10 +542,12 @@ def patch_thread_module(thread):
except:
pass
def patch_thread_modules():
for t in threading_modules_to_patch:
patch_thread_module(t)
def undo_patch_thread_modules():
for t in threading_modules_to_patch:
try:
@@ -512,6 +560,7 @@ def undo_patch_thread_modules():
except:
pass
def disable_trace_thread_modules():
'''
Can be used to temporarily stop tracing threads created with thread.start_new_thread.
@@ -527,6 +576,7 @@ def enable_trace_thread_modules():
global _UseNewThreadStartup
_UseNewThreadStartup = _NewThreadStartupWithTrace
def get_original_start_new_thread(threading_module):
try:
return threading_module._original_start_new_thread