blob: 8d68cea9876c03a3a6a448f6804fb4e609f8a630 [file] [log] [blame]
Tor Norbye3a2425a2013-11-04 10:16:08 -08001#IMPORTANT: pydevd_constants must be the 1st thing defined because it'll keep a reference to the original sys._getframe
Tor Norbye1aa2e092014-08-20 17:01:23 -07002from __future__ import nested_scopes # Jython 2.1 support
Tor Norbyec3d3a902014-09-04 13:24:04 -07003from pydevd_constants import * # @UnusedWildImport
4
5import pydev_monkey_qt
Tor Norbyee782c572014-09-18 11:43:07 -07006from pydevd_utils import save_main_module
7
Tor Norbyec3d3a902014-09-04 13:24:04 -07008pydev_monkey_qt.patch_qt()
Tor Norbye1aa2e092014-08-20 17:01:23 -07009
Tor Norbyec667c1f2014-05-28 17:06:51 -070010import traceback
11
Tor Norbyee782c572014-09-18 11:43:07 -070012from pydevd_plugin_utils import PluginManager
13
14from pydevd_frame_utils import add_exception_to_frame
Tor Norbye3a2425a2013-11-04 10:16:08 -080015import pydev_imports
16from pydevd_breakpoints import * #@UnusedWildImport
17import fix_getpass
Tor Norbye3a2425a2013-11-04 10:16:08 -080018from pydevd_comm import CMD_CHANGE_VARIABLE, \
19 CMD_EVALUATE_EXPRESSION, \
20 CMD_EXEC_EXPRESSION, \
21 CMD_GET_COMPLETIONS, \
22 CMD_GET_FRAME, \
23 CMD_GET_VARIABLE, \
24 CMD_LIST_THREADS, \
25 CMD_REMOVE_BREAK, \
26 CMD_RUN, \
27 CMD_SET_BREAK, \
28 CMD_SET_NEXT_STATEMENT,\
29 CMD_STEP_INTO, \
30 CMD_STEP_OVER, \
31 CMD_STEP_RETURN, \
32 CMD_THREAD_CREATE, \
33 CMD_THREAD_KILL, \
34 CMD_THREAD_RUN, \
35 CMD_THREAD_SUSPEND, \
36 CMD_RUN_TO_LINE, \
37 CMD_RELOAD_CODE, \
38 CMD_VERSION, \
39 CMD_CONSOLE_EXEC, \
40 CMD_ADD_EXCEPTION_BREAK, \
41 CMD_REMOVE_EXCEPTION_BREAK, \
42 CMD_LOAD_SOURCE, \
43 CMD_ADD_DJANGO_EXCEPTION_BREAK, \
44 CMD_REMOVE_DJANGO_EXCEPTION_BREAK, \
45 CMD_SMART_STEP_INTO,\
Tor Norbye1aa2e092014-08-20 17:01:23 -070046 InternalChangeVariable, \
Tor Norbye3a2425a2013-11-04 10:16:08 -080047 InternalGetCompletions, \
48 InternalEvaluateExpression, \
49 InternalConsoleExec, \
50 InternalGetFrame, \
51 InternalGetVariable, \
52 InternalTerminateThread, \
53 InternalRunThread, \
54 InternalStepThread, \
55 NetCommand, \
56 NetCommandFactory, \
57 PyDBDaemonThread, \
58 _queue, \
59 ReaderThread, \
60 SetGlobalDebugger, \
61 WriterThread, \
62 PydevdFindThreadById, \
63 PydevdLog, \
64 StartClient, \
65 StartServer, \
Tor Norbye1aa2e092014-08-20 17:01:23 -070066 InternalSetNextStatementThread, \
67 ReloadCodeCommand, \
Tor Norbyec3d3a902014-09-04 13:24:04 -070068 ID_TO_MEANING,\
69 CMD_SET_PY_EXCEPTION, \
Tor Norbye1aa2e092014-08-20 17:01:23 -070070 CMD_IGNORE_THROWN_EXCEPTION_AT,\
71 InternalGetBreakpointException, \
72 InternalSendCurrExceptionTrace,\
73 InternalSendCurrExceptionTraceProceeded,\
74 CMD_ENABLE_DONT_TRACE, \
75 CMD_GET_FILE_CONTENTS,\
76 CMD_SET_PROPERTY_TRACE, CMD_RUN_CUSTOM_OPERATION,\
77 InternalRunCustomOperation, CMD_EVALUATE_CONSOLE_EXPRESSION, InternalEvaluateConsoleExpression,\
78 InternalConsoleGetCompletions
79
Tor Norbye3a2425a2013-11-04 10:16:08 -080080from pydevd_file_utils import NormFileToServer, GetFilenameAndBase
81import pydevd_file_utils
82import pydevd_vars
Tor Norbye3a2425a2013-11-04 10:16:08 -080083import pydevd_vm_type
84import pydevd_tracing
85import pydevd_io
Tor Norbye3a2425a2013-11-04 10:16:08 -080086from pydevd_additional_thread_info import PyDBAdditionalThreadInfo
Tor Norbyec667c1f2014-05-28 17:06:51 -070087from pydevd_custom_frames import CustomFramesContainer, CustomFramesContainerInit
Tor Norbye1aa2e092014-08-20 17:01:23 -070088import pydevd_dont_trace
89import pydevd_traceproperty
Tor Norbyec667c1f2014-05-28 17:06:51 -070090
Tor Norbyec3d3a902014-09-04 13:24:04 -070091from _pydev_imps import _pydev_time as time, _pydev_thread
Tor Norbye3a2425a2013-11-04 10:16:08 -080092
Tor Norbyec3d3a902014-09-04 13:24:04 -070093import _pydev_threading as threading
Tor Norbye3a2425a2013-11-04 10:16:08 -080094
95import os
Tor Norbyec3d3a902014-09-04 13:24:04 -070096import atexit
Tor Norbye3a2425a2013-11-04 10:16:08 -080097
98
99threadingEnumerate = threading.enumerate
100threadingCurrentThread = threading.currentThread
101
Tor Norbye1aa2e092014-08-20 17:01:23 -0700102try:
103 '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).
104except:
105 pass
Tor Norbye3a2425a2013-11-04 10:16:08 -0800106
107DONT_TRACE = {
Tor Norbyec667c1f2014-05-28 17:06:51 -0700108 # commonly used things from the stdlib that we don't want to trace
Tor Norbye3a2425a2013-11-04 10:16:08 -0800109 'Queue.py':1,
110 'queue.py':1,
111 'socket.py':1,
Tor Norbyec667c1f2014-05-28 17:06:51 -0700112 'weakref.py':1,
113 'linecache.py':1,
114 'threading.py':1,
Tor Norbye3a2425a2013-11-04 10:16:08 -0800115
Tor Norbyee782c572014-09-18 11:43:07 -0700116 # thirs party libs that we don't want to trace
117 'pluginbase.py':1,
118 'pkgutil_old.py':1,
119 'uuid_old.py':1,
120
Tor Norbye3a2425a2013-11-04 10:16:08 -0800121 #things from pydev that we don't want to trace
Tor Norbye1aa2e092014-08-20 17:01:23 -0700122 '_pydev_execfile.py':1,
123 '_pydev_jython_execfile.py':1,
124 '_pydev_threading':1,
Tor Norbyec3d3a902014-09-04 13:24:04 -0700125 '_pydev_Queue':1,
Tor Norbye1aa2e092014-08-20 17:01:23 -0700126 'django_debug.py':1,
Tor Norbyee782c572014-09-18 11:43:07 -0700127 'jinja2_debug.py':1,
Tor Norbye1aa2e092014-08-20 17:01:23 -0700128 'pydev_log.py':1,
Tor Norbyec3d3a902014-09-04 13:24:04 -0700129 'pydev_monkey.py':1 ,
Tor Norbyec667c1f2014-05-28 17:06:51 -0700130 'pydevd.py':1 ,
Tor Norbye3a2425a2013-11-04 10:16:08 -0800131 'pydevd_additional_thread_info.py':1,
132 'pydevd_comm.py':1,
Tor Norbyec667c1f2014-05-28 17:06:51 -0700133 'pydevd_console.py':1 ,
Tor Norbye3a2425a2013-11-04 10:16:08 -0800134 'pydevd_constants.py':1,
Tor Norbye1aa2e092014-08-20 17:01:23 -0700135 'pydevd_custom_frames.py':1,
136 'pydevd_dont_trace.py':1,
Tor Norbye3a2425a2013-11-04 10:16:08 -0800137 'pydevd_exec.py':1,
138 'pydevd_exec2.py':1,
139 'pydevd_file_utils.py':1,
140 'pydevd_frame.py':1,
Tor Norbyec667c1f2014-05-28 17:06:51 -0700141 'pydevd_import_class.py':1 ,
Tor Norbye3a2425a2013-11-04 10:16:08 -0800142 'pydevd_io.py':1 ,
Tor Norbyec667c1f2014-05-28 17:06:51 -0700143 'pydevd_psyco_stub.py':1,
Tor Norbye1aa2e092014-08-20 17:01:23 -0700144 'pydevd_referrers.py':1 ,
Tor Norbyec667c1f2014-05-28 17:06:51 -0700145 'pydevd_reload.py':1 ,
Tor Norbye3a2425a2013-11-04 10:16:08 -0800146 'pydevd_resolver.py':1 ,
Tor Norbye1aa2e092014-08-20 17:01:23 -0700147 'pydevd_save_locals.py':1 ,
148 'pydevd_signature.py':1,
Tor Norbyec667c1f2014-05-28 17:06:51 -0700149 'pydevd_stackless.py':1 ,
150 'pydevd_traceproperty.py':1,
Tor Norbye3a2425a2013-11-04 10:16:08 -0800151 'pydevd_tracing.py':1 ,
Tor Norbye3a2425a2013-11-04 10:16:08 -0800152 'pydevd_utils.py':1,
153 'pydevd_vars.py':1,
154 'pydevd_vm_type.py':1,
Tor Norbye1aa2e092014-08-20 17:01:23 -0700155 'pydevd_xml.py':1,
Tor Norbyec667c1f2014-05-28 17:06:51 -0700156 }
Tor Norbye3a2425a2013-11-04 10:16:08 -0800157
158if IS_PY3K:
Tor Norbyec667c1f2014-05-28 17:06:51 -0700159 # if we try to trace io.py it seems it can get halted (see http://bugs.python.org/issue4716)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800160 DONT_TRACE['io.py'] = 1
161
Tor Norbyec667c1f2014-05-28 17:06:51 -0700162 # Don't trace common encodings too
163 DONT_TRACE['cp1252.py'] = 1
164 DONT_TRACE['utf_8.py'] = 1
165
Tor Norbye3a2425a2013-11-04 10:16:08 -0800166
167connected = False
168bufferStdOutToServer = False
169bufferStdErrToServer = False
170remote = False
171
Tor Norbyec667c1f2014-05-28 17:06:51 -0700172from _pydev_filesystem_encoding import getfilesystemencoding
173file_system_encoding = getfilesystemencoding()
Tor Norbye3a2425a2013-11-04 10:16:08 -0800174
Tor Norbye1aa2e092014-08-20 17:01:23 -0700175
176# Hack for https://sw-brainwy.rhcloud.com/tracker/PyDev/363 (i.e.: calling isAlive() can throw AssertionError under some circumstances)
177# It is required to debug threads started by start_new_thread in Python 3.4
178_temp = threading.Thread()
179if hasattr(_temp, '_is_stopped'): # Python 3.4 has this
180 def isThreadAlive(t):
181 try:
182 return not t._is_stopped
183 except:
184 return t.isAlive()
185
186elif hasattr(_temp, '_Thread__stopped'): # Python 2.7 has this
187 def isThreadAlive(t):
188 try:
189 return not t._Thread__stopped
190 except:
191 return t.isAlive()
192
193else: # Haven't checked all other versions, so, let's use the regular isAlive call in this case.
194 def isThreadAlive(t):
195 return t.isAlive()
196del _temp
Tor Norbye3a2425a2013-11-04 10:16:08 -0800197
198#=======================================================================================================================
199# PyDBCommandThread
200#=======================================================================================================================
201class PyDBCommandThread(PyDBDaemonThread):
202
203 def __init__(self, pyDb):
204 PyDBDaemonThread.__init__(self)
Tor Norbyec667c1f2014-05-28 17:06:51 -0700205 self._py_db_command_thread_event = pyDb._py_db_command_thread_event
Tor Norbye3a2425a2013-11-04 10:16:08 -0800206 self.pyDb = pyDb
207 self.setName('pydevd.CommandThread')
208
209 def OnRun(self):
Tor Norbye1aa2e092014-08-20 17:01:23 -0700210 for i in xrange(1, 10):
Tor Norbye3a2425a2013-11-04 10:16:08 -0800211 time.sleep(0.5) #this one will only start later on (because otherwise we may not have any non-daemon threads
212 if self.killReceived:
213 return
214
215 if self.dontTraceMe:
216 self.pyDb.SetTrace(None) # no debugging on this thread
217
218 try:
219 while not self.killReceived:
220 try:
221 self.pyDb.processInternalCommands()
222 except:
223 PydevdLog(0, 'Finishing debug communication...(2)')
Tor Norbyec667c1f2014-05-28 17:06:51 -0700224 self._py_db_command_thread_event.clear()
225 self._py_db_command_thread_event.wait(0.5)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800226 except:
227 pydev_log.debug(sys.exc_info()[0])
228
229 #only got this error in interpreter shutdown
230 #PydevdLog(0, 'Finishing debug communication...(3)')
231
232
233def killAllPydevThreads():
Tor Norbyec3d3a902014-09-04 13:24:04 -0700234 threads = DictKeys(PyDBDaemonThread.created_pydb_daemon_threads)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800235 for t in threads:
236 if hasattr(t, 'doKillPydevThread'):
237 t.doKillPydevThread()
Tor Norbye1aa2e092014-08-20 17:01:23 -0700238
Tor Norbye3a2425a2013-11-04 10:16:08 -0800239
240#=======================================================================================================================
241# PyDBCheckAliveThread
242#=======================================================================================================================
243class PyDBCheckAliveThread(PyDBDaemonThread):
244
245 def __init__(self, pyDb):
246 PyDBDaemonThread.__init__(self)
247 self.pyDb = pyDb
Tor Norbye3a2425a2013-11-04 10:16:08 -0800248 self.setName('pydevd.CheckAliveThread')
249
250 def OnRun(self):
251 if self.dontTraceMe:
Tor Norbyec3d3a902014-09-04 13:24:04 -0700252
253 disable_tracing = True
254
255 if pydevd_vm_type.GetVmType() == pydevd_vm_type.PydevdVmType.JYTHON and sys.hexversion <= 0x020201f0:
256 # don't run untraced threads if we're in jython 2.2.1 or lower
257 # jython bug: if we start a thread and another thread changes the tracing facility
258 # it affects other threads (it's not set only for the thread but globally)
259 # Bug: http://sourceforge.net/tracker/index.php?func=detail&aid=1870039&group_id=12867&atid=112867
260 disable_tracing = False
261
262 if disable_tracing:
263 pydevd_tracing.SetTrace(None) # no debugging on this thread
264
Tor Norbye3a2425a2013-11-04 10:16:08 -0800265 while not self.killReceived:
266 if not self.pyDb.haveAliveThreads():
267 try:
268 pydev_log.debug("No alive threads, finishing debug session")
269 self.pyDb.FinishDebuggingSession()
270 killAllPydevThreads()
271 except:
272 traceback.print_exc()
273
Tor Norbye3a2425a2013-11-04 10:16:08 -0800274 self.killReceived = True
275 return
276
277 time.sleep(0.3)
278
279 def doKillPydevThread(self):
280 pass
281
Tor Norbye3a2425a2013-11-04 10:16:08 -0800282
Tor Norbyec667c1f2014-05-28 17:06:51 -0700283
Tor Norbye3a2425a2013-11-04 10:16:08 -0800284#=======================================================================================================================
285# PyDB
286#=======================================================================================================================
287class PyDB:
288 """ Main debugging class
289 Lots of stuff going on here:
290
291 PyDB starts two threads on startup that connect to remote debugger (RDB)
292 The threads continuously read & write commands to RDB.
293 PyDB communicates with these threads through command queues.
294 Every RDB command is processed by calling processNetCommand.
295 Every PyDB net command is sent to the net by posting NetCommand to WriterThread queue
296
297 Some commands need to be executed on the right thread (suspend/resume & friends)
298 These are placed on the internal command queue.
299 """
300
Tor Norbye3a2425a2013-11-04 10:16:08 -0800301
302 def __init__(self):
303 SetGlobalDebugger(self)
304 pydevd_tracing.ReplaceSysSetTraceFunc()
305 self.reader = None
306 self.writer = None
307 self.quitting = None
308 self.cmdFactory = NetCommandFactory()
Tor Norbyec667c1f2014-05-28 17:06:51 -0700309 self._cmd_queue = {} # the hash of Queues. Key is thread id, value is thread
Tor Norbye1aa2e092014-08-20 17:01:23 -0700310
Tor Norbye3a2425a2013-11-04 10:16:08 -0800311 self.breakpoints = {}
Tor Norbye1aa2e092014-08-20 17:01:23 -0700312
313 self.file_to_id_to_line_breakpoint = {}
Tor Norbyee782c572014-09-18 11:43:07 -0700314 self.file_to_id_to_plugin_breakpoint = {}
Tor Norbye1aa2e092014-08-20 17:01:23 -0700315
316 # Note: breakpoints dict should not be mutated: a copy should be created
317 # and later it should be assigned back (to prevent concurrency issues).
318 self.break_on_uncaught_exceptions = {}
319 self.break_on_caught_exceptions = {}
320
Tor Norbye3a2425a2013-11-04 10:16:08 -0800321 self.readyToRun = False
Tor Norbyec3d3a902014-09-04 13:24:04 -0700322 self._main_lock = _pydev_thread.allocate_lock()
323 self._lock_running_thread_ids = _pydev_thread.allocate_lock()
Tor Norbyec667c1f2014-05-28 17:06:51 -0700324 self._py_db_command_thread_event = threading.Event()
325 CustomFramesContainer._py_db_command_thread_event = self._py_db_command_thread_event
Tor Norbye3a2425a2013-11-04 10:16:08 -0800326 self._finishDebuggingSession = False
327 self._terminationEventSent = False
Tor Norbye3a2425a2013-11-04 10:16:08 -0800328 self.signature_factory = None
329 self.SetTrace = pydevd_tracing.SetTrace
Tor Norbye1aa2e092014-08-20 17:01:23 -0700330 self.break_on_exceptions_thrown_in_same_context = False
331 self.ignore_exceptions_thrown_in_lines_with_ignore_exception = True
332
333 # Suspend debugger even if breakpoint condition raises an exception
334 SUSPEND_ON_BREAKPOINT_EXCEPTION = True
335 self.suspend_on_breakpoint_exception = SUSPEND_ON_BREAKPOINT_EXCEPTION
336
337 # By default user can step into properties getter/setter/deleter methods
338 self.disable_property_trace = False
339 self.disable_property_getter_trace = False
340 self.disable_property_setter_trace = False
341 self.disable_property_deleter_trace = False
Tor Norbye3a2425a2013-11-04 10:16:08 -0800342
343 #this is a dict of thread ids pointing to thread ids. Whenever a command is passed to the java end that
344 #acknowledges that a thread was created, the thread id should be passed here -- and if at some time we do not
345 #find that thread alive anymore, we must remove it from this list and make the java side know that the thread
346 #was killed.
347 self._running_thread_ids = {}
Tor Norbye1aa2e092014-08-20 17:01:23 -0700348 self._set_breakpoints_with_id = False
349
350 # This attribute holds the file-> lines which have an @IgnoreException.
351 self.filename_to_lines_where_exceptions_are_ignored = {}
352
Tor Norbyee782c572014-09-18 11:43:07 -0700353 #working with plugins
354 self.plugin = PluginManager(self)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800355
356 def haveAliveThreads(self):
357 for t in threadingEnumerate():
Tor Norbyec3d3a902014-09-04 13:24:04 -0700358 if isinstance(t, PyDBDaemonThread):
359 pydev_log.error_once(
360 'Error in debugger: Found PyDBDaemonThread through threading.enumerate().\n')
361
362 if getattr(t, 'is_pydev_daemon_thread', False):
363 #Important: Jython 2.5rc4 has a bug where a thread created with thread.start_new_thread won't be
364 #set as a daemon thread, so, we also have to check for the 'is_pydev_daemon_thread' flag.
365 #See: https://github.com/fabioz/PyDev.Debugger/issues/11
366 continue
367
368 if isThreadAlive(t) and not t.isDaemon():
Tor Norbye3a2425a2013-11-04 10:16:08 -0800369 return True
370
371 return False
372
373 def FinishDebuggingSession(self):
374 self._finishDebuggingSession = True
375
376 def acquire(self):
377 if PyDBUseLocks:
378 self.lock.acquire()
379 return True
380
381 def release(self):
382 if PyDBUseLocks:
383 self.lock.release()
384 return True
385
386 def initializeNetwork(self, sock):
387 try:
Tor Norbyec667c1f2014-05-28 17:06:51 -0700388 sock.settimeout(None) # infinite, no timeouts from now on - jython does not have it
Tor Norbye3a2425a2013-11-04 10:16:08 -0800389 except:
390 pass
391 self.writer = WriterThread(sock)
392 self.reader = ReaderThread(sock)
393 self.writer.start()
394 self.reader.start()
395
Tor Norbyec667c1f2014-05-28 17:06:51 -0700396 time.sleep(0.1) # give threads time to start
Tor Norbye3a2425a2013-11-04 10:16:08 -0800397
398 def connect(self, host, port):
399 if host:
400 s = StartClient(host, port)
401 else:
402 s = StartServer(port)
403
404 self.initializeNetwork(s)
405
406
407 def getInternalQueue(self, thread_id):
408 """ returns internal command queue for a given thread.
409 if new queue is created, notify the RDB about it """
Tor Norbyec667c1f2014-05-28 17:06:51 -0700410 if thread_id.startswith('__frame__'):
411 thread_id = thread_id[thread_id.rfind('|') + 1:]
Tor Norbye3a2425a2013-11-04 10:16:08 -0800412 try:
413 return self._cmd_queue[thread_id]
414 except KeyError:
415 return self._cmd_queue.setdefault(thread_id, _queue.Queue()) #@UndefinedVariable
416
417
418 def postInternalCommand(self, int_cmd, thread_id):
419 """ if thread_id is *, post to all """
420 if thread_id == "*":
Tor Norbyec667c1f2014-05-28 17:06:51 -0700421 threads = threadingEnumerate()
422 for t in threads:
Tor Norbyec3d3a902014-09-04 13:24:04 -0700423 thread_id = GetThreadId(t)
424 queue = self.getInternalQueue(thread_id)
425 queue.put(int_cmd)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800426
427 else:
428 queue = self.getInternalQueue(thread_id)
429 queue.put(int_cmd)
430
431 def checkOutputRedirect(self):
432 global bufferStdOutToServer
433 global bufferStdErrToServer
434
435 if bufferStdOutToServer:
Tor Norbye1aa2e092014-08-20 17:01:23 -0700436 initStdoutRedirect()
437 self.checkOutput(sys.stdoutBuf, 1) #@UndefinedVariable
Tor Norbye3a2425a2013-11-04 10:16:08 -0800438
439 if bufferStdErrToServer:
Tor Norbye1aa2e092014-08-20 17:01:23 -0700440 initStderrRedirect()
441 self.checkOutput(sys.stderrBuf, 2) #@UndefinedVariable
Tor Norbye3a2425a2013-11-04 10:16:08 -0800442
443 def checkOutput(self, out, outCtx):
444 '''Checks the output to see if we have to send some buffered output to the debug server
445
446 @param out: sys.stdout or sys.stderr
447 @param outCtx: the context indicating: 1=stdout and 2=stderr (to know the colors to write it)
448 '''
449
450 try:
451 v = out.getvalue()
452
453 if v:
454 self.cmdFactory.makeIoMessage(v, outCtx, self)
455 except:
456 traceback.print_exc()
457
458
459 def processInternalCommands(self):
460 '''This function processes internal commands
461 '''
Tor Norbye3a2425a2013-11-04 10:16:08 -0800462 self._main_lock.acquire()
463 try:
464
465 self.checkOutputRedirect()
466
Tor Norbyec667c1f2014-05-28 17:06:51 -0700467 curr_thread_id = GetThreadId(threadingCurrentThread())
468 program_threads_alive = {}
469 all_threads = threadingEnumerate()
470 program_threads_dead = []
Tor Norbye3a2425a2013-11-04 10:16:08 -0800471 self._lock_running_thread_ids.acquire()
472 try:
473 for t in all_threads:
474 thread_id = GetThreadId(t)
475
Tor Norbyec3d3a902014-09-04 13:24:04 -0700476 if isinstance(t, PyDBDaemonThread):
477 pydev_log.error_once('Found PyDBDaemonThread in threading.enumerate.')
478
479 elif getattr(t, 'is_pydev_daemon_thread', False):
480 pass # I.e.: skip the DummyThreads created from pydev daemon threads
481
482 elif isThreadAlive(t):
Tor Norbye3a2425a2013-11-04 10:16:08 -0800483 program_threads_alive[thread_id] = t
484
485 if not DictContains(self._running_thread_ids, thread_id):
486 if not hasattr(t, 'additionalInfo'):
Tor Norbyec667c1f2014-05-28 17:06:51 -0700487 # see http://sourceforge.net/tracker/index.php?func=detail&aid=1955428&group_id=85796&atid=577329
488 # Let's create the additional info right away!
Tor Norbye3a2425a2013-11-04 10:16:08 -0800489 t.additionalInfo = PyDBAdditionalThreadInfo()
490 self._running_thread_ids[thread_id] = t
491 self.writer.addCommand(self.cmdFactory.makeThreadCreatedMessage(t))
492
493
494 queue = self.getInternalQueue(thread_id)
Tor Norbyec667c1f2014-05-28 17:06:51 -0700495 cmdsToReadd = [] # some commands must be processed by the thread itself... if that's the case,
496 # we will re-add the commands to the queue after executing.
Tor Norbye3a2425a2013-11-04 10:16:08 -0800497 try:
498 while True:
499 int_cmd = queue.get(False)
500 if int_cmd.canBeExecutedBy(curr_thread_id):
501 PydevdLog(2, "processing internal command ", str(int_cmd))
502 int_cmd.doIt(self)
503 else:
504 PydevdLog(2, "NOT processing internal command ", str(int_cmd))
505 cmdsToReadd.append(int_cmd)
506
507 except _queue.Empty: #@UndefinedVariable
508 for int_cmd in cmdsToReadd:
509 queue.put(int_cmd)
510 # this is how we exit
511
512
513 thread_ids = list(self._running_thread_ids.keys())
514 for tId in thread_ids:
515 if not DictContains(program_threads_alive, tId):
516 program_threads_dead.append(tId)
517 finally:
518 self._lock_running_thread_ids.release()
519
520 for tId in program_threads_dead:
521 try:
522 self.processThreadNotAlive(tId)
523 except:
524 sys.stderr.write('Error iterating through %s (%s) - %s\n' % (
525 program_threads_alive, program_threads_alive.__class__, dir(program_threads_alive)))
526 raise
527
528
529 if len(program_threads_alive) == 0:
530 self.FinishDebuggingSession()
531 for t in all_threads:
532 if hasattr(t, 'doKillPydevThread'):
533 t.doKillPydevThread()
534
535 finally:
536 self._main_lock.release()
537
538
Tor Norbyec667c1f2014-05-28 17:06:51 -0700539 def setTracingForUntracedContexts(self, ignore_frame=None, overwrite_prev_trace=False):
540 # Enable the tracing for existing threads (because there may be frames being executed that
541 # are currently untraced).
Tor Norbye3a2425a2013-11-04 10:16:08 -0800542 threads = threadingEnumerate()
Tor Norbyec667c1f2014-05-28 17:06:51 -0700543 try:
544 for t in threads:
Tor Norbyec3d3a902014-09-04 13:24:04 -0700545 # TODO: optimize so that we only actually add that tracing if it's in
546 # the new breakpoint context.
547 additionalInfo = None
548 try:
549 additionalInfo = t.additionalInfo
550 except AttributeError:
551 pass # that's ok, no info currently set
Tor Norbye3a2425a2013-11-04 10:16:08 -0800552
Tor Norbyec3d3a902014-09-04 13:24:04 -0700553 if additionalInfo is not None:
554 for frame in additionalInfo.IterFrames():
555 if frame is not ignore_frame:
556 self.SetTraceForFrameAndParents(frame, overwrite_prev_trace=overwrite_prev_trace)
Tor Norbyec667c1f2014-05-28 17:06:51 -0700557 finally:
558 frame = None
559 t = None
560 threads = None
561 additionalInfo = None
Tor Norbye3a2425a2013-11-04 10:16:08 -0800562
563
Tor Norbye1aa2e092014-08-20 17:01:23 -0700564 def consolidate_breakpoints(self, file, id_to_breakpoint, breakpoints):
565 break_dict = {}
566 for breakpoint_id, pybreakpoint in DictIterItems(id_to_breakpoint):
567 break_dict[pybreakpoint.line] = pybreakpoint
568
569 breakpoints[file] = break_dict
570
571
572 def add_break_on_exception(
573 self,
574 exception,
575 notify_always,
576 notify_on_terminate,
577 notify_on_first_raise_only,
578 ):
Tor Norbyee782c572014-09-18 11:43:07 -0700579 try:
580 eb = ExceptionBreakpoint(
581 exception,
582 notify_always,
583 notify_on_terminate,
584 notify_on_first_raise_only,
585 )
586 except ImportError:
587 pydev_log.error("Error unable to add break on exception for: %s (exception could not be imported)\n" % (exception,))
588 return None
Tor Norbye1aa2e092014-08-20 17:01:23 -0700589
590 if eb.notify_on_terminate:
591 cp = self.break_on_uncaught_exceptions.copy()
592 cp[exception] = eb
593 if DebugInfoHolder.DEBUG_TRACE_BREAKPOINTS > 0:
594 pydev_log.error("Exceptions to hook on terminate: %s\n" % (cp,))
595 self.break_on_uncaught_exceptions = cp
596
597 if eb.notify_always:
598 cp = self.break_on_caught_exceptions.copy()
599 cp[exception] = eb
600 if DebugInfoHolder.DEBUG_TRACE_BREAKPOINTS > 0:
601 pydev_log.error("Exceptions to hook always: %s\n" % (cp,))
602 self.break_on_caught_exceptions = cp
603
604 return eb
605
606 def update_after_exceptions_added(self, added):
607 updated_on_caught = False
608 updated_on_uncaught = False
609
610 for eb in added:
611 if not updated_on_uncaught and eb.notify_on_terminate:
612 updated_on_uncaught = True
613 update_exception_hook(self)
614
615 if not updated_on_caught and eb.notify_always:
616 updated_on_caught = True
617 self.setTracingForUntracedContexts()
618
619
Tor Norbye3a2425a2013-11-04 10:16:08 -0800620 def processNetCommand(self, cmd_id, seq, text):
621 '''Processes a command received from the Java side
622
623 @param cmd_id: the id of the command
624 @param seq: the sequence of the command
625 @param text: the text received in the command
626
627 @note: this method is run as a big switch... after doing some tests, it's not clear whether changing it for
628 a dict id --> function call will have better performance result. A simple test with xrange(10000000) showed
629 that the gains from having a fast access to what should be executed are lost because of the function call in
630 a way that if we had 10 elements in the switch the if..elif are better -- but growing the number of choices
631 makes the solution with the dispatch look better -- so, if this gets more than 20-25 choices at some time,
632 it may be worth refactoring it (actually, reordering the ifs so that the ones used mostly come before
633 probably will give better performance).
634 '''
Tor Norbyec3d3a902014-09-04 13:24:04 -0700635 #print(ID_TO_MEANING[str(cmd_id)], repr(text))
Tor Norbye3a2425a2013-11-04 10:16:08 -0800636
637 self._main_lock.acquire()
638 try:
639 try:
640 cmd = None
641 if cmd_id == CMD_RUN:
642 self.readyToRun = True
643
644 elif cmd_id == CMD_VERSION:
645 # response is version number
Tor Norbye1aa2e092014-08-20 17:01:23 -0700646 # ide_os should be 'WINDOWS' or 'UNIX'.
647 ide_os = 'WINDOWS'
Tor Norbye3a2425a2013-11-04 10:16:08 -0800648
Tor Norbye1aa2e092014-08-20 17:01:23 -0700649 # Breakpoints can be grouped by 'LINE' or by 'ID'.
650 breakpoints_by = 'LINE'
651
652 splitted = text.split('\t')
653 if len(splitted) == 1:
654 _local_version = splitted
655
656 elif len(splitted) == 2:
657 _local_version, ide_os = splitted
658
659 elif len(splitted) == 3:
660 _local_version, ide_os, breakpoints_by = splitted
661
662 if breakpoints_by == 'ID':
663 self._set_breakpoints_with_id = True
664 else:
665 self._set_breakpoints_with_id = False
666
667 pydevd_file_utils.set_ide_os(ide_os)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800668
669 cmd = self.cmdFactory.makeVersionMessage(seq)
670
671 elif cmd_id == CMD_LIST_THREADS:
672 # response is a list of threads
673 cmd = self.cmdFactory.makeListThreadsMessage(seq)
674
675 elif cmd_id == CMD_THREAD_KILL:
676 int_cmd = InternalTerminateThread(text)
677 self.postInternalCommand(int_cmd, text)
678
679 elif cmd_id == CMD_THREAD_SUSPEND:
Tor Norbyec667c1f2014-05-28 17:06:51 -0700680 # Yes, thread suspend is still done at this point, not through an internal command!
Tor Norbye3a2425a2013-11-04 10:16:08 -0800681 t = PydevdFindThreadById(text)
682 if t:
683 additionalInfo = None
684 try:
685 additionalInfo = t.additionalInfo
686 except AttributeError:
Tor Norbyec667c1f2014-05-28 17:06:51 -0700687 pass # that's ok, no info currently set
Tor Norbye3a2425a2013-11-04 10:16:08 -0800688
689 if additionalInfo is not None:
690 for frame in additionalInfo.IterFrames():
691 self.SetTraceForFrameAndParents(frame)
692 del frame
693
694 self.setSuspend(t, CMD_THREAD_SUSPEND)
Tor Norbyec667c1f2014-05-28 17:06:51 -0700695 elif text.startswith('__frame__:'):
696 sys.stderr.write("Can't suspend tasklet: %s\n" % (text,))
Tor Norbye3a2425a2013-11-04 10:16:08 -0800697
698 elif cmd_id == CMD_THREAD_RUN:
699 t = PydevdFindThreadById(text)
700 if t:
701 thread_id = GetThreadId(t)
702 int_cmd = InternalRunThread(thread_id)
703 self.postInternalCommand(int_cmd, thread_id)
704
Tor Norbyec667c1f2014-05-28 17:06:51 -0700705 elif text.startswith('__frame__:'):
706 sys.stderr.write("Can't make tasklet run: %s\n" % (text,))
707
708
Tor Norbye3a2425a2013-11-04 10:16:08 -0800709 elif cmd_id == CMD_STEP_INTO or cmd_id == CMD_STEP_OVER or cmd_id == CMD_STEP_RETURN:
Tor Norbyec667c1f2014-05-28 17:06:51 -0700710 # we received some command to make a single step
Tor Norbye3a2425a2013-11-04 10:16:08 -0800711 t = PydevdFindThreadById(text)
712 if t:
713 thread_id = GetThreadId(t)
714 int_cmd = InternalStepThread(thread_id, cmd_id)
715 self.postInternalCommand(int_cmd, thread_id)
716
Tor Norbyec667c1f2014-05-28 17:06:51 -0700717 elif text.startswith('__frame__:'):
718 sys.stderr.write("Can't make tasklet step command: %s\n" % (text,))
719
720
Tor Norbye3a2425a2013-11-04 10:16:08 -0800721 elif cmd_id == CMD_RUN_TO_LINE or cmd_id == CMD_SET_NEXT_STATEMENT or cmd_id == CMD_SMART_STEP_INTO:
Tor Norbyec667c1f2014-05-28 17:06:51 -0700722 # we received some command to make a single step
Tor Norbye3a2425a2013-11-04 10:16:08 -0800723 thread_id, line, func_name = text.split('\t', 2)
724 t = PydevdFindThreadById(thread_id)
725 if t:
726 int_cmd = InternalSetNextStatementThread(thread_id, cmd_id, line, func_name)
727 self.postInternalCommand(int_cmd, thread_id)
Tor Norbyec667c1f2014-05-28 17:06:51 -0700728 elif thread_id.startswith('__frame__:'):
729 sys.stderr.write("Can't set next statement in tasklet: %s\n" % (thread_id,))
Tor Norbye3a2425a2013-11-04 10:16:08 -0800730
731
732 elif cmd_id == CMD_RELOAD_CODE:
Tor Norbyec667c1f2014-05-28 17:06:51 -0700733 # we received some command to make a reload of a module
Tor Norbye3a2425a2013-11-04 10:16:08 -0800734 module_name = text.strip()
Tor Norbye3a2425a2013-11-04 10:16:08 -0800735
Tor Norbyec667c1f2014-05-28 17:06:51 -0700736 thread_id = '*' # Any thread
Tor Norbye3a2425a2013-11-04 10:16:08 -0800737
Tor Norbyec667c1f2014-05-28 17:06:51 -0700738 # Note: not going for the main thread because in this case it'd only do the load
739 # when we stopped on a breakpoint.
740 # for tid, t in self._running_thread_ids.items(): #Iterate in copy
741 # thread_name = t.getName()
742 #
743 # print thread_name, GetThreadId(t)
744 # #Note: if possible, try to reload on the main thread
745 # if thread_name == 'MainThread':
746 # thread_id = tid
747
748 int_cmd = ReloadCodeCommand(module_name, thread_id)
749 self.postInternalCommand(int_cmd, thread_id)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800750
751
752 elif cmd_id == CMD_CHANGE_VARIABLE:
Tor Norbyec667c1f2014-05-28 17:06:51 -0700753 # the text is: thread\tstackframe\tFRAME|GLOBAL\tattribute_to_change\tvalue_to_change
Tor Norbye3a2425a2013-11-04 10:16:08 -0800754 try:
755 thread_id, frame_id, scope, attr_and_value = text.split('\t', 3)
756
757 tab_index = attr_and_value.rindex('\t')
758 attr = attr_and_value[0:tab_index].replace('\t', '.')
759 value = attr_and_value[tab_index + 1:]
760 int_cmd = InternalChangeVariable(seq, thread_id, frame_id, scope, attr, value)
761 self.postInternalCommand(int_cmd, thread_id)
762
763 except:
764 traceback.print_exc()
765
766 elif cmd_id == CMD_GET_VARIABLE:
Tor Norbyec667c1f2014-05-28 17:06:51 -0700767 # we received some command to get a variable
768 # the text is: thread_id\tframe_id\tFRAME|GLOBAL\tattributes*
Tor Norbye3a2425a2013-11-04 10:16:08 -0800769 try:
770 thread_id, frame_id, scopeattrs = text.split('\t', 2)
771
Tor Norbyec667c1f2014-05-28 17:06:51 -0700772 if scopeattrs.find('\t') != -1: # there are attributes beyond scope
Tor Norbye3a2425a2013-11-04 10:16:08 -0800773 scope, attrs = scopeattrs.split('\t', 1)
774 else:
775 scope, attrs = (scopeattrs, None)
776
777 int_cmd = InternalGetVariable(seq, thread_id, frame_id, scope, attrs)
778 self.postInternalCommand(int_cmd, thread_id)
779
780 except:
781 traceback.print_exc()
782
783 elif cmd_id == CMD_GET_COMPLETIONS:
Tor Norbyec667c1f2014-05-28 17:06:51 -0700784 # we received some command to get a variable
785 # the text is: thread_id\tframe_id\tactivation token
Tor Norbye3a2425a2013-11-04 10:16:08 -0800786 try:
787 thread_id, frame_id, scope, act_tok = text.split('\t', 3)
788
789 int_cmd = InternalGetCompletions(seq, thread_id, frame_id, act_tok)
790 self.postInternalCommand(int_cmd, thread_id)
791
792 except:
793 traceback.print_exc()
794
795 elif cmd_id == CMD_GET_FRAME:
796 thread_id, frame_id, scope = text.split('\t', 2)
797
798 int_cmd = InternalGetFrame(seq, thread_id, frame_id)
799 self.postInternalCommand(int_cmd, thread_id)
800
801 elif cmd_id == CMD_SET_BREAK:
Tor Norbyec667c1f2014-05-28 17:06:51 -0700802 # func name: 'None': match anything. Empty: match global, specified: only method context.
Tor Norbyec667c1f2014-05-28 17:06:51 -0700803 # command to add some breakpoint.
Tor Norbye3a2425a2013-11-04 10:16:08 -0800804 # text is file\tline. Add to breakpoints dictionary
Tor Norbye1aa2e092014-08-20 17:01:23 -0700805 if self._set_breakpoints_with_id:
806 breakpoint_id, type, file, line, func_name, condition, expression = text.split('\t', 6)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800807
Tor Norbye1aa2e092014-08-20 17:01:23 -0700808 breakpoint_id = int(breakpoint_id)
809 line = int(line)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800810
Tor Norbyec667c1f2014-05-28 17:06:51 -0700811 # We must restore new lines and tabs as done in
812 # AbstractDebugTarget.breakpointAdded
Tor Norbye3a2425a2013-11-04 10:16:08 -0800813 condition = condition.replace("@_@NEW_LINE_CHAR@_@", '\n').\
814 replace("@_@TAB_CHAR@_@", '\t').strip()
815
Tor Norbye1aa2e092014-08-20 17:01:23 -0700816 expression = expression.replace("@_@NEW_LINE_CHAR@_@", '\n').\
817 replace("@_@TAB_CHAR@_@", '\t').strip()
Tor Norbye3a2425a2013-11-04 10:16:08 -0800818 else:
Tor Norbye1aa2e092014-08-20 17:01:23 -0700819 #Note: this else should be removed after PyCharm migrates to setting
820 #breakpoints by id (and ideally also provides func_name).
821 type, file, line, condition, expression = text.split('\t', 4)
822 # If we don't have an id given for each breakpoint, consider
823 # the id to be the line.
824 breakpoint_id = line = int(line)
825 if condition.startswith('**FUNC**'):
826 func_name, condition = condition.split('\t', 1)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800827
Tor Norbye1aa2e092014-08-20 17:01:23 -0700828 # We must restore new lines and tabs as done in
829 # AbstractDebugTarget.breakpointAdded
830 condition = condition.replace("@_@NEW_LINE_CHAR@_@", '\n').\
831 replace("@_@TAB_CHAR@_@", '\t').strip()
832
833 func_name = func_name[8:]
834 else:
835 func_name = 'None' # Match anything if not specified.
836
837 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.
838 file = file.encode(file_system_encoding)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800839
840 file = NormFileToServer(file)
841
842 if not pydevd_file_utils.exists(file):
843 sys.stderr.write('pydev debugger: warning: trying to add breakpoint'\
844 ' to file that does not exist: %s (will have no effect)\n' % (file,))
845 sys.stderr.flush()
846
Tor Norbye3a2425a2013-11-04 10:16:08 -0800847
848 if len(condition) <= 0 or condition is None or condition == "None":
849 condition = None
850
851 if len(expression) <= 0 or expression is None or expression == "None":
852 expression = None
853
Tor Norbyee782c572014-09-18 11:43:07 -0700854 supported_type = False
Tor Norbye3a2425a2013-11-04 10:16:08 -0800855 if type == 'python-line':
Tor Norbye1aa2e092014-08-20 17:01:23 -0700856 breakpoint = LineBreakpoint(line, condition, func_name, expression)
857 breakpoints = self.breakpoints
858 file_to_id_to_breakpoint = self.file_to_id_to_line_breakpoint
Tor Norbyee782c572014-09-18 11:43:07 -0700859 supported_type = True
Tor Norbye3a2425a2013-11-04 10:16:08 -0800860 else:
Tor Norbyee782c572014-09-18 11:43:07 -0700861 result = self.plugin.add_breakpoint('add_line_breakpoint', self, type, file, line, condition, expression, func_name)
862 if result is not None:
863 supported_type = True
864 breakpoint, breakpoints = result
865 file_to_id_to_breakpoint = self.file_to_id_to_plugin_breakpoint
866 else:
867 supported_type = False
868
869 if not supported_type:
Tor Norbye3a2425a2013-11-04 10:16:08 -0800870 raise NameError(type)
871
Tor Norbye1aa2e092014-08-20 17:01:23 -0700872 if DebugInfoHolder.DEBUG_TRACE_BREAKPOINTS > 0:
873 pydev_log.debug('Added breakpoint:%s - line:%s - func_name:%s\n' % (file, line, func_name.encode('utf-8')))
874 sys.stderr.flush()
875
876 if DictContains(file_to_id_to_breakpoint, file):
877 id_to_pybreakpoint = file_to_id_to_breakpoint[file]
878 else:
879 id_to_pybreakpoint = file_to_id_to_breakpoint[file] = {}
880
881 id_to_pybreakpoint[breakpoint_id] = breakpoint
882 self.consolidate_breakpoints(file, id_to_pybreakpoint, breakpoints)
883
Tor Norbyec3d3a902014-09-04 13:24:04 -0700884 self.setTracingForUntracedContexts(overwrite_prev_trace=True)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800885
886 elif cmd_id == CMD_REMOVE_BREAK:
887 #command to remove some breakpoint
Tor Norbye1aa2e092014-08-20 17:01:23 -0700888 #text is type\file\tid. Remove from breakpoints dictionary
889 breakpoint_type, file, breakpoint_id = text.split('\t', 2)
890
891 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.
892 file = file.encode(file_system_encoding)
893
Tor Norbye3a2425a2013-11-04 10:16:08 -0800894 file = NormFileToServer(file)
Tor Norbye1aa2e092014-08-20 17:01:23 -0700895
Tor Norbye3a2425a2013-11-04 10:16:08 -0800896 try:
Tor Norbye1aa2e092014-08-20 17:01:23 -0700897 breakpoint_id = int(breakpoint_id)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800898 except ValueError:
Tor Norbye1aa2e092014-08-20 17:01:23 -0700899 pydev_log.error('Error removing breakpoint. Expected breakpoint_id to be an int. Found: %s' % (breakpoint_id,))
Tor Norbye3a2425a2013-11-04 10:16:08 -0800900
901 else:
Tor Norbyee782c572014-09-18 11:43:07 -0700902 file_to_id_to_breakpoint = None
Tor Norbye1aa2e092014-08-20 17:01:23 -0700903 if breakpoint_type == 'python-line':
904 breakpoints = self.breakpoints
905 file_to_id_to_breakpoint = self.file_to_id_to_line_breakpoint
Tor Norbye1aa2e092014-08-20 17:01:23 -0700906 else:
Tor Norbyee782c572014-09-18 11:43:07 -0700907 result = self.plugin.get_breakpoints(self, breakpoint_type)
908 if result is not None:
909 file_to_id_to_breakpoint = self.file_to_id_to_plugin_breakpoint
910 breakpoints = result
Tor Norbye1aa2e092014-08-20 17:01:23 -0700911
Tor Norbyee782c572014-09-18 11:43:07 -0700912 if file_to_id_to_breakpoint is None:
913 pydev_log.error('Error removing breakpoint. Cant handle breakpoint of type %s' % breakpoint_type)
914 else:
915 try:
916 id_to_pybreakpoint = file_to_id_to_breakpoint.get(file, {})
917 if DebugInfoHolder.DEBUG_TRACE_BREAKPOINTS > 0:
918 existing = id_to_pybreakpoint[breakpoint_id]
919 sys.stderr.write('Removed breakpoint:%s - line:%s - func_name:%s (id: %s)\n' % (
920 file, existing.line, existing.func_name.encode('utf-8'), breakpoint_id))
Tor Norbye1aa2e092014-08-20 17:01:23 -0700921
Tor Norbyee782c572014-09-18 11:43:07 -0700922 del id_to_pybreakpoint[breakpoint_id]
923 self.consolidate_breakpoints(file, id_to_pybreakpoint, breakpoints)
924 except KeyError:
925 pydev_log.error("Error removing breakpoint: Breakpoint id not found: %s id: %s. Available ids: %s\n" % (
926 file, breakpoint_id, DictKeys(id_to_pybreakpoint)))
Tor Norbye3a2425a2013-11-04 10:16:08 -0800927
Tor Norbye3a2425a2013-11-04 10:16:08 -0800928
929 elif cmd_id == CMD_EVALUATE_EXPRESSION or cmd_id == CMD_EXEC_EXPRESSION:
930 #command to evaluate the given expression
931 #text is: thread\tstackframe\tLOCAL\texpression
932 thread_id, frame_id, scope, expression, trim = text.split('\t', 4)
933 int_cmd = InternalEvaluateExpression(seq, thread_id, frame_id, expression,
934 cmd_id == CMD_EXEC_EXPRESSION, int(trim) == 1)
935 self.postInternalCommand(int_cmd, thread_id)
936
937 elif cmd_id == CMD_CONSOLE_EXEC:
938 #command to exec expression in console, in case expression is only partially valid 'False' is returned
939 #text is: thread\tstackframe\tLOCAL\texpression
940
941 thread_id, frame_id, scope, expression = text.split('\t', 3)
942
943 int_cmd = InternalConsoleExec(seq, thread_id, frame_id, expression)
944 self.postInternalCommand(int_cmd, thread_id)
945
Tor Norbye1aa2e092014-08-20 17:01:23 -0700946 elif cmd_id == CMD_SET_PY_EXCEPTION:
947 # Command which receives set of exceptions on which user wants to break the debugger
948 # text is: break_on_uncaught;break_on_caught;TypeError;ImportError;zipimport.ZipImportError;
949 # This API is optional and works 'in bulk' -- it's possible
950 # to get finer-grained control with CMD_ADD_EXCEPTION_BREAK/CMD_REMOVE_EXCEPTION_BREAK
951 # which allows setting caught/uncaught per exception.
952 #
953 splitted = text.split(';')
954 self.break_on_uncaught_exceptions = {}
955 self.break_on_caught_exceptions = {}
956 added = []
957 if len(splitted) >= 4:
958 if splitted[0] == 'true':
959 break_on_uncaught = True
960 else:
961 break_on_uncaught = False
962
963 if splitted[1] == 'true':
964 break_on_caught = True
965 else:
966 break_on_caught = False
967
968 if splitted[2] == 'true':
969 self.break_on_exceptions_thrown_in_same_context = True
970 else:
971 self.break_on_exceptions_thrown_in_same_context = False
972
973 if splitted[3] == 'true':
974 self.ignore_exceptions_thrown_in_lines_with_ignore_exception = True
975 else:
976 self.ignore_exceptions_thrown_in_lines_with_ignore_exception = False
977
978 for exception_type in splitted[4:]:
979 exception_type = exception_type.strip()
980 if not exception_type:
981 continue
982
983 exception_breakpoint = self.add_break_on_exception(
984 exception_type,
985 notify_always=break_on_caught,
986 notify_on_terminate=break_on_uncaught,
987 notify_on_first_raise_only=False,
988 )
Tor Norbyee782c572014-09-18 11:43:07 -0700989 if exception_breakpoint is None:
990 continue
Tor Norbye1aa2e092014-08-20 17:01:23 -0700991 added.append(exception_breakpoint)
992
993 self.update_after_exceptions_added(added)
994
995 else:
996 sys.stderr.write("Error when setting exception list. Received: %s\n" % (text,))
997
998 elif cmd_id == CMD_GET_FILE_CONTENTS:
999
1000 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.
1001 text = text.encode(file_system_encoding)
1002
1003 if os.path.exists(text):
1004 f = open(text, 'r')
1005 try:
1006 source = f.read()
1007 finally:
1008 f.close()
1009 cmd = self.cmdFactory.makeGetFileContents(seq, source)
1010
1011 elif cmd_id == CMD_SET_PROPERTY_TRACE:
1012 # Command which receives whether to trace property getter/setter/deleter
1013 # text is feature_state(true/false);disable_getter/disable_setter/disable_deleter
1014 if text != "":
1015 splitted = text.split(';')
1016 if len(splitted) >= 3:
1017 if self.disable_property_trace is False and splitted[0] == 'true':
1018 # Replacing property by custom property only when the debugger starts
1019 pydevd_traceproperty.replace_builtin_property()
1020 self.disable_property_trace = True
1021 # Enable/Disable tracing of the property getter
1022 if splitted[1] == 'true':
1023 self.disable_property_getter_trace = True
1024 else:
1025 self.disable_property_getter_trace = False
1026 # Enable/Disable tracing of the property setter
1027 if splitted[2] == 'true':
1028 self.disable_property_setter_trace = True
1029 else:
1030 self.disable_property_setter_trace = False
1031 # Enable/Disable tracing of the property deleter
1032 if splitted[3] == 'true':
1033 self.disable_property_deleter_trace = True
1034 else:
1035 self.disable_property_deleter_trace = False
1036 else:
1037 # User hasn't configured any settings for property tracing
1038 pass
1039
Tor Norbye3a2425a2013-11-04 10:16:08 -08001040 elif cmd_id == CMD_ADD_EXCEPTION_BREAK:
Tor Norbyee782c572014-09-18 11:43:07 -07001041 if text.find('\t') != -1:
1042 exception, notify_always, notify_on_terminate = text.split('\t', 2)
1043 else:
1044 exception, notify_always, notify_on_terminate = text, 0, 0
1045
1046 if exception.find('-') != -1:
1047 type, exception = exception.split('-')
1048 else:
1049 type = 'python'
1050
1051 if type == 'python':
1052 exception_breakpoint = self.add_break_on_exception(
1053 exception,
1054 notify_always=int(notify_always) > 0,
1055 notify_on_terminate = int(notify_on_terminate) == 1,
1056 notify_on_first_raise_only=int(notify_always) == 2
1057 )
1058
1059 if exception_breakpoint is not None:
1060 self.update_after_exceptions_added([exception_breakpoint])
1061 else:
1062 supported_type = self.plugin.add_breakpoint('add_exception_breakpoint', self, type, exception)
1063
1064 if not supported_type:
1065 raise NameError(type)
1066
1067
Tor Norbye3a2425a2013-11-04 10:16:08 -08001068
1069 elif cmd_id == CMD_REMOVE_EXCEPTION_BREAK:
1070 exception = text
Tor Norbyee782c572014-09-18 11:43:07 -07001071 if exception.find('-') != -1:
1072 type, exception = exception.split('-')
1073 else:
1074 type = 'python'
Tor Norbye1aa2e092014-08-20 17:01:23 -07001075
Tor Norbyee782c572014-09-18 11:43:07 -07001076 if type == 'python':
1077 try:
1078 cp = self.break_on_uncaught_exceptions.copy()
1079 DictPop(cp, exception, None)
1080 self.break_on_uncaught_exceptions = cp
1081
1082 cp = self.break_on_caught_exceptions.copy()
1083 DictPop(cp, exception, None)
1084 self.break_on_caught_exceptions = cp
1085 except:
1086 pydev_log.debug("Error while removing exception %s"%sys.exc_info()[0])
1087 update_exception_hook(self)
1088 else:
1089 supported_type = self.plugin.remove_exception_breakpoint(self, type, exception)
1090
1091 if not supported_type:
1092 raise NameError(type)
Tor Norbye3a2425a2013-11-04 10:16:08 -08001093
1094 elif cmd_id == CMD_LOAD_SOURCE:
1095 path = text
1096 try:
1097 f = open(path, 'r')
1098 source = f.read()
1099 self.cmdFactory.makeLoadSourceMessage(seq, source, self)
1100 except:
1101 return self.cmdFactory.makeErrorMessage(seq, pydevd_tracing.GetExceptionTracebackStr())
1102
1103 elif cmd_id == CMD_ADD_DJANGO_EXCEPTION_BREAK:
1104 exception = text
1105
Tor Norbyee782c572014-09-18 11:43:07 -07001106 self.plugin.add_breakpoint('add_exception_breakpoint', self, 'django', exception)
1107
Tor Norbye3a2425a2013-11-04 10:16:08 -08001108
1109 elif cmd_id == CMD_REMOVE_DJANGO_EXCEPTION_BREAK:
1110 exception = text
1111
Tor Norbyee782c572014-09-18 11:43:07 -07001112 self.plugin.remove_exception_breakpoint(self, 'django', exception)
Tor Norbye3a2425a2013-11-04 10:16:08 -08001113
Tor Norbye1aa2e092014-08-20 17:01:23 -07001114 elif cmd_id == CMD_EVALUATE_CONSOLE_EXPRESSION:
1115 # Command which takes care for the debug console communication
1116 if text != "":
1117 thread_id, frame_id, console_command = text.split('\t', 2)
1118 console_command, line = console_command.split('\t')
1119 if console_command == 'EVALUATE':
1120 int_cmd = InternalEvaluateConsoleExpression(seq, thread_id, frame_id, line)
1121 elif console_command == 'GET_COMPLETIONS':
1122 int_cmd = InternalConsoleGetCompletions(seq, thread_id, frame_id, line)
1123 self.postInternalCommand(int_cmd, thread_id)
1124
1125 elif cmd_id == CMD_RUN_CUSTOM_OPERATION:
1126 # Command which runs a custom operation
1127 if text != "":
1128 try:
1129 location, custom = text.split('||', 1)
1130 except:
1131 sys.stderr.write('Custom operation now needs a || separator. Found: %s\n' % (text,))
1132 raise
1133
1134 thread_id, frame_id, scopeattrs = location.split('\t', 2)
1135
1136 if scopeattrs.find('\t') != -1: # there are attributes beyond scope
1137 scope, attrs = scopeattrs.split('\t', 1)
1138 else:
1139 scope, attrs = (scopeattrs, None)
1140
1141 # : style: EXECFILE or EXEC
1142 # : encoded_code_or_file: file to execute or code
1143 # : fname: name of function to be executed in the resulting namespace
1144 style, encoded_code_or_file, fnname = custom.split('\t', 3)
1145 int_cmd = InternalRunCustomOperation(seq, thread_id, frame_id, scope, attrs,
1146 style, encoded_code_or_file, fnname)
1147 self.postInternalCommand(int_cmd, thread_id)
1148
1149 elif cmd_id == CMD_IGNORE_THROWN_EXCEPTION_AT:
1150 if text:
1151 replace = 'REPLACE:' # Not all 3.x versions support u'REPLACE:', so, doing workaround.
1152 if not IS_PY3K:
1153 replace = unicode(replace)
1154
1155 if text.startswith(replace):
1156 text = text[8:]
1157 self.filename_to_lines_where_exceptions_are_ignored.clear()
1158
1159 if text:
1160 for line in text.split('||'): # Can be bulk-created (one in each line)
1161 filename, line_number = line.split('|')
1162 if not IS_PY3K:
1163 filename = filename.encode(file_system_encoding)
1164
1165 filename = NormFileToServer(filename)
1166
1167 if os.path.exists(filename):
1168 lines_ignored = self.filename_to_lines_where_exceptions_are_ignored.get(filename)
1169 if lines_ignored is None:
1170 lines_ignored = self.filename_to_lines_where_exceptions_are_ignored[filename] = {}
1171 lines_ignored[int(line_number)] = 1
1172 else:
1173 sys.stderr.write('pydev debugger: warning: trying to ignore exception thrown'\
1174 ' on file that does not exist: %s (will have no effect)\n' % (filename,))
1175
1176 elif cmd_id == CMD_ENABLE_DONT_TRACE:
1177 if text:
1178 true_str = 'true' # Not all 3.x versions support u'str', so, doing workaround.
1179 if not IS_PY3K:
1180 true_str = unicode(true_str)
1181
1182 mode = text.strip() == true_str
1183 pydevd_dont_trace.trace_filter(mode)
1184
Tor Norbye3a2425a2013-11-04 10:16:08 -08001185 else:
1186 #I have no idea what this is all about
1187 cmd = self.cmdFactory.makeErrorMessage(seq, "unexpected command " + str(cmd_id))
1188
1189 if cmd is not None:
1190 self.writer.addCommand(cmd)
1191 del cmd
1192
1193 except Exception:
1194 traceback.print_exc()
1195 cmd = self.cmdFactory.makeErrorMessage(seq,
1196 "Unexpected exception in processNetCommand.\nInitial params: %s" % ((cmd_id, seq, text),))
1197
1198 self.writer.addCommand(cmd)
1199 finally:
1200 self._main_lock.release()
1201
1202 def processThreadNotAlive(self, threadId):
1203 """ if thread is not alive, cancel trace_dispatch processing """
1204 self._lock_running_thread_ids.acquire()
1205 try:
1206 thread = self._running_thread_ids.pop(threadId, None)
1207 if thread is None:
1208 return
1209
1210 wasNotified = thread.additionalInfo.pydev_notify_kill
1211 if not wasNotified:
1212 thread.additionalInfo.pydev_notify_kill = True
1213
1214 finally:
1215 self._lock_running_thread_ids.release()
1216
1217 cmd = self.cmdFactory.makeThreadKilledMessage(threadId)
1218 self.writer.addCommand(cmd)
1219
1220
1221 def setSuspend(self, thread, stop_reason):
1222 thread.additionalInfo.suspend_type = PYTHON_SUSPEND
1223 thread.additionalInfo.pydev_state = STATE_SUSPEND
1224 thread.stop_reason = stop_reason
1225
Tor Norbye1aa2e092014-08-20 17:01:23 -07001226 # If conditional breakpoint raises any exception during evaluation send details to Java
1227 if stop_reason == CMD_SET_BREAK and self.suspend_on_breakpoint_exception:
1228 self.sendBreakpointConditionException(thread)
1229
1230
1231 def sendBreakpointConditionException(self, thread):
1232 """If conditional breakpoint raises an exception during evaluation
1233 send exception details to java
1234 """
1235 thread_id = GetThreadId(thread)
1236 conditional_breakpoint_exception_tuple = thread.additionalInfo.conditional_breakpoint_exception
1237 # conditional_breakpoint_exception_tuple - should contain 2 values (exception_type, stacktrace)
1238 if conditional_breakpoint_exception_tuple and len(conditional_breakpoint_exception_tuple) == 2:
1239 exc_type, stacktrace = conditional_breakpoint_exception_tuple
1240 int_cmd = InternalGetBreakpointException(thread_id, exc_type, stacktrace)
1241 # Reset the conditional_breakpoint_exception details to None
1242 thread.additionalInfo.conditional_breakpoint_exception = None
1243 self.postInternalCommand(int_cmd, thread_id)
1244
1245
1246 def sendCaughtExceptionStack(self, thread, arg, curr_frame_id):
1247 """Sends details on the exception which was caught (and where we stopped) to the java side.
1248
1249 arg is: exception type, description, traceback object
1250 """
1251 thread_id = GetThreadId(thread)
1252 int_cmd = InternalSendCurrExceptionTrace(thread_id, arg, curr_frame_id)
1253 self.postInternalCommand(int_cmd, thread_id)
1254
1255
1256 def sendCaughtExceptionStackProceeded(self, thread):
1257 """Sends that some thread was resumed and is no longer showing an exception trace.
1258 """
1259 thread_id = GetThreadId(thread)
1260 int_cmd = InternalSendCurrExceptionTraceProceeded(thread_id)
1261 self.postInternalCommand(int_cmd, thread_id)
1262 self.processInternalCommands()
1263
Tor Norbye3a2425a2013-11-04 10:16:08 -08001264
1265 def doWaitSuspend(self, thread, frame, event, arg): #@UnusedVariable
1266 """ busy waits until the thread state changes to RUN
1267 it expects thread's state as attributes of the thread.
1268 Upon running, processes any outstanding Stepping commands.
1269 """
1270 self.processInternalCommands()
1271
1272 message = getattr(thread.additionalInfo, "message", None)
1273
1274 cmd = self.cmdFactory.makeThreadSuspendMessage(GetThreadId(thread), frame, thread.stop_reason, message)
1275 self.writer.addCommand(cmd)
1276
Tor Norbyec667c1f2014-05-28 17:06:51 -07001277 CustomFramesContainer.custom_frames_lock.acquire()
1278 try:
1279 from_this_thread = []
Tor Norbye3a2425a2013-11-04 10:16:08 -08001280
Tor Norbye1aa2e092014-08-20 17:01:23 -07001281 for frame_id, custom_frame in DictIterItems(CustomFramesContainer.custom_frames):
Tor Norbyec667c1f2014-05-28 17:06:51 -07001282 if custom_frame.thread_id == thread.ident:
1283 # print >> sys.stderr, 'Frame created: ', frame_id
1284 self.writer.addCommand(self.cmdFactory.makeCustomFrameCreatedMessage(frame_id, custom_frame.name))
1285 self.writer.addCommand(self.cmdFactory.makeThreadSuspendMessage(frame_id, custom_frame.frame, CMD_THREAD_SUSPEND, ""))
1286
1287 from_this_thread.append(frame_id)
1288
1289 finally:
1290 CustomFramesContainer.custom_frames_lock.release()
1291
1292
1293
1294 info = thread.additionalInfo
Tor Norbye3a2425a2013-11-04 10:16:08 -08001295 while info.pydev_state == STATE_SUSPEND and not self._finishDebuggingSession:
1296 self.processInternalCommands()
1297 time.sleep(0.01)
1298
Tor Norbyec667c1f2014-05-28 17:06:51 -07001299 # process any stepping instructions
Tor Norbye3a2425a2013-11-04 10:16:08 -08001300 if info.pydev_step_cmd == CMD_STEP_INTO:
1301 info.pydev_step_stop = None
1302 info.pydev_smart_step_stop = None
1303
1304 elif info.pydev_step_cmd == CMD_STEP_OVER:
1305 info.pydev_step_stop = frame
1306 info.pydev_smart_step_stop = None
1307 self.SetTraceForFrameAndParents(frame)
1308
1309 elif info.pydev_step_cmd == CMD_SMART_STEP_INTO:
1310 self.SetTraceForFrameAndParents(frame)
1311 info.pydev_step_stop = None
1312 info.pydev_smart_step_stop = frame
1313
1314 elif info.pydev_step_cmd == CMD_RUN_TO_LINE or info.pydev_step_cmd == CMD_SET_NEXT_STATEMENT :
1315 self.SetTraceForFrameAndParents(frame)
1316
1317 if event == 'line' or event == 'exception':
1318 #If we're already in the correct context, we have to stop it now, because we can act only on
1319 #line events -- if a return was the next statement it wouldn't work (so, we have this code
1320 #repeated at pydevd_frame).
1321 stop = False
1322 curr_func_name = frame.f_code.co_name
1323
1324 #global context is set with an empty name
1325 if curr_func_name in ('?', '<module>'):
1326 curr_func_name = ''
1327
1328 if curr_func_name == info.pydev_func_name:
1329 line = info.pydev_next_line
1330 if frame.f_lineno == line:
1331 stop = True
1332 else :
1333 if frame.f_trace is None:
1334 frame.f_trace = self.trace_dispatch
1335 frame.f_lineno = line
1336 frame.f_trace = None
1337 stop = True
1338 if stop:
1339 info.pydev_state = STATE_SUSPEND
1340 self.doWaitSuspend(thread, frame, event, arg)
1341 return
1342
1343
1344 elif info.pydev_step_cmd == CMD_STEP_RETURN:
1345 back_frame = frame.f_back
1346 if back_frame is not None:
Tor Norbyec667c1f2014-05-28 17:06:51 -07001347 # steps back to the same frame (in a return call it will stop in the 'back frame' for the user)
Tor Norbye3a2425a2013-11-04 10:16:08 -08001348 info.pydev_step_stop = frame
1349 self.SetTraceForFrameAndParents(frame)
1350 else:
Tor Norbyec667c1f2014-05-28 17:06:51 -07001351 # No back frame?!? -- this happens in jython when we have some frame created from an awt event
1352 # (the previous frame would be the awt event, but this doesn't make part of 'jython', only 'java')
1353 # so, if we're doing a step return in this situation, it's the same as just making it run
Tor Norbye3a2425a2013-11-04 10:16:08 -08001354 info.pydev_step_stop = None
1355 info.pydev_step_cmd = None
1356 info.pydev_state = STATE_RUN
1357
1358 del frame
1359 cmd = self.cmdFactory.makeThreadRunMessage(GetThreadId(thread), info.pydev_step_cmd)
1360 self.writer.addCommand(cmd)
1361
Tor Norbyec667c1f2014-05-28 17:06:51 -07001362 CustomFramesContainer.custom_frames_lock.acquire()
1363 try:
1364 # The ones that remained on last_running must now be removed.
1365 for frame_id in from_this_thread:
1366 # print >> sys.stderr, 'Removing created frame: ', frame_id
1367 self.writer.addCommand(self.cmdFactory.makeThreadKilledMessage(frame_id))
1368
1369 finally:
1370 CustomFramesContainer.custom_frames_lock.release()
Tor Norbye3a2425a2013-11-04 10:16:08 -08001371
1372 def handle_post_mortem_stop(self, additionalInfo, t):
1373 pydev_log.debug("We are stopping in post-mortem\n")
Tor Norbye3a2425a2013-11-04 10:16:08 -08001374 frame, frames_byid = additionalInfo.pydev_force_stop_at_exception
1375 thread_id = GetThreadId(t)
1376 pydevd_vars.addAdditionalFrameById(thread_id, frames_byid)
1377 try:
1378 try:
1379 add_exception_to_frame(frame, additionalInfo.exception)
1380 self.setSuspend(t, CMD_ADD_EXCEPTION_BREAK)
1381 self.doWaitSuspend(t, frame, 'exception', None)
1382 except:
1383 pydev_log.error("We've got an error while stopping in post-mortem: %s\n"%sys.exc_info()[0])
1384 finally:
1385 additionalInfo.pydev_force_stop_at_exception = None
1386 pydevd_vars.removeAdditionalFrameById(thread_id)
1387
1388 def trace_dispatch(self, frame, event, arg):
1389 ''' This is the callback used when we enter some context in the debugger.
1390
1391 We also decorate the thread we are in with info about the debugging.
1392 The attributes added are:
1393 pydev_state
1394 pydev_step_stop
1395 pydev_step_cmd
1396 pydev_notify_kill
1397 '''
1398 try:
1399 if self._finishDebuggingSession and not self._terminationEventSent:
1400 #that was not working very well because jython gave some socket errors
Tor Norbye3a2425a2013-11-04 10:16:08 -08001401 try:
Tor Norbyec3d3a902014-09-04 13:24:04 -07001402 threads = DictKeys(PyDBDaemonThread.created_pydb_daemon_threads)
Tor Norbye3a2425a2013-11-04 10:16:08 -08001403 for t in threads:
1404 if hasattr(t, 'doKillPydevThread'):
1405 t.doKillPydevThread()
1406 except:
1407 traceback.print_exc()
1408 self._terminationEventSent = True
1409 return None
1410
1411 filename, base = GetFilenameAndBase(frame)
1412
1413 is_file_to_ignore = DictContains(DONT_TRACE, base) #we don't want to debug threading or anything related to pydevd
1414
Tor Norbyec3d3a902014-09-04 13:24:04 -07001415 #print('trace_dispatch', base, frame.f_lineno, event, frame.f_code.co_name, is_file_to_ignore)
Tor Norbye3a2425a2013-11-04 10:16:08 -08001416 if is_file_to_ignore:
1417 return None
1418
Tor Norbye3a2425a2013-11-04 10:16:08 -08001419 try:
1420 #this shouldn't give an exception, but it could happen... (python bug)
1421 #see http://mail.python.org/pipermail/python-bugs-list/2007-June/038796.html
1422 #and related bug: http://bugs.python.org/issue1733757
1423 t = threadingCurrentThread()
1424 except:
1425 frame.f_trace = self.trace_dispatch
1426 return self.trace_dispatch
1427
1428 try:
1429 additionalInfo = t.additionalInfo
1430 if additionalInfo is None:
1431 raise AttributeError()
1432 except:
1433 t.additionalInfo = PyDBAdditionalThreadInfo()
1434 additionalInfo = t.additionalInfo
1435
1436 if additionalInfo is None:
1437 return None
1438
1439 if additionalInfo.is_tracing:
1440 f = frame
1441 while f is not None:
Tor Norbye1aa2e092014-08-20 17:01:23 -07001442 if 'trace_dispatch' == f.f_code.co_name:
1443 _fname, bs = GetFilenameAndBase(f)
1444 if bs == 'pydevd_frame.py':
Tor Norbye3a2425a2013-11-04 10:16:08 -08001445 return None #we don't wan't to trace code invoked from pydevd_frame.trace_dispatch
1446 f = f.f_back
1447
1448 # if thread is not alive, cancel trace_dispatch processing
Tor Norbye92584642014-04-17 08:39:25 -07001449 if not isThreadAlive(t):
Tor Norbye3a2425a2013-11-04 10:16:08 -08001450 self.processThreadNotAlive(GetThreadId(t))
Tor Norbye92584642014-04-17 08:39:25 -07001451 return None # suspend tracing
Tor Norbye3a2425a2013-11-04 10:16:08 -08001452
Tor Norbyec667c1f2014-05-28 17:06:51 -07001453 # each new frame...
Tor Norbye3a2425a2013-11-04 10:16:08 -08001454 return additionalInfo.CreateDbFrame((self, filename, additionalInfo, t, frame)).trace_dispatch(frame, event, arg)
1455
1456 except SystemExit:
1457 return None
1458
Tor Norbye3a2425a2013-11-04 10:16:08 -08001459 except Exception:
Tor Norbyec667c1f2014-05-28 17:06:51 -07001460 # Log it
Tor Norbyec3d3a902014-09-04 13:24:04 -07001461 try:
1462 if traceback is not None:
1463 # This can actually happen during the interpreter shutdown in Python 2.7
1464 traceback.print_exc()
1465 except:
1466 # Error logging? We're really in the interpreter shutdown...
1467 # (https://github.com/fabioz/PyDev.Debugger/issues/8)
1468 pass
Tor Norbye3a2425a2013-11-04 10:16:08 -08001469 return None
1470
1471 if USE_PSYCO_OPTIMIZATION:
1472 try:
1473 import psyco
1474 trace_dispatch = psyco.proxy(trace_dispatch)
1475 processNetCommand = psyco.proxy(processNetCommand)
1476 processInternalCommands = psyco.proxy(processInternalCommands)
1477 doWaitSuspend = psyco.proxy(doWaitSuspend)
1478 getInternalQueue = psyco.proxy(getInternalQueue)
1479 except ImportError:
Tor Norbyec667c1f2014-05-28 17:06:51 -07001480 if hasattr(sys, 'exc_clear'): # jython does not have it
1481 sys.exc_clear() # don't keep the traceback (let's keep it clear for when we go to the point of executing client code)
Tor Norbye3a2425a2013-11-04 10:16:08 -08001482
1483 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"):
1484 sys.stderr.write("pydev debugger: warning: psyco not available for speedups (the debugger will still work correctly, but a bit slower)\n")
1485 sys.stderr.flush()
1486
1487
1488
Tor Norbyec3d3a902014-09-04 13:24:04 -07001489 def SetTraceForFrameAndParents(self, frame, also_add_to_passed_frame=True, overwrite_prev_trace=False, dispatch_func=None):
1490 if dispatch_func is None:
1491 dispatch_func = self.trace_dispatch
Tor Norbye3a2425a2013-11-04 10:16:08 -08001492
1493 if also_add_to_passed_frame:
Tor Norbyec667c1f2014-05-28 17:06:51 -07001494 self.update_trace(frame, dispatch_func, overwrite_prev_trace)
Tor Norbye3a2425a2013-11-04 10:16:08 -08001495
1496 frame = frame.f_back
1497 while frame:
Tor Norbyec667c1f2014-05-28 17:06:51 -07001498 self.update_trace(frame, dispatch_func, overwrite_prev_trace)
Tor Norbye3a2425a2013-11-04 10:16:08 -08001499
1500 frame = frame.f_back
1501 del frame
1502
1503 def update_trace(self, frame, dispatch_func, overwrite_prev):
1504 if frame.f_trace is None:
Tor Norbye1aa2e092014-08-20 17:01:23 -07001505 frame.f_trace = dispatch_func
Tor Norbye3a2425a2013-11-04 10:16:08 -08001506 else:
Tor Norbye1aa2e092014-08-20 17:01:23 -07001507 if overwrite_prev:
1508 frame.f_trace = dispatch_func
1509 else:
1510 try:
1511 #If it's the trace_exception, go back to the frame trace dispatch!
1512 if frame.f_trace.im_func.__name__ == 'trace_exception':
1513 frame.f_trace = frame.f_trace.im_self.trace_dispatch
1514 except AttributeError:
1515 pass
1516 frame = frame.f_back
Tor Norbye3a2425a2013-11-04 10:16:08 -08001517 del frame
1518
Tor Norbyec667c1f2014-05-28 17:06:51 -07001519 def prepareToRun(self):
1520 ''' Shared code to prepare debugging by installing traces and registering threads '''
Tor Norbyec667c1f2014-05-28 17:06:51 -07001521 self.patch_threads()
Tor Norbyec3d3a902014-09-04 13:24:04 -07001522 pydevd_tracing.SetTrace(self.trace_dispatch)
Tor Norbye3a2425a2013-11-04 10:16:08 -08001523
1524
Tor Norbyec667c1f2014-05-28 17:06:51 -07001525 PyDBCommandThread(self).start()
1526 PyDBCheckAliveThread(self).start()
1527
Tor Norbye1aa2e092014-08-20 17:01:23 -07001528
Tor Norbyec667c1f2014-05-28 17:06:51 -07001529 def patch_threads(self):
1530 try:
1531 # not available in jython!
1532 threading.settrace(self.trace_dispatch) # for all future threads
1533 except:
1534 pass
1535
Tor Norbye1aa2e092014-08-20 17:01:23 -07001536 from pydev_monkey import patch_thread_modules
1537 patch_thread_modules()
Tor Norbyec667c1f2014-05-28 17:06:51 -07001538
1539
1540 def run(self, file, globals=None, locals=None, set_trace=True):
1541 if os.path.isdir(file):
1542 new_target = os.path.join(file, '__main__.py')
1543 if os.path.isfile(new_target):
1544 file = new_target
Tor Norbye3a2425a2013-11-04 10:16:08 -08001545
1546 if globals is None:
Tor Norbyee782c572014-09-18 11:43:07 -07001547 m = save_main_module(file, 'pydevd')
Tor Norbye3a2425a2013-11-04 10:16:08 -08001548 globals = m.__dict__
1549 try:
1550 globals['__builtins__'] = __builtins__
1551 except NameError:
Tor Norbyec667c1f2014-05-28 17:06:51 -07001552 pass # Not there on Jython...
Tor Norbye3a2425a2013-11-04 10:16:08 -08001553
1554 if locals is None:
1555 locals = globals
1556
Tor Norbyec667c1f2014-05-28 17:06:51 -07001557 if set_trace:
1558 # Predefined (writable) attributes: __name__ is the module's name;
1559 # __doc__ is the module's documentation string, or None if unavailable;
1560 # __file__ is the pathname of the file from which the module was loaded,
1561 # if it was loaded from a file. The __file__ attribute is not present for
1562 # C modules that are statically linked into the interpreter; for extension modules
1563 # loaded dynamically from a shared library, it is the pathname of the shared library file.
Tor Norbye3a2425a2013-11-04 10:16:08 -08001564
1565
Tor Norbyec667c1f2014-05-28 17:06:51 -07001566 # 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
1567 # debug and run.
1568 if m.__file__.startswith(sys.path[0]):
1569 # print >> sys.stderr, 'Deleting: ', sys.path[0]
1570 del sys.path[0]
Tor Norbye3a2425a2013-11-04 10:16:08 -08001571
Tor Norbyec667c1f2014-05-28 17:06:51 -07001572 # now, the local directory has to be added to the pythonpath
1573 # sys.path.insert(0, os.getcwd())
1574 # Changed: it's not the local directory, but the directory of the file launched
1575 # The file being run ust be in the pythonpath (even if it was not before)
1576 sys.path.insert(0, os.path.split(file)[0])
Tor Norbye3a2425a2013-11-04 10:16:08 -08001577
Tor Norbyec667c1f2014-05-28 17:06:51 -07001578 self.prepareToRun()
Tor Norbye3a2425a2013-11-04 10:16:08 -08001579
Tor Norbyec667c1f2014-05-28 17:06:51 -07001580 while not self.readyToRun:
1581 time.sleep(0.1) # busy wait until we receive run command
Tor Norbye3a2425a2013-11-04 10:16:08 -08001582
Tor Norbye3a2425a2013-11-04 10:16:08 -08001583
Tor Norbyec667c1f2014-05-28 17:06:51 -07001584 pydev_imports.execfile(file, globals, locals) # execute the script
Tor Norbye3a2425a2013-11-04 10:16:08 -08001585
1586 def exiting(self):
1587 sys.stdout.flush()
1588 sys.stderr.flush()
1589 self.checkOutputRedirect()
1590 cmd = self.cmdFactory.makeExitMessage()
1591 self.writer.addCommand(cmd)
1592
Tor Norbyec3d3a902014-09-04 13:24:04 -07001593 def wait_for_commands(self, globals):
1594 thread = threading.currentThread()
1595 import pydevd_frame_utils
1596 frame = pydevd_frame_utils.Frame(None, -1, pydevd_frame_utils.FCode("Console",
1597 os.path.abspath(os.path.dirname(__file__))), globals, globals)
1598 thread_id = GetThreadId(thread)
1599 import pydevd_vars
1600 pydevd_vars.addAdditionalFrameById(thread_id, {id(frame): frame})
1601
1602 cmd = self.cmdFactory.makeShowConsoleMessage(thread_id, frame)
1603 self.writer.addCommand(cmd)
1604
1605 while True:
1606 self.processInternalCommands()
1607 time.sleep(0.01)
1608
Tor Norbye3a2425a2013-11-04 10:16:08 -08001609def set_debug(setup):
1610 setup['DEBUG_RECORD_SOCKET_READS'] = True
1611 setup['DEBUG_TRACE_BREAKPOINTS'] = 1
1612 setup['DEBUG_TRACE_LEVEL'] = 3
1613
1614
1615def processCommandLine(argv):
1616 """ parses the arguments.
1617 removes our arguments from the command line """
1618 setup = {}
1619 setup['client'] = ''
1620 setup['server'] = False
1621 setup['port'] = 0
1622 setup['file'] = ''
Tor Norbye1aa2e092014-08-20 17:01:23 -07001623 setup['multiproc'] = False #Used by PyCharm (reuses connection: ssh tunneling)
1624 setup['multiprocess'] = False # Used by PyDev (creates new connection to ide)
Tor Norbye3a2425a2013-11-04 10:16:08 -08001625 setup['save-signatures'] = False
Tor Norbyec3d3a902014-09-04 13:24:04 -07001626 setup['print-in-debugger-startup'] = False
1627 setup['cmd-line'] = False
Tor Norbye3a2425a2013-11-04 10:16:08 -08001628 i = 0
1629 del argv[0]
1630 while (i < len(argv)):
Tor Norbyec3d3a902014-09-04 13:24:04 -07001631 if argv[i] == '--port':
Tor Norbye3a2425a2013-11-04 10:16:08 -08001632 del argv[i]
1633 setup['port'] = int(argv[i])
1634 del argv[i]
Tor Norbyec3d3a902014-09-04 13:24:04 -07001635 elif argv[i] == '--vm_type':
Tor Norbye3a2425a2013-11-04 10:16:08 -08001636 del argv[i]
1637 setup['vm_type'] = argv[i]
1638 del argv[i]
Tor Norbyec3d3a902014-09-04 13:24:04 -07001639 elif argv[i] == '--client':
Tor Norbye3a2425a2013-11-04 10:16:08 -08001640 del argv[i]
1641 setup['client'] = argv[i]
1642 del argv[i]
Tor Norbyec3d3a902014-09-04 13:24:04 -07001643 elif argv[i] == '--server':
Tor Norbye3a2425a2013-11-04 10:16:08 -08001644 del argv[i]
1645 setup['server'] = True
Tor Norbyec3d3a902014-09-04 13:24:04 -07001646 elif argv[i] == '--file':
Tor Norbye3a2425a2013-11-04 10:16:08 -08001647 del argv[i]
1648 setup['file'] = argv[i]
1649 i = len(argv) # pop out, file is our last argument
Tor Norbyec3d3a902014-09-04 13:24:04 -07001650 elif argv[i] == '--DEBUG_RECORD_SOCKET_READS':
Tor Norbye3a2425a2013-11-04 10:16:08 -08001651 del argv[i]
1652 setup['DEBUG_RECORD_SOCKET_READS'] = True
Tor Norbyec3d3a902014-09-04 13:24:04 -07001653 elif argv[i] == '--DEBUG':
Tor Norbye3a2425a2013-11-04 10:16:08 -08001654 del argv[i]
1655 set_debug(setup)
Tor Norbyec3d3a902014-09-04 13:24:04 -07001656 elif argv[i] == '--multiproc':
Tor Norbye3a2425a2013-11-04 10:16:08 -08001657 del argv[i]
1658 setup['multiproc'] = True
Tor Norbyec3d3a902014-09-04 13:24:04 -07001659 elif argv[i] == '--multiprocess':
Tor Norbye1aa2e092014-08-20 17:01:23 -07001660 del argv[i]
1661 setup['multiprocess'] = True
Tor Norbyec3d3a902014-09-04 13:24:04 -07001662 elif argv[i] == '--save-signatures':
Tor Norbye3a2425a2013-11-04 10:16:08 -08001663 del argv[i]
1664 setup['save-signatures'] = True
Tor Norbyec3d3a902014-09-04 13:24:04 -07001665 elif argv[i] == '--print-in-debugger-startup':
1666 del argv[i]
1667 setup['print-in-debugger-startup'] = True
1668 elif (argv[i] == '--cmd-line'):
1669 del argv[i]
1670 setup['cmd-line'] = True
Tor Norbye3a2425a2013-11-04 10:16:08 -08001671 else:
1672 raise ValueError("unexpected option " + argv[i])
1673 return setup
1674
1675def usage(doExit=0):
1676 sys.stdout.write('Usage:\n')
1677 sys.stdout.write('pydevd.py --port=N [(--client hostname) | --server] --file executable [file_options]\n')
1678 if doExit:
1679 sys.exit(0)
1680
Tor Norbye3a2425a2013-11-04 10:16:08 -08001681
1682def initStdoutRedirect():
1683 if not getattr(sys, 'stdoutBuf', None):
1684 sys.stdoutBuf = pydevd_io.IOBuf()
1685 sys.stdout = pydevd_io.IORedirector(sys.stdout, sys.stdoutBuf) #@UndefinedVariable
1686
1687def initStderrRedirect():
1688 if not getattr(sys, 'stderrBuf', None):
1689 sys.stderrBuf = pydevd_io.IOBuf()
1690 sys.stderr = pydevd_io.IORedirector(sys.stderr, sys.stderrBuf) #@UndefinedVariable
1691
Tor Norbyec667c1f2014-05-28 17:06:51 -07001692#=======================================================================================================================
1693# settrace
1694#=======================================================================================================================
1695def settrace(
1696 host=None,
1697 stdoutToServer=False,
1698 stderrToServer=False,
1699 port=5678,
1700 suspend=True,
1701 trace_only_current_thread=False,
1702 overwrite_prev_trace=False,
1703 patch_multiprocessing=False,
1704 ):
Tor Norbye3a2425a2013-11-04 10:16:08 -08001705 '''Sets the tracing function with the pydev debug function and initializes needed facilities.
1706
Tor Norbyec667c1f2014-05-28 17:06:51 -07001707 @param host: the user may specify another host, if the debug server is not in the same machine (default is the local
1708 host)
1709
Tor Norbye3a2425a2013-11-04 10:16:08 -08001710 @param stdoutToServer: when this is true, the stdout is passed to the debug server
Tor Norbyec667c1f2014-05-28 17:06:51 -07001711
Tor Norbye3a2425a2013-11-04 10:16:08 -08001712 @param stderrToServer: when this is true, the stderr is passed to the debug server
1713 so that they are printed in its console and not in this process console.
Tor Norbyec667c1f2014-05-28 17:06:51 -07001714
Tor Norbye3a2425a2013-11-04 10:16:08 -08001715 @param port: specifies which port to use for communicating with the server (note that the server must be started
1716 in the same port). @note: currently it's hard-coded at 5678 in the client
Tor Norbyec667c1f2014-05-28 17:06:51 -07001717
Tor Norbye3a2425a2013-11-04 10:16:08 -08001718 @param suspend: whether a breakpoint should be emulated as soon as this function is called.
Tor Norbyec667c1f2014-05-28 17:06:51 -07001719
1720 @param trace_only_current_thread: determines if only the current thread will be traced or all current and future
1721 threads will also have the tracing enabled.
1722
1723 @param overwrite_prev_trace: if True we'll reset the frame.f_trace of frames which are already being traced
1724
1725 @param patch_multiprocessing: if True we'll patch the functions which create new processes so that launched
1726 processes are debugged.
Tor Norbye3a2425a2013-11-04 10:16:08 -08001727 '''
1728 _set_trace_lock.acquire()
1729 try:
Tor Norbyec667c1f2014-05-28 17:06:51 -07001730 _locked_settrace(
1731 host,
1732 stdoutToServer,
1733 stderrToServer,
1734 port,
1735 suspend,
1736 trace_only_current_thread,
1737 overwrite_prev_trace,
1738 patch_multiprocessing,
1739 )
Tor Norbye3a2425a2013-11-04 10:16:08 -08001740 finally:
1741 _set_trace_lock.release()
1742
Tor Norbyec667c1f2014-05-28 17:06:51 -07001743
1744
Tor Norbyec3d3a902014-09-04 13:24:04 -07001745_set_trace_lock = _pydev_thread.allocate_lock()
Tor Norbye3a2425a2013-11-04 10:16:08 -08001746
Tor Norbyec667c1f2014-05-28 17:06:51 -07001747def _locked_settrace(
1748 host,
1749 stdoutToServer,
1750 stderrToServer,
1751 port,
1752 suspend,
1753 trace_only_current_thread,
1754 overwrite_prev_trace,
1755 patch_multiprocessing,
1756 ):
1757 if patch_multiprocessing:
1758 try:
1759 import pydev_monkey #Jython 2.1 can't use it...
1760 except:
1761 pass
1762 else:
1763 pydev_monkey.patch_new_process_functions()
1764
Tor Norbye3a2425a2013-11-04 10:16:08 -08001765 if host is None:
1766 import pydev_localhost
1767 host = pydev_localhost.get_localhost()
1768
1769 global connected
1770 global bufferStdOutToServer
1771 global bufferStdErrToServer
Tor Norbye3a2425a2013-11-04 10:16:08 -08001772
1773 if not connected :
Tor Norbye3a2425a2013-11-04 10:16:08 -08001774 pydevd_vm_type.SetupType()
1775
1776 debugger = PyDB()
Tor Norbyec667c1f2014-05-28 17:06:51 -07001777 debugger.connect(host, port) # Note: connect can raise error.
1778
1779 # Mark connected only if it actually succeeded.
1780 connected = True
1781 bufferStdOutToServer = stdoutToServer
1782 bufferStdErrToServer = stderrToServer
Tor Norbye3a2425a2013-11-04 10:16:08 -08001783
Tor Norbye3a2425a2013-11-04 10:16:08 -08001784 if bufferStdOutToServer:
1785 initStdoutRedirect()
1786
1787 if bufferStdErrToServer:
1788 initStderrRedirect()
1789
Tor Norbyec667c1f2014-05-28 17:06:51 -07001790 debugger.SetTraceForFrameAndParents(GetFrame(), False, overwrite_prev_trace=overwrite_prev_trace)
1791
1792
1793 CustomFramesContainer.custom_frames_lock.acquire()
1794 try:
Tor Norbye1aa2e092014-08-20 17:01:23 -07001795 for _frameId, custom_frame in DictIterItems(CustomFramesContainer.custom_frames):
Tor Norbyec667c1f2014-05-28 17:06:51 -07001796 debugger.SetTraceForFrameAndParents(custom_frame.frame, False)
1797 finally:
1798 CustomFramesContainer.custom_frames_lock.release()
1799
Tor Norbye3a2425a2013-11-04 10:16:08 -08001800
1801 t = threadingCurrentThread()
1802 try:
1803 additionalInfo = t.additionalInfo
1804 except AttributeError:
1805 additionalInfo = PyDBAdditionalThreadInfo()
1806 t.additionalInfo = additionalInfo
1807
1808 while not debugger.readyToRun:
Tor Norbyec667c1f2014-05-28 17:06:51 -07001809 time.sleep(0.1) # busy wait until we receive run command
Tor Norbye3a2425a2013-11-04 10:16:08 -08001810
Tor Norbyec667c1f2014-05-28 17:06:51 -07001811 # note that we do that through pydevd_tracing.SetTrace so that the tracing
1812 # is not warned to the user!
Tor Norbye3a2425a2013-11-04 10:16:08 -08001813 pydevd_tracing.SetTrace(debugger.trace_dispatch)
1814
1815 if not trace_only_current_thread:
Tor Norbyec667c1f2014-05-28 17:06:51 -07001816 # Trace future threads?
1817 debugger.patch_threads()
Tor Norbye3a2425a2013-11-04 10:16:08 -08001818
Tor Norbyec667c1f2014-05-28 17:06:51 -07001819 # As this is the first connection, also set tracing for any untraced threads
1820 debugger.setTracingForUntracedContexts(ignore_frame=GetFrame(), overwrite_prev_trace=overwrite_prev_trace)
Tor Norbye3a2425a2013-11-04 10:16:08 -08001821
Tor Norbyec3d3a902014-09-04 13:24:04 -07001822 # Stop the tracing as the last thing before the actual shutdown for a clean exit.
1823 atexit.register(stoptrace)
1824
Tor Norbyec667c1f2014-05-28 17:06:51 -07001825 #Suspend as the last thing after all tracing is in place.
1826 if suspend:
1827 debugger.setSuspend(t, CMD_SET_BREAK)
Tor Norbye3a2425a2013-11-04 10:16:08 -08001828
1829 PyDBCommandThread(debugger).start()
1830 PyDBCheckAliveThread(debugger).start()
1831
1832 else:
Tor Norbyec667c1f2014-05-28 17:06:51 -07001833 # ok, we're already in debug mode, with all set, so, let's just set the break
Tor Norbye3a2425a2013-11-04 10:16:08 -08001834 debugger = GetGlobalDebugger()
1835
1836 debugger.SetTraceForFrameAndParents(GetFrame(), False)
1837
1838 t = threadingCurrentThread()
1839 try:
1840 additionalInfo = t.additionalInfo
1841 except AttributeError:
1842 additionalInfo = PyDBAdditionalThreadInfo()
1843 t.additionalInfo = additionalInfo
1844
1845 pydevd_tracing.SetTrace(debugger.trace_dispatch)
1846
1847 if not trace_only_current_thread:
Tor Norbyec667c1f2014-05-28 17:06:51 -07001848 # Trace future threads?
1849 debugger.patch_threads()
Tor Norbye3a2425a2013-11-04 10:16:08 -08001850
Tor Norbye3a2425a2013-11-04 10:16:08 -08001851
1852 if suspend:
1853 debugger.setSuspend(t, CMD_SET_BREAK)
1854
Tor Norbyec667c1f2014-05-28 17:06:51 -07001855
Tor Norbye3a2425a2013-11-04 10:16:08 -08001856def stoptrace():
1857 global connected
1858 if connected:
1859 pydevd_tracing.RestoreSysSetTraceFunc()
1860 sys.settrace(None)
1861 try:
1862 #not available in jython!
1863 threading.settrace(None) # for all future threads
1864 except:
1865 pass
Tor Norbye1aa2e092014-08-20 17:01:23 -07001866
1867 from pydev_monkey import undo_patch_thread_modules
1868 undo_patch_thread_modules()
Tor Norbyec3d3a902014-09-04 13:24:04 -07001869
Tor Norbye3a2425a2013-11-04 10:16:08 -08001870 debugger = GetGlobalDebugger()
Tor Norbyec3d3a902014-09-04 13:24:04 -07001871
Tor Norbye3a2425a2013-11-04 10:16:08 -08001872 if debugger:
Tor Norbyec3d3a902014-09-04 13:24:04 -07001873
1874 debugger.SetTraceForFrameAndParents(
1875 GetFrame(), also_add_to_passed_frame=True, overwrite_prev_trace=True, dispatch_func=lambda *args:None)
Tor Norbye3a2425a2013-11-04 10:16:08 -08001876 debugger.exiting()
Tor Norbyec3d3a902014-09-04 13:24:04 -07001877
Tor Norbye1aa2e092014-08-20 17:01:23 -07001878 killAllPydevThreads()
1879
Tor Norbye3a2425a2013-11-04 10:16:08 -08001880 connected = False
1881
1882class Dispatcher(object):
1883 def __init__(self):
1884 self.port = None
1885
1886 def connect(self, host, port):
1887 self.host = host
1888 self.port = port
1889 self.client = StartClient(self.host, self.port)
1890 self.reader = DispatchReader(self)
1891 self.reader.dontTraceMe = False #we run reader in the same thread so we don't want to loose tracing
1892 self.reader.run()
1893
1894 def close(self):
1895 try:
1896 self.reader.doKillPydevThread()
1897 except :
1898 pass
1899
1900class DispatchReader(ReaderThread):
1901 def __init__(self, dispatcher):
1902 self.dispatcher = dispatcher
1903 ReaderThread.__init__(self, self.dispatcher.client)
1904
Tor Norbyec3d3a902014-09-04 13:24:04 -07001905 def OnRun(self):
1906 dummy_thread = threading.currentThread()
1907 dummy_thread.is_pydev_daemon_thread = False
1908 return ReaderThread.OnRun(self)
1909
Tor Norbye3a2425a2013-11-04 10:16:08 -08001910 def handleExcept(self):
1911 ReaderThread.handleExcept(self)
1912
1913 def processCommand(self, cmd_id, seq, text):
1914 if cmd_id == 99:
1915 self.dispatcher.port = int(text)
1916 self.killReceived = True
1917
1918
Tor Norbye1aa2e092014-08-20 17:01:23 -07001919DISPATCH_APPROACH_NEW_CONNECTION = 1 # Used by PyDev
1920DISPATCH_APPROACH_EXISTING_CONNECTION = 2 # Used by PyCharm
1921DISPATCH_APPROACH = DISPATCH_APPROACH_NEW_CONNECTION
1922
Tor Norbye3a2425a2013-11-04 10:16:08 -08001923def dispatch():
Tor Norbye1aa2e092014-08-20 17:01:23 -07001924 setup = SetupHolder.setup
Tor Norbye3a2425a2013-11-04 10:16:08 -08001925 host = setup['client']
1926 port = setup['port']
Tor Norbye1aa2e092014-08-20 17:01:23 -07001927 if DISPATCH_APPROACH == DISPATCH_APPROACH_EXISTING_CONNECTION:
1928 dispatcher = Dispatcher()
1929 try:
1930 dispatcher.connect(host, port)
1931 port = dispatcher.port
1932 finally:
1933 dispatcher.close()
Tor Norbye3a2425a2013-11-04 10:16:08 -08001934 return host, port
1935
1936
1937def settrace_forked():
Tor Norbye1aa2e092014-08-20 17:01:23 -07001938 '''
1939 When creating a fork from a process in the debugger, we need to reset the whole debugger environment!
1940 '''
Tor Norbye3a2425a2013-11-04 10:16:08 -08001941 host, port = dispatch()
1942
1943 import pydevd_tracing
1944 pydevd_tracing.RestoreSysSetTraceFunc()
1945
1946 if port is not None:
1947 global connected
1948 connected = False
Tor Norbyec667c1f2014-05-28 17:06:51 -07001949
1950 CustomFramesContainerInit()
1951
1952 settrace(
1953 host,
1954 port=port,
1955 suspend=False,
1956 trace_only_current_thread=False,
1957 overwrite_prev_trace=True,
1958 patch_multiprocessing=True,
1959 )
Tor Norbye1aa2e092014-08-20 17:01:23 -07001960
1961#=======================================================================================================================
1962# SetupHolder
1963#=======================================================================================================================
1964class SetupHolder:
1965
1966 setup = None
1967
1968
Tor Norbye3a2425a2013-11-04 10:16:08 -08001969#=======================================================================================================================
1970# main
1971#=======================================================================================================================
1972if __name__ == '__main__':
Tor Norbyec3d3a902014-09-04 13:24:04 -07001973
Tor Norbye3a2425a2013-11-04 10:16:08 -08001974 # parse the command line. --file is our last argument that is required
1975 try:
1976 sys.original_argv = sys.argv[:]
1977 setup = processCommandLine(sys.argv)
Tor Norbye1aa2e092014-08-20 17:01:23 -07001978 SetupHolder.setup = setup
Tor Norbye3a2425a2013-11-04 10:16:08 -08001979 except ValueError:
1980 traceback.print_exc()
1981 usage(1)
1982
Tor Norbyec3d3a902014-09-04 13:24:04 -07001983 if setup['print-in-debugger-startup']:
1984 try:
1985 pid = ' (pid: %s)' % os.getpid()
1986 except:
1987 pid = ''
1988 sys.stderr.write("pydev debugger: starting%s\n" % pid)
Tor Norbye3a2425a2013-11-04 10:16:08 -08001989
Tor Norbye3a2425a2013-11-04 10:16:08 -08001990 fix_getpass.fixGetpass()
1991
Tor Norbye3a2425a2013-11-04 10:16:08 -08001992 pydev_log.debug("Executing file %s" % setup['file'])
1993 pydev_log.debug("arguments: %s"% str(sys.argv))
1994
1995
1996 pydevd_vm_type.SetupType(setup.get('vm_type', None))
1997
1998 if os.getenv('PYCHARM_DEBUG'):
1999 set_debug(setup)
2000
2001 DebugInfoHolder.DEBUG_RECORD_SOCKET_READS = setup.get('DEBUG_RECORD_SOCKET_READS', False)
2002 DebugInfoHolder.DEBUG_TRACE_BREAKPOINTS = setup.get('DEBUG_TRACE_BREAKPOINTS', -1)
2003 DebugInfoHolder.DEBUG_TRACE_LEVEL = setup.get('DEBUG_TRACE_LEVEL', -1)
2004
2005 port = setup['port']
2006 host = setup['client']
Tor Norbyec667c1f2014-05-28 17:06:51 -07002007 f = setup['file']
2008 fix_app_engine_debug = False
Tor Norbye3a2425a2013-11-04 10:16:08 -08002009
Tor Norbye3a2425a2013-11-04 10:16:08 -08002010
Tor Norbye1aa2e092014-08-20 17:01:23 -07002011 try:
2012 import pydev_monkey
2013 except:
2014 pass #Not usable on jython 2.1
Tor Norbye3a2425a2013-11-04 10:16:08 -08002015 else:
Tor Norbye1aa2e092014-08-20 17:01:23 -07002016 if setup['multiprocess']: # PyDev
2017 pydev_monkey.patch_new_process_functions()
Tor Norbye3a2425a2013-11-04 10:16:08 -08002018
Tor Norbye1aa2e092014-08-20 17:01:23 -07002019 elif setup['multiproc']: # PyCharm
2020 pydev_log.debug("Started in multiproc mode\n")
2021 # Note: we're not inside method, so, no need for 'global'
2022 DISPATCH_APPROACH = DISPATCH_APPROACH_EXISTING_CONNECTION
Tor Norbye3a2425a2013-11-04 10:16:08 -08002023
Tor Norbye1aa2e092014-08-20 17:01:23 -07002024 dispatcher = Dispatcher()
2025 try:
2026 dispatcher.connect(host, port)
2027 if dispatcher.port is not None:
2028 port = dispatcher.port
2029 pydev_log.debug("Received port %d\n" %port)
2030 pydev_log.info("pydev debugger: process %d is connecting\n"% os.getpid())
2031
Tor Norbyec667c1f2014-05-28 17:06:51 -07002032 try:
Tor Norbye1aa2e092014-08-20 17:01:23 -07002033 pydev_monkey.patch_new_process_functions()
Tor Norbyec667c1f2014-05-28 17:06:51 -07002034 except:
Tor Norbye1aa2e092014-08-20 17:01:23 -07002035 pydev_log.error("Error patching process functions\n")
Tor Norbyec667c1f2014-05-28 17:06:51 -07002036 traceback.print_exc()
Tor Norbye1aa2e092014-08-20 17:01:23 -07002037 else:
2038 pydev_log.error("pydev debugger: couldn't get port for new debug process\n")
2039 finally:
2040 dispatcher.close()
2041 else:
2042 pydev_log.info("pydev debugger: starting\n")
2043
2044 try:
2045 pydev_monkey.patch_new_process_functions_with_warning()
2046 except:
2047 pydev_log.error("Error patching process functions\n")
2048 traceback.print_exc()
2049
2050 # Only do this patching if we're not running with multiprocess turned on.
2051 if f.find('dev_appserver.py') != -1:
2052 if os.path.basename(f).startswith('dev_appserver.py'):
2053 appserver_dir = os.path.dirname(f)
2054 version_file = os.path.join(appserver_dir, 'VERSION')
2055 if os.path.exists(version_file):
2056 try:
2057 stream = open(version_file, 'r')
2058 try:
2059 for line in stream.read().splitlines():
2060 line = line.strip()
2061 if line.startswith('release:'):
2062 line = line[8:].strip()
2063 version = line.replace('"', '')
2064 version = version.split('.')
2065 if int(version[0]) > 1:
2066 fix_app_engine_debug = True
2067
2068 elif int(version[0]) == 1:
2069 if int(version[1]) >= 7:
2070 # Only fix from 1.7 onwards
2071 fix_app_engine_debug = True
2072 break
2073 finally:
2074 stream.close()
2075 except:
2076 traceback.print_exc()
Tor Norbyec667c1f2014-05-28 17:06:51 -07002077
2078 try:
2079 # In the default run (i.e.: run directly on debug mode), we try to patch stackless as soon as possible
2080 # on a run where we have a remote debug, we may have to be more careful because patching stackless means
2081 # that if the user already had a stackless.set_schedule_callback installed, he'd loose it and would need
2082 # to call it again (because stackless provides no way of getting the last function which was registered
2083 # in set_schedule_callback).
2084 #
2085 # So, ideally, if there's an application using stackless and the application wants to use the remote debugger
2086 # and benefit from stackless debugging, the application itself must call:
2087 #
2088 # import pydevd_stackless
2089 # pydevd_stackless.patch_stackless()
2090 #
2091 # itself to be able to benefit from seeing the tasklets created before the remote debugger is attached.
2092 import pydevd_stackless
2093 pydevd_stackless.patch_stackless()
2094 except:
2095 pass # It's ok not having stackless there...
2096
Tor Norbyec3d3a902014-09-04 13:24:04 -07002097 debugger = PyDB()
2098
Tor Norbyec667c1f2014-05-28 17:06:51 -07002099 if fix_app_engine_debug:
2100 sys.stderr.write("pydev debugger: google app engine integration enabled\n")
2101 curr_dir = os.path.dirname(__file__)
2102 app_engine_startup_file = os.path.join(curr_dir, 'pydev_app_engine_debug_startup.py')
2103
2104 sys.argv.insert(1, '--python_startup_script=' + app_engine_startup_file)
2105 import json
2106 setup['pydevd'] = __file__
2107 sys.argv.insert(2, '--python_startup_args=%s' % json.dumps(setup),)
2108 sys.argv.insert(3, '--automatic_restart=no')
2109 sys.argv.insert(4, '--max_module_instances=1')
2110
Tor Norbyec667c1f2014-05-28 17:06:51 -07002111 # Run the dev_appserver
2112 debugger.run(setup['file'], None, None, set_trace=False)
Tor Norbyec667c1f2014-05-28 17:06:51 -07002113 else:
2114 # as to get here all our imports are already resolved, the psyco module can be
2115 # changed and we'll still get the speedups in the debugger, as those functions
2116 # are already compiled at this time.
2117 try:
2118 import psyco
2119 except ImportError:
2120 if hasattr(sys, 'exc_clear'): # jython does not have it
2121 sys.exc_clear() # don't keep the traceback -- clients don't want to see it
2122 pass # that's ok, no need to mock psyco if it's not available anyways
2123 else:
2124 # if it's available, let's change it for a stub (pydev already made use of it)
2125 import pydevd_psyco_stub
2126 sys.modules['psyco'] = pydevd_psyco_stub
Tor Norbye3a2425a2013-11-04 10:16:08 -08002127
Tor Norbye1aa2e092014-08-20 17:01:23 -07002128 if setup['save-signatures']:
2129 if pydevd_vm_type.GetVmType() == pydevd_vm_type.PydevdVmType.JYTHON:
2130 sys.stderr.write("Collecting run-time type information is not supported for Jython\n")
2131 else:
Tor Norbyec3d3a902014-09-04 13:24:04 -07002132 # Only import it if we're going to use it!
2133 from pydevd_signature import SignatureFactory
Tor Norbye1aa2e092014-08-20 17:01:23 -07002134 debugger.signature_factory = SignatureFactory()
Tor Norbye3a2425a2013-11-04 10:16:08 -08002135
Tor Norbye1aa2e092014-08-20 17:01:23 -07002136 try:
2137 debugger.connect(host, port)
2138 except:
2139 sys.stderr.write("Could not connect to %s: %s\n" % (host, port))
2140 traceback.print_exc()
2141 sys.exit(1)
Tor Norbye3a2425a2013-11-04 10:16:08 -08002142
Tor Norbye1aa2e092014-08-20 17:01:23 -07002143 connected = True # Mark that we're connected when started from inside ide.
Tor Norbye3a2425a2013-11-04 10:16:08 -08002144
Tor Norbyec3d3a902014-09-04 13:24:04 -07002145 globals = debugger.run(setup['file'], None, None)
2146
2147 if setup['cmd-line']:
2148 debugger.wait_for_commands(globals)
2149
2150