blob: 4a509d053619a2ddae1b856cb7bb8f868d37db01 [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 Norbyec667c1f2014-05-28 17:06:51 -07002import traceback
3
Tor Norbye3a2425a2013-11-04 10:16:08 -08004from django_debug import DjangoLineBreakpoint
5from pydevd_signature import SignatureFactory
6from pydevd_frame import add_exception_to_frame
Tor Norbye3a2425a2013-11-04 10:16:08 -08007import pydev_imports
8from pydevd_breakpoints import * #@UnusedWildImport
9import fix_getpass
Tor Norbye3a2425a2013-11-04 10:16:08 -080010from pydevd_comm import CMD_CHANGE_VARIABLE, \
11 CMD_EVALUATE_EXPRESSION, \
12 CMD_EXEC_EXPRESSION, \
13 CMD_GET_COMPLETIONS, \
14 CMD_GET_FRAME, \
15 CMD_GET_VARIABLE, \
16 CMD_LIST_THREADS, \
17 CMD_REMOVE_BREAK, \
18 CMD_RUN, \
19 CMD_SET_BREAK, \
20 CMD_SET_NEXT_STATEMENT,\
21 CMD_STEP_INTO, \
22 CMD_STEP_OVER, \
23 CMD_STEP_RETURN, \
24 CMD_THREAD_CREATE, \
25 CMD_THREAD_KILL, \
26 CMD_THREAD_RUN, \
27 CMD_THREAD_SUSPEND, \
28 CMD_RUN_TO_LINE, \
29 CMD_RELOAD_CODE, \
30 CMD_VERSION, \
31 CMD_CONSOLE_EXEC, \
32 CMD_ADD_EXCEPTION_BREAK, \
33 CMD_REMOVE_EXCEPTION_BREAK, \
34 CMD_LOAD_SOURCE, \
35 CMD_ADD_DJANGO_EXCEPTION_BREAK, \
36 CMD_REMOVE_DJANGO_EXCEPTION_BREAK, \
37 CMD_SMART_STEP_INTO,\
38 InternalChangeVariable, \
39 InternalGetCompletions, \
40 InternalEvaluateExpression, \
41 InternalConsoleExec, \
42 InternalGetFrame, \
43 InternalGetVariable, \
44 InternalTerminateThread, \
45 InternalRunThread, \
46 InternalStepThread, \
47 NetCommand, \
48 NetCommandFactory, \
49 PyDBDaemonThread, \
50 _queue, \
51 ReaderThread, \
52 SetGlobalDebugger, \
53 WriterThread, \
54 PydevdFindThreadById, \
55 PydevdLog, \
56 StartClient, \
57 StartServer, \
Tor Norbyec667c1f2014-05-28 17:06:51 -070058 InternalSetNextStatementThread, ReloadCodeCommand
Tor Norbye3a2425a2013-11-04 10:16:08 -080059from pydevd_file_utils import NormFileToServer, GetFilenameAndBase
60import pydevd_file_utils
61import pydevd_vars
Tor Norbye3a2425a2013-11-04 10:16:08 -080062import pydevd_vm_type
63import pydevd_tracing
64import pydevd_io
65import pydev_monkey
66from pydevd_additional_thread_info import PyDBAdditionalThreadInfo
Tor Norbyec667c1f2014-05-28 17:06:51 -070067from pydevd_custom_frames import CustomFramesContainer, CustomFramesContainerInit
68
Tor Norbye3a2425a2013-11-04 10:16:08 -080069
70if USE_LIB_COPY:
71 import _pydev_time as time
72 import _pydev_threading as threading
73else:
74 import time
75 import threading
76
77import os
78
79
80threadingEnumerate = threading.enumerate
81threadingCurrentThread = threading.currentThread
82
83
84DONT_TRACE = {
Tor Norbyec667c1f2014-05-28 17:06:51 -070085 # commonly used things from the stdlib that we don't want to trace
Tor Norbye3a2425a2013-11-04 10:16:08 -080086 'threading.py':1,
87 'Queue.py':1,
88 'queue.py':1,
89 'socket.py':1,
Tor Norbyec667c1f2014-05-28 17:06:51 -070090 'weakref.py':1,
91 'linecache.py':1,
92 'threading.py':1,
Tor Norbye3a2425a2013-11-04 10:16:08 -080093
94 #things from pydev that we don't want to trace
Tor Norbyec667c1f2014-05-28 17:06:51 -070095 'pydevd.py':1 ,
Tor Norbye3a2425a2013-11-04 10:16:08 -080096 'pydevd_additional_thread_info.py':1,
Tor Norbyec667c1f2014-05-28 17:06:51 -070097 'pydevd_custom_frames.py':1,
Tor Norbye3a2425a2013-11-04 10:16:08 -080098 'pydevd_comm.py':1,
Tor Norbyec667c1f2014-05-28 17:06:51 -070099 'pydevd_console.py':1 ,
Tor Norbye3a2425a2013-11-04 10:16:08 -0800100 'pydevd_constants.py':1,
101 'pydevd_exec.py':1,
102 'pydevd_exec2.py':1,
103 'pydevd_file_utils.py':1,
104 'pydevd_frame.py':1,
Tor Norbyec667c1f2014-05-28 17:06:51 -0700105 'pydevd_import_class.py':1 ,
Tor Norbye3a2425a2013-11-04 10:16:08 -0800106 'pydevd_io.py':1 ,
Tor Norbyec667c1f2014-05-28 17:06:51 -0700107 'pydevd_psyco_stub.py':1,
108 'pydevd_reload.py':1 ,
Tor Norbye3a2425a2013-11-04 10:16:08 -0800109 'pydevd_resolver.py':1 ,
Tor Norbyec667c1f2014-05-28 17:06:51 -0700110 'pydevd_stackless.py':1 ,
111 'pydevd_traceproperty.py':1,
Tor Norbye3a2425a2013-11-04 10:16:08 -0800112 'pydevd_tracing.py':1 ,
113 'pydevd_signature.py':1,
114 'pydevd_utils.py':1,
115 'pydevd_vars.py':1,
116 'pydevd_vm_type.py':1,
Tor Norbye3a2425a2013-11-04 10:16:08 -0800117 '_pydev_execfile.py':1,
118 '_pydev_jython_execfile.py':1
Tor Norbyec667c1f2014-05-28 17:06:51 -0700119 }
Tor Norbye3a2425a2013-11-04 10:16:08 -0800120
121if IS_PY3K:
Tor Norbyec667c1f2014-05-28 17:06:51 -0700122 # 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 -0800123 DONT_TRACE['io.py'] = 1
124
Tor Norbyec667c1f2014-05-28 17:06:51 -0700125 # Don't trace common encodings too
126 DONT_TRACE['cp1252.py'] = 1
127 DONT_TRACE['utf_8.py'] = 1
128
Tor Norbye3a2425a2013-11-04 10:16:08 -0800129
130connected = False
131bufferStdOutToServer = False
132bufferStdErrToServer = False
133remote = False
134
Tor Norbyec667c1f2014-05-28 17:06:51 -0700135from _pydev_filesystem_encoding import getfilesystemencoding
136file_system_encoding = getfilesystemencoding()
Tor Norbye3a2425a2013-11-04 10:16:08 -0800137
Tor Norbye92584642014-04-17 08:39:25 -0700138def isThreadAlive(t):
139 try:
Tor Norbyec667c1f2014-05-28 17:06:51 -0700140 # If thread is not started yet we treat it as alive.
141 # It is required to debug threads started by start_new_thread in Python 3.4
142 if hasattr(t, '_is_stopped'):
143 alive = not t._is_stopped
144 else:
145 alive = not t.__stopped
Tor Norbye92584642014-04-17 08:39:25 -0700146 except:
Tor Norbyec667c1f2014-05-28 17:06:51 -0700147 alive = t.isAlive()
Tor Norbye92584642014-04-17 08:39:25 -0700148 return alive
Tor Norbye3a2425a2013-11-04 10:16:08 -0800149
150#=======================================================================================================================
151# PyDBCommandThread
152#=======================================================================================================================
153class PyDBCommandThread(PyDBDaemonThread):
154
155 def __init__(self, pyDb):
156 PyDBDaemonThread.__init__(self)
Tor Norbyec667c1f2014-05-28 17:06:51 -0700157 self._py_db_command_thread_event = pyDb._py_db_command_thread_event
Tor Norbye3a2425a2013-11-04 10:16:08 -0800158 self.pyDb = pyDb
159 self.setName('pydevd.CommandThread')
160
161 def OnRun(self):
162 for i in range(1, 10):
163 time.sleep(0.5) #this one will only start later on (because otherwise we may not have any non-daemon threads
164 if self.killReceived:
165 return
166
167 if self.dontTraceMe:
168 self.pyDb.SetTrace(None) # no debugging on this thread
169
170 try:
171 while not self.killReceived:
172 try:
173 self.pyDb.processInternalCommands()
174 except:
175 PydevdLog(0, 'Finishing debug communication...(2)')
Tor Norbyec667c1f2014-05-28 17:06:51 -0700176 self._py_db_command_thread_event.clear()
177 self._py_db_command_thread_event.wait(0.5)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800178 except:
179 pydev_log.debug(sys.exc_info()[0])
180
181 #only got this error in interpreter shutdown
182 #PydevdLog(0, 'Finishing debug communication...(3)')
183
184
185def killAllPydevThreads():
186 threads = threadingEnumerate()
187 for t in threads:
188 if hasattr(t, 'doKillPydevThread'):
189 t.doKillPydevThread()
190
191
192#=======================================================================================================================
193# PyDBCheckAliveThread
194#=======================================================================================================================
195class PyDBCheckAliveThread(PyDBDaemonThread):
196
197 def __init__(self, pyDb):
198 PyDBDaemonThread.__init__(self)
199 self.pyDb = pyDb
200 self.setDaemon(False)
201 self.setName('pydevd.CheckAliveThread')
202
203 def OnRun(self):
204 if self.dontTraceMe:
205 self.pyDb.SetTrace(None) # no debugging on this thread
206 while not self.killReceived:
207 if not self.pyDb.haveAliveThreads():
208 try:
209 pydev_log.debug("No alive threads, finishing debug session")
210 self.pyDb.FinishDebuggingSession()
211 killAllPydevThreads()
212 except:
213 traceback.print_exc()
214
Tor Norbye3a2425a2013-11-04 10:16:08 -0800215 self.killReceived = True
216 return
217
218 time.sleep(0.3)
219
220 def doKillPydevThread(self):
221 pass
222
223if USE_LIB_COPY:
224 import _pydev_thread as thread
225else:
226 try:
227 import thread
228 except ImportError:
229 import _thread as thread #Py3K changed it.
230
231_original_start_new_thread = thread.start_new_thread
232
233if getattr(thread, '_original_start_new_thread', None) is None:
234 thread._original_start_new_thread = thread.start_new_thread
235
236#=======================================================================================================================
237# NewThreadStartup
238#=======================================================================================================================
239class NewThreadStartup:
240
241 def __init__(self, original_func, args, kwargs):
242 self.original_func = original_func
243 self.args = args
244 self.kwargs = kwargs
245
246 def __call__(self):
247 global_debugger = GetGlobalDebugger()
248 global_debugger.SetTrace(global_debugger.trace_dispatch)
249 self.original_func(*self.args, **self.kwargs)
250
251thread.NewThreadStartup = NewThreadStartup
252
253#=======================================================================================================================
254# pydev_start_new_thread
255#=======================================================================================================================
256def _pydev_start_new_thread(function, args, kwargs={}):
257 '''
258 We need to replace the original thread.start_new_thread with this function so that threads started through
259 it and not through the threading module are properly traced.
260 '''
261 if USE_LIB_COPY:
262 import _pydev_thread as thread
263 else:
264 try:
265 import thread
266 except ImportError:
267 import _thread as thread #Py3K changed it.
268
269 return thread._original_start_new_thread(thread.NewThreadStartup(function, args, kwargs), ())
270
271class PydevStartNewThread(object):
272 def __get__(self, obj, type=None):
273 return self
274
275 def __call__(self, function, args, kwargs={}):
276 return _pydev_start_new_thread(function, args, kwargs)
277
278pydev_start_new_thread = PydevStartNewThread()
279
Tor Norbyec667c1f2014-05-28 17:06:51 -0700280
Tor Norbye3a2425a2013-11-04 10:16:08 -0800281#=======================================================================================================================
282# PyDB
283#=======================================================================================================================
284class PyDB:
285 """ Main debugging class
286 Lots of stuff going on here:
287
288 PyDB starts two threads on startup that connect to remote debugger (RDB)
289 The threads continuously read & write commands to RDB.
290 PyDB communicates with these threads through command queues.
291 Every RDB command is processed by calling processNetCommand.
292 Every PyDB net command is sent to the net by posting NetCommand to WriterThread queue
293
294 Some commands need to be executed on the right thread (suspend/resume & friends)
295 These are placed on the internal command queue.
296 """
297
Tor Norbye3a2425a2013-11-04 10:16:08 -0800298
299 def __init__(self):
300 SetGlobalDebugger(self)
301 pydevd_tracing.ReplaceSysSetTraceFunc()
302 self.reader = None
303 self.writer = None
304 self.quitting = None
305 self.cmdFactory = NetCommandFactory()
Tor Norbyec667c1f2014-05-28 17:06:51 -0700306 self._cmd_queue = {} # the hash of Queues. Key is thread id, value is thread
Tor Norbye3a2425a2013-11-04 10:16:08 -0800307 self.breakpoints = {}
308 self.django_breakpoints = {}
309 self.exception_set = {}
310 self.always_exception_set = set()
311 self.django_exception_break = {}
312 self.readyToRun = False
313 self._main_lock = threading.Lock()
314 self._lock_running_thread_ids = threading.Lock()
Tor Norbyec667c1f2014-05-28 17:06:51 -0700315 self._py_db_command_thread_event = threading.Event()
316 CustomFramesContainer._py_db_command_thread_event = self._py_db_command_thread_event
Tor Norbye3a2425a2013-11-04 10:16:08 -0800317 self._finishDebuggingSession = False
318 self._terminationEventSent = False
319 self.force_post_mortem_stop = 0
320 self.signature_factory = None
321 self.SetTrace = pydevd_tracing.SetTrace
322
323 #this is a dict of thread ids pointing to thread ids. Whenever a command is passed to the java end that
324 #acknowledges that a thread was created, the thread id should be passed here -- and if at some time we do not
325 #find that thread alive anymore, we must remove it from this list and make the java side know that the thread
326 #was killed.
327 self._running_thread_ids = {}
328
329 def haveAliveThreads(self):
330 for t in threadingEnumerate():
Tor Norbye92584642014-04-17 08:39:25 -0700331 if not isinstance(t, PyDBDaemonThread) and isThreadAlive(t) and not t.isDaemon():
Tor Norbye3a2425a2013-11-04 10:16:08 -0800332 return True
333
334 return False
335
336 def FinishDebuggingSession(self):
337 self._finishDebuggingSession = True
338
339 def acquire(self):
340 if PyDBUseLocks:
341 self.lock.acquire()
342 return True
343
344 def release(self):
345 if PyDBUseLocks:
346 self.lock.release()
347 return True
348
349 def initializeNetwork(self, sock):
350 try:
Tor Norbyec667c1f2014-05-28 17:06:51 -0700351 sock.settimeout(None) # infinite, no timeouts from now on - jython does not have it
Tor Norbye3a2425a2013-11-04 10:16:08 -0800352 except:
353 pass
354 self.writer = WriterThread(sock)
355 self.reader = ReaderThread(sock)
356 self.writer.start()
357 self.reader.start()
358
Tor Norbyec667c1f2014-05-28 17:06:51 -0700359 time.sleep(0.1) # give threads time to start
Tor Norbye3a2425a2013-11-04 10:16:08 -0800360
361 def connect(self, host, port):
362 if host:
363 s = StartClient(host, port)
364 else:
365 s = StartServer(port)
366
367 self.initializeNetwork(s)
368
369
370 def getInternalQueue(self, thread_id):
371 """ returns internal command queue for a given thread.
372 if new queue is created, notify the RDB about it """
Tor Norbyec667c1f2014-05-28 17:06:51 -0700373 if thread_id.startswith('__frame__'):
374 thread_id = thread_id[thread_id.rfind('|') + 1:]
Tor Norbye3a2425a2013-11-04 10:16:08 -0800375 try:
376 return self._cmd_queue[thread_id]
377 except KeyError:
378 return self._cmd_queue.setdefault(thread_id, _queue.Queue()) #@UndefinedVariable
379
380
381 def postInternalCommand(self, int_cmd, thread_id):
382 """ if thread_id is *, post to all """
383 if thread_id == "*":
Tor Norbyec667c1f2014-05-28 17:06:51 -0700384 threads = threadingEnumerate()
385 for t in threads:
386 thread_name = t.getName()
387 if not thread_name.startswith('pydevd.') or thread_name == 'pydevd.CommandThread':
388 thread_id = GetThreadId(t)
389 queue = self.getInternalQueue(thread_id)
390 queue.put(int_cmd)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800391
392 else:
393 queue = self.getInternalQueue(thread_id)
394 queue.put(int_cmd)
395
396 def checkOutputRedirect(self):
397 global bufferStdOutToServer
398 global bufferStdErrToServer
399
400 if bufferStdOutToServer:
401 initStdoutRedirect()
402 self.checkOutput(sys.stdoutBuf, 1) #@UndefinedVariable
403
404 if bufferStdErrToServer:
405 initStderrRedirect()
406 self.checkOutput(sys.stderrBuf, 2) #@UndefinedVariable
407
408 def checkOutput(self, out, outCtx):
409 '''Checks the output to see if we have to send some buffered output to the debug server
410
411 @param out: sys.stdout or sys.stderr
412 @param outCtx: the context indicating: 1=stdout and 2=stderr (to know the colors to write it)
413 '''
414
415 try:
416 v = out.getvalue()
417
418 if v:
419 self.cmdFactory.makeIoMessage(v, outCtx, self)
420 except:
421 traceback.print_exc()
422
423
424 def processInternalCommands(self):
425 '''This function processes internal commands
426 '''
Tor Norbye3a2425a2013-11-04 10:16:08 -0800427 self._main_lock.acquire()
428 try:
429
430 self.checkOutputRedirect()
431
Tor Norbyec667c1f2014-05-28 17:06:51 -0700432 curr_thread_id = GetThreadId(threadingCurrentThread())
433 program_threads_alive = {}
434 all_threads = threadingEnumerate()
435 program_threads_dead = []
Tor Norbye3a2425a2013-11-04 10:16:08 -0800436 self._lock_running_thread_ids.acquire()
437 try:
438 for t in all_threads:
439 thread_id = GetThreadId(t)
440
Tor Norbye92584642014-04-17 08:39:25 -0700441 if not isinstance(t, PyDBDaemonThread) and isThreadAlive(t):
Tor Norbye3a2425a2013-11-04 10:16:08 -0800442 program_threads_alive[thread_id] = t
443
444 if not DictContains(self._running_thread_ids, thread_id):
445 if not hasattr(t, 'additionalInfo'):
Tor Norbyec667c1f2014-05-28 17:06:51 -0700446 # see http://sourceforge.net/tracker/index.php?func=detail&aid=1955428&group_id=85796&atid=577329
447 # Let's create the additional info right away!
Tor Norbye3a2425a2013-11-04 10:16:08 -0800448 t.additionalInfo = PyDBAdditionalThreadInfo()
449 self._running_thread_ids[thread_id] = t
450 self.writer.addCommand(self.cmdFactory.makeThreadCreatedMessage(t))
451
452
453 queue = self.getInternalQueue(thread_id)
Tor Norbyec667c1f2014-05-28 17:06:51 -0700454 cmdsToReadd = [] # some commands must be processed by the thread itself... if that's the case,
455 # we will re-add the commands to the queue after executing.
Tor Norbye3a2425a2013-11-04 10:16:08 -0800456 try:
457 while True:
458 int_cmd = queue.get(False)
459 if int_cmd.canBeExecutedBy(curr_thread_id):
460 PydevdLog(2, "processing internal command ", str(int_cmd))
461 int_cmd.doIt(self)
462 else:
463 PydevdLog(2, "NOT processing internal command ", str(int_cmd))
464 cmdsToReadd.append(int_cmd)
465
466 except _queue.Empty: #@UndefinedVariable
467 for int_cmd in cmdsToReadd:
468 queue.put(int_cmd)
469 # this is how we exit
470
471
472 thread_ids = list(self._running_thread_ids.keys())
473 for tId in thread_ids:
474 if not DictContains(program_threads_alive, tId):
475 program_threads_dead.append(tId)
476 finally:
477 self._lock_running_thread_ids.release()
478
479 for tId in program_threads_dead:
480 try:
481 self.processThreadNotAlive(tId)
482 except:
483 sys.stderr.write('Error iterating through %s (%s) - %s\n' % (
484 program_threads_alive, program_threads_alive.__class__, dir(program_threads_alive)))
485 raise
486
487
488 if len(program_threads_alive) == 0:
489 self.FinishDebuggingSession()
490 for t in all_threads:
491 if hasattr(t, 'doKillPydevThread'):
492 t.doKillPydevThread()
493
494 finally:
495 self._main_lock.release()
496
497
Tor Norbyec667c1f2014-05-28 17:06:51 -0700498 def setTracingForUntracedContexts(self, ignore_frame=None, overwrite_prev_trace=False):
499 # Enable the tracing for existing threads (because there may be frames being executed that
500 # are currently untraced).
Tor Norbye3a2425a2013-11-04 10:16:08 -0800501 threads = threadingEnumerate()
Tor Norbyec667c1f2014-05-28 17:06:51 -0700502 try:
503 for t in threads:
504 if not t.getName().startswith('pydevd.'):
505 # TODO: optimize so that we only actually add that tracing if it's in
506 # the new breakpoint context.
507 additionalInfo = None
508 try:
509 additionalInfo = t.additionalInfo
510 except AttributeError:
511 pass # that's ok, no info currently set
Tor Norbye3a2425a2013-11-04 10:16:08 -0800512
Tor Norbyec667c1f2014-05-28 17:06:51 -0700513 if additionalInfo is not None:
514 for frame in additionalInfo.IterFrames():
515 if frame is not ignore_frame:
516 self.SetTraceForFrameAndParents(frame, overwrite_prev_trace=overwrite_prev_trace)
517 finally:
518 frame = None
519 t = None
520 threads = None
521 additionalInfo = None
Tor Norbye3a2425a2013-11-04 10:16:08 -0800522
523
524 def processNetCommand(self, cmd_id, seq, text):
525 '''Processes a command received from the Java side
526
527 @param cmd_id: the id of the command
528 @param seq: the sequence of the command
529 @param text: the text received in the command
530
531 @note: this method is run as a big switch... after doing some tests, it's not clear whether changing it for
532 a dict id --> function call will have better performance result. A simple test with xrange(10000000) showed
533 that the gains from having a fast access to what should be executed are lost because of the function call in
534 a way that if we had 10 elements in the switch the if..elif are better -- but growing the number of choices
535 makes the solution with the dispatch look better -- so, if this gets more than 20-25 choices at some time,
536 it may be worth refactoring it (actually, reordering the ifs so that the ones used mostly come before
537 probably will give better performance).
538 '''
539
540 self._main_lock.acquire()
541 try:
542 try:
543 cmd = None
544 if cmd_id == CMD_RUN:
545 self.readyToRun = True
546
547 elif cmd_id == CMD_VERSION:
548 # response is version number
549 local_version, pycharm_os = text.split('\t', 1)
550
551 pydevd_file_utils.set_pycharm_os(pycharm_os)
552
553 cmd = self.cmdFactory.makeVersionMessage(seq)
554
555 elif cmd_id == CMD_LIST_THREADS:
556 # response is a list of threads
557 cmd = self.cmdFactory.makeListThreadsMessage(seq)
558
559 elif cmd_id == CMD_THREAD_KILL:
560 int_cmd = InternalTerminateThread(text)
561 self.postInternalCommand(int_cmd, text)
562
563 elif cmd_id == CMD_THREAD_SUSPEND:
Tor Norbyec667c1f2014-05-28 17:06:51 -0700564 # Yes, thread suspend is still done at this point, not through an internal command!
Tor Norbye3a2425a2013-11-04 10:16:08 -0800565 t = PydevdFindThreadById(text)
566 if t:
567 additionalInfo = None
568 try:
569 additionalInfo = t.additionalInfo
570 except AttributeError:
Tor Norbyec667c1f2014-05-28 17:06:51 -0700571 pass # that's ok, no info currently set
Tor Norbye3a2425a2013-11-04 10:16:08 -0800572
573 if additionalInfo is not None:
574 for frame in additionalInfo.IterFrames():
575 self.SetTraceForFrameAndParents(frame)
576 del frame
577
578 self.setSuspend(t, CMD_THREAD_SUSPEND)
Tor Norbyec667c1f2014-05-28 17:06:51 -0700579 elif text.startswith('__frame__:'):
580 sys.stderr.write("Can't suspend tasklet: %s\n" % (text,))
Tor Norbye3a2425a2013-11-04 10:16:08 -0800581
582 elif cmd_id == CMD_THREAD_RUN:
583 t = PydevdFindThreadById(text)
584 if t:
585 thread_id = GetThreadId(t)
586 int_cmd = InternalRunThread(thread_id)
587 self.postInternalCommand(int_cmd, thread_id)
588
Tor Norbyec667c1f2014-05-28 17:06:51 -0700589 elif text.startswith('__frame__:'):
590 sys.stderr.write("Can't make tasklet run: %s\n" % (text,))
591
592
Tor Norbye3a2425a2013-11-04 10:16:08 -0800593 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 -0700594 # we received some command to make a single step
Tor Norbye3a2425a2013-11-04 10:16:08 -0800595 t = PydevdFindThreadById(text)
596 if t:
597 thread_id = GetThreadId(t)
598 int_cmd = InternalStepThread(thread_id, cmd_id)
599 self.postInternalCommand(int_cmd, thread_id)
600
Tor Norbyec667c1f2014-05-28 17:06:51 -0700601 elif text.startswith('__frame__:'):
602 sys.stderr.write("Can't make tasklet step command: %s\n" % (text,))
603
604
Tor Norbye3a2425a2013-11-04 10:16:08 -0800605 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 -0700606 # we received some command to make a single step
Tor Norbye3a2425a2013-11-04 10:16:08 -0800607 thread_id, line, func_name = text.split('\t', 2)
608 t = PydevdFindThreadById(thread_id)
609 if t:
610 int_cmd = InternalSetNextStatementThread(thread_id, cmd_id, line, func_name)
611 self.postInternalCommand(int_cmd, thread_id)
Tor Norbyec667c1f2014-05-28 17:06:51 -0700612 elif thread_id.startswith('__frame__:'):
613 sys.stderr.write("Can't set next statement in tasklet: %s\n" % (thread_id,))
Tor Norbye3a2425a2013-11-04 10:16:08 -0800614
615
616 elif cmd_id == CMD_RELOAD_CODE:
Tor Norbyec667c1f2014-05-28 17:06:51 -0700617 # we received some command to make a reload of a module
Tor Norbye3a2425a2013-11-04 10:16:08 -0800618 module_name = text.strip()
Tor Norbye3a2425a2013-11-04 10:16:08 -0800619
Tor Norbyec667c1f2014-05-28 17:06:51 -0700620 thread_id = '*' # Any thread
Tor Norbye3a2425a2013-11-04 10:16:08 -0800621
Tor Norbyec667c1f2014-05-28 17:06:51 -0700622 # Note: not going for the main thread because in this case it'd only do the load
623 # when we stopped on a breakpoint.
624 # for tid, t in self._running_thread_ids.items(): #Iterate in copy
625 # thread_name = t.getName()
626 #
627 # print thread_name, GetThreadId(t)
628 # #Note: if possible, try to reload on the main thread
629 # if thread_name == 'MainThread':
630 # thread_id = tid
631
632 int_cmd = ReloadCodeCommand(module_name, thread_id)
633 self.postInternalCommand(int_cmd, thread_id)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800634
635
636 elif cmd_id == CMD_CHANGE_VARIABLE:
Tor Norbyec667c1f2014-05-28 17:06:51 -0700637 # the text is: thread\tstackframe\tFRAME|GLOBAL\tattribute_to_change\tvalue_to_change
Tor Norbye3a2425a2013-11-04 10:16:08 -0800638 try:
639 thread_id, frame_id, scope, attr_and_value = text.split('\t', 3)
640
641 tab_index = attr_and_value.rindex('\t')
642 attr = attr_and_value[0:tab_index].replace('\t', '.')
643 value = attr_and_value[tab_index + 1:]
644 int_cmd = InternalChangeVariable(seq, thread_id, frame_id, scope, attr, value)
645 self.postInternalCommand(int_cmd, thread_id)
646
647 except:
648 traceback.print_exc()
649
650 elif cmd_id == CMD_GET_VARIABLE:
Tor Norbyec667c1f2014-05-28 17:06:51 -0700651 # we received some command to get a variable
652 # the text is: thread_id\tframe_id\tFRAME|GLOBAL\tattributes*
Tor Norbye3a2425a2013-11-04 10:16:08 -0800653 try:
654 thread_id, frame_id, scopeattrs = text.split('\t', 2)
655
Tor Norbyec667c1f2014-05-28 17:06:51 -0700656 if scopeattrs.find('\t') != -1: # there are attributes beyond scope
Tor Norbye3a2425a2013-11-04 10:16:08 -0800657 scope, attrs = scopeattrs.split('\t', 1)
658 else:
659 scope, attrs = (scopeattrs, None)
660
661 int_cmd = InternalGetVariable(seq, thread_id, frame_id, scope, attrs)
662 self.postInternalCommand(int_cmd, thread_id)
663
664 except:
665 traceback.print_exc()
666
667 elif cmd_id == CMD_GET_COMPLETIONS:
Tor Norbyec667c1f2014-05-28 17:06:51 -0700668 # we received some command to get a variable
669 # the text is: thread_id\tframe_id\tactivation token
Tor Norbye3a2425a2013-11-04 10:16:08 -0800670 try:
671 thread_id, frame_id, scope, act_tok = text.split('\t', 3)
672
673 int_cmd = InternalGetCompletions(seq, thread_id, frame_id, act_tok)
674 self.postInternalCommand(int_cmd, thread_id)
675
676 except:
677 traceback.print_exc()
678
679 elif cmd_id == CMD_GET_FRAME:
680 thread_id, frame_id, scope = text.split('\t', 2)
681
682 int_cmd = InternalGetFrame(seq, thread_id, frame_id)
683 self.postInternalCommand(int_cmd, thread_id)
684
685 elif cmd_id == CMD_SET_BREAK:
Tor Norbyec667c1f2014-05-28 17:06:51 -0700686 # func name: 'None': match anything. Empty: match global, specified: only method context.
Tor Norbye3a2425a2013-11-04 10:16:08 -0800687
Tor Norbyec667c1f2014-05-28 17:06:51 -0700688 # command to add some breakpoint.
Tor Norbye3a2425a2013-11-04 10:16:08 -0800689 # text is file\tline. Add to breakpoints dictionary
690 type, file, line, condition, expression = text.split('\t', 4)
691
Tor Norbyec667c1f2014-05-28 17:06:51 -0700692 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.
693 file = file.encode(file_system_encoding)
694
Tor Norbye3a2425a2013-11-04 10:16:08 -0800695 if condition.startswith('**FUNC**'):
696 func_name, condition = condition.split('\t', 1)
697
Tor Norbyec667c1f2014-05-28 17:06:51 -0700698 # We must restore new lines and tabs as done in
699 # AbstractDebugTarget.breakpointAdded
Tor Norbye3a2425a2013-11-04 10:16:08 -0800700 condition = condition.replace("@_@NEW_LINE_CHAR@_@", '\n').\
701 replace("@_@TAB_CHAR@_@", '\t').strip()
702
703 func_name = func_name[8:]
704 else:
Tor Norbyec667c1f2014-05-28 17:06:51 -0700705 func_name = 'None' # Match anything if not specified.
Tor Norbye3a2425a2013-11-04 10:16:08 -0800706
707
708 file = NormFileToServer(file)
709
710 if not pydevd_file_utils.exists(file):
711 sys.stderr.write('pydev debugger: warning: trying to add breakpoint'\
712 ' to file that does not exist: %s (will have no effect)\n' % (file,))
713 sys.stderr.flush()
714
715 line = int(line)
716
717 if len(condition) <= 0 or condition is None or condition == "None":
718 condition = None
719
720 if len(expression) <= 0 or expression is None or expression == "None":
721 expression = None
722
723 if type == 'python-line':
724 breakpoint = LineBreakpoint(type, True, condition, func_name, expression)
725 breakpoint.add(self.breakpoints, file, line, func_name)
726 elif type == 'django-line':
727 breakpoint = DjangoLineBreakpoint(type, file, line, True, condition, func_name, expression)
728 breakpoint.add(self.django_breakpoints, file, line, func_name)
729 else:
730 raise NameError(type)
731
732 self.setTracingForUntracedContexts()
733
734 elif cmd_id == CMD_REMOVE_BREAK:
735 #command to remove some breakpoint
736 #text is file\tline. Remove from breakpoints dictionary
737 type, file, line = text.split('\t', 2)
738 file = NormFileToServer(file)
739 try:
740 line = int(line)
741 except ValueError:
742 pass
743
744 else:
745 found = False
746 try:
747 if type == 'django-line':
748 del self.django_breakpoints[file][line]
749 elif type == 'python-line':
750 del self.breakpoints[file][line] #remove the breakpoint in that line
751 else:
752 try:
753 del self.django_breakpoints[file][line]
754 found = True
755 except:
756 pass
757 try:
758 del self.breakpoints[file][line] #remove the breakpoint in that line
759 found = True
760 except:
761 pass
762
763 if DebugInfoHolder.DEBUG_TRACE_BREAKPOINTS > 0:
764 sys.stderr.write('Removed breakpoint:%s - %s\n' % (file, line))
765 sys.stderr.flush()
766 except KeyError:
767 found = False
768
769 if not found:
770 #ok, it's not there...
771 if DebugInfoHolder.DEBUG_TRACE_BREAKPOINTS > 0:
772 #Sometimes, when adding a breakpoint, it adds a remove command before (don't really know why)
773 sys.stderr.write("breakpoint not found: %s - %s\n" % (file, line))
774 sys.stderr.flush()
775
776 elif cmd_id == CMD_EVALUATE_EXPRESSION or cmd_id == CMD_EXEC_EXPRESSION:
777 #command to evaluate the given expression
778 #text is: thread\tstackframe\tLOCAL\texpression
779 thread_id, frame_id, scope, expression, trim = text.split('\t', 4)
780 int_cmd = InternalEvaluateExpression(seq, thread_id, frame_id, expression,
781 cmd_id == CMD_EXEC_EXPRESSION, int(trim) == 1)
782 self.postInternalCommand(int_cmd, thread_id)
783
784 elif cmd_id == CMD_CONSOLE_EXEC:
785 #command to exec expression in console, in case expression is only partially valid 'False' is returned
786 #text is: thread\tstackframe\tLOCAL\texpression
787
788 thread_id, frame_id, scope, expression = text.split('\t', 3)
789
790 int_cmd = InternalConsoleExec(seq, thread_id, frame_id, expression)
791 self.postInternalCommand(int_cmd, thread_id)
792
793 elif cmd_id == CMD_ADD_EXCEPTION_BREAK:
794 exception, notify_always, notify_on_terminate = text.split('\t', 2)
795
796 eb = ExceptionBreakpoint(exception, notify_always, notify_on_terminate)
797
798 self.exception_set[exception] = eb
799
800 if eb.notify_on_terminate:
801 update_exception_hook(self)
802 if DebugInfoHolder.DEBUG_TRACE_BREAKPOINTS > 0:
803 pydev_log.error("Exceptions to hook on terminate: %s\n" % (self.exception_set,))
804
805 if eb.notify_always:
806 self.always_exception_set.add(exception)
807 if DebugInfoHolder.DEBUG_TRACE_BREAKPOINTS > 0:
808 pydev_log.error("Exceptions to hook always: %s\n" % (self.always_exception_set,))
809 self.setTracingForUntracedContexts()
810
811 elif cmd_id == CMD_REMOVE_EXCEPTION_BREAK:
812 exception = text
813 try:
814 del self.exception_set[exception]
815 self.always_exception_set.remove(exception)
816 except:
Tor Norbye1fff8e22014-03-10 13:13:45 -0700817 pydev_log.debug("Error while removing exception"%sys.exc_info()[0]);
Tor Norbye3a2425a2013-11-04 10:16:08 -0800818 update_exception_hook(self)
819
820 elif cmd_id == CMD_LOAD_SOURCE:
821 path = text
822 try:
823 f = open(path, 'r')
824 source = f.read()
825 self.cmdFactory.makeLoadSourceMessage(seq, source, self)
826 except:
827 return self.cmdFactory.makeErrorMessage(seq, pydevd_tracing.GetExceptionTracebackStr())
828
829 elif cmd_id == CMD_ADD_DJANGO_EXCEPTION_BREAK:
830 exception = text
831
832 self.django_exception_break[exception] = True
833 self.setTracingForUntracedContexts()
834
835 elif cmd_id == CMD_REMOVE_DJANGO_EXCEPTION_BREAK:
836 exception = text
837
838 try:
839 del self.django_exception_break[exception]
840 except :
841 pass
842
843 else:
844 #I have no idea what this is all about
845 cmd = self.cmdFactory.makeErrorMessage(seq, "unexpected command " + str(cmd_id))
846
847 if cmd is not None:
848 self.writer.addCommand(cmd)
849 del cmd
850
851 except Exception:
852 traceback.print_exc()
853 cmd = self.cmdFactory.makeErrorMessage(seq,
854 "Unexpected exception in processNetCommand.\nInitial params: %s" % ((cmd_id, seq, text),))
855
856 self.writer.addCommand(cmd)
857 finally:
858 self._main_lock.release()
859
860 def processThreadNotAlive(self, threadId):
861 """ if thread is not alive, cancel trace_dispatch processing """
862 self._lock_running_thread_ids.acquire()
863 try:
864 thread = self._running_thread_ids.pop(threadId, None)
865 if thread is None:
866 return
867
868 wasNotified = thread.additionalInfo.pydev_notify_kill
869 if not wasNotified:
870 thread.additionalInfo.pydev_notify_kill = True
871
872 finally:
873 self._lock_running_thread_ids.release()
874
875 cmd = self.cmdFactory.makeThreadKilledMessage(threadId)
876 self.writer.addCommand(cmd)
877
878
879 def setSuspend(self, thread, stop_reason):
880 thread.additionalInfo.suspend_type = PYTHON_SUSPEND
881 thread.additionalInfo.pydev_state = STATE_SUSPEND
882 thread.stop_reason = stop_reason
883
884
885 def doWaitSuspend(self, thread, frame, event, arg): #@UnusedVariable
886 """ busy waits until the thread state changes to RUN
887 it expects thread's state as attributes of the thread.
888 Upon running, processes any outstanding Stepping commands.
889 """
890 self.processInternalCommands()
891
892 message = getattr(thread.additionalInfo, "message", None)
893
894 cmd = self.cmdFactory.makeThreadSuspendMessage(GetThreadId(thread), frame, thread.stop_reason, message)
895 self.writer.addCommand(cmd)
896
Tor Norbyec667c1f2014-05-28 17:06:51 -0700897 CustomFramesContainer.custom_frames_lock.acquire()
898 try:
899 from_this_thread = []
Tor Norbye3a2425a2013-11-04 10:16:08 -0800900
Tor Norbyec667c1f2014-05-28 17:06:51 -0700901 for frame_id, custom_frame in CustomFramesContainer.custom_frames.items():
902 if custom_frame.thread_id == thread.ident:
903 # print >> sys.stderr, 'Frame created: ', frame_id
904 self.writer.addCommand(self.cmdFactory.makeCustomFrameCreatedMessage(frame_id, custom_frame.name))
905 self.writer.addCommand(self.cmdFactory.makeThreadSuspendMessage(frame_id, custom_frame.frame, CMD_THREAD_SUSPEND, ""))
906
907 from_this_thread.append(frame_id)
908
909 finally:
910 CustomFramesContainer.custom_frames_lock.release()
911
912
913
914 info = thread.additionalInfo
Tor Norbye3a2425a2013-11-04 10:16:08 -0800915 while info.pydev_state == STATE_SUSPEND and not self._finishDebuggingSession:
916 self.processInternalCommands()
917 time.sleep(0.01)
918
Tor Norbyec667c1f2014-05-28 17:06:51 -0700919 # process any stepping instructions
Tor Norbye3a2425a2013-11-04 10:16:08 -0800920 if info.pydev_step_cmd == CMD_STEP_INTO:
921 info.pydev_step_stop = None
922 info.pydev_smart_step_stop = None
923
924 elif info.pydev_step_cmd == CMD_STEP_OVER:
925 info.pydev_step_stop = frame
926 info.pydev_smart_step_stop = None
927 self.SetTraceForFrameAndParents(frame)
928
929 elif info.pydev_step_cmd == CMD_SMART_STEP_INTO:
930 self.SetTraceForFrameAndParents(frame)
931 info.pydev_step_stop = None
932 info.pydev_smart_step_stop = frame
933
934 elif info.pydev_step_cmd == CMD_RUN_TO_LINE or info.pydev_step_cmd == CMD_SET_NEXT_STATEMENT :
935 self.SetTraceForFrameAndParents(frame)
936
937 if event == 'line' or event == 'exception':
938 #If we're already in the correct context, we have to stop it now, because we can act only on
939 #line events -- if a return was the next statement it wouldn't work (so, we have this code
940 #repeated at pydevd_frame).
941 stop = False
942 curr_func_name = frame.f_code.co_name
943
944 #global context is set with an empty name
945 if curr_func_name in ('?', '<module>'):
946 curr_func_name = ''
947
948 if curr_func_name == info.pydev_func_name:
949 line = info.pydev_next_line
950 if frame.f_lineno == line:
951 stop = True
952 else :
953 if frame.f_trace is None:
954 frame.f_trace = self.trace_dispatch
955 frame.f_lineno = line
956 frame.f_trace = None
957 stop = True
958 if stop:
959 info.pydev_state = STATE_SUSPEND
960 self.doWaitSuspend(thread, frame, event, arg)
961 return
962
963
964 elif info.pydev_step_cmd == CMD_STEP_RETURN:
965 back_frame = frame.f_back
966 if back_frame is not None:
Tor Norbyec667c1f2014-05-28 17:06:51 -0700967 # 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 -0800968 info.pydev_step_stop = frame
969 self.SetTraceForFrameAndParents(frame)
970 else:
Tor Norbyec667c1f2014-05-28 17:06:51 -0700971 # No back frame?!? -- this happens in jython when we have some frame created from an awt event
972 # (the previous frame would be the awt event, but this doesn't make part of 'jython', only 'java')
973 # 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 -0800974 info.pydev_step_stop = None
975 info.pydev_step_cmd = None
976 info.pydev_state = STATE_RUN
977
978 del frame
979 cmd = self.cmdFactory.makeThreadRunMessage(GetThreadId(thread), info.pydev_step_cmd)
980 self.writer.addCommand(cmd)
981
Tor Norbyec667c1f2014-05-28 17:06:51 -0700982 CustomFramesContainer.custom_frames_lock.acquire()
983 try:
984 # The ones that remained on last_running must now be removed.
985 for frame_id in from_this_thread:
986 # print >> sys.stderr, 'Removing created frame: ', frame_id
987 self.writer.addCommand(self.cmdFactory.makeThreadKilledMessage(frame_id))
988
989 finally:
990 CustomFramesContainer.custom_frames_lock.release()
Tor Norbye3a2425a2013-11-04 10:16:08 -0800991
992 def handle_post_mortem_stop(self, additionalInfo, t):
993 pydev_log.debug("We are stopping in post-mortem\n")
994 self.force_post_mortem_stop -= 1
995 frame, frames_byid = additionalInfo.pydev_force_stop_at_exception
996 thread_id = GetThreadId(t)
997 pydevd_vars.addAdditionalFrameById(thread_id, frames_byid)
998 try:
999 try:
1000 add_exception_to_frame(frame, additionalInfo.exception)
1001 self.setSuspend(t, CMD_ADD_EXCEPTION_BREAK)
1002 self.doWaitSuspend(t, frame, 'exception', None)
1003 except:
1004 pydev_log.error("We've got an error while stopping in post-mortem: %s\n"%sys.exc_info()[0])
1005 finally:
1006 additionalInfo.pydev_force_stop_at_exception = None
1007 pydevd_vars.removeAdditionalFrameById(thread_id)
1008
1009 def trace_dispatch(self, frame, event, arg):
1010 ''' This is the callback used when we enter some context in the debugger.
1011
1012 We also decorate the thread we are in with info about the debugging.
1013 The attributes added are:
1014 pydev_state
1015 pydev_step_stop
1016 pydev_step_cmd
1017 pydev_notify_kill
1018 '''
1019 try:
1020 if self._finishDebuggingSession and not self._terminationEventSent:
1021 #that was not working very well because jython gave some socket errors
Tor Norbye3a2425a2013-11-04 10:16:08 -08001022 try:
1023 threads = threadingEnumerate()
1024 for t in threads:
1025 if hasattr(t, 'doKillPydevThread'):
1026 t.doKillPydevThread()
1027 except:
1028 traceback.print_exc()
1029 self._terminationEventSent = True
1030 return None
1031
1032 filename, base = GetFilenameAndBase(frame)
1033
1034 is_file_to_ignore = DictContains(DONT_TRACE, base) #we don't want to debug threading or anything related to pydevd
1035
1036 if is_file_to_ignore:
1037 return None
1038
1039 #print('trace_dispatch', base, frame.f_lineno, event, frame.f_code.co_name)
1040 try:
1041 #this shouldn't give an exception, but it could happen... (python bug)
1042 #see http://mail.python.org/pipermail/python-bugs-list/2007-June/038796.html
1043 #and related bug: http://bugs.python.org/issue1733757
1044 t = threadingCurrentThread()
1045 except:
1046 frame.f_trace = self.trace_dispatch
1047 return self.trace_dispatch
1048
1049 try:
1050 additionalInfo = t.additionalInfo
1051 if additionalInfo is None:
1052 raise AttributeError()
1053 except:
1054 t.additionalInfo = PyDBAdditionalThreadInfo()
1055 additionalInfo = t.additionalInfo
1056
1057 if additionalInfo is None:
1058 return None
1059
1060 if additionalInfo.is_tracing:
1061 f = frame
1062 while f is not None:
1063 fname, bs = GetFilenameAndBase(f)
1064 if bs == 'pydevd_frame.py':
1065 if 'trace_dispatch' == f.f_code.co_name:
1066 return None #we don't wan't to trace code invoked from pydevd_frame.trace_dispatch
1067 f = f.f_back
1068
1069 # if thread is not alive, cancel trace_dispatch processing
Tor Norbye92584642014-04-17 08:39:25 -07001070 if not isThreadAlive(t):
Tor Norbye3a2425a2013-11-04 10:16:08 -08001071 self.processThreadNotAlive(GetThreadId(t))
Tor Norbye92584642014-04-17 08:39:25 -07001072 return None # suspend tracing
Tor Norbye3a2425a2013-11-04 10:16:08 -08001073
1074 if is_file_to_ignore:
1075 return None
1076
Tor Norbyec667c1f2014-05-28 17:06:51 -07001077 # each new frame...
Tor Norbye3a2425a2013-11-04 10:16:08 -08001078 return additionalInfo.CreateDbFrame((self, filename, additionalInfo, t, frame)).trace_dispatch(frame, event, arg)
1079
1080 except SystemExit:
1081 return None
1082
Tor Norbye3a2425a2013-11-04 10:16:08 -08001083 except Exception:
Tor Norbyec667c1f2014-05-28 17:06:51 -07001084 # Log it
Tor Norbye3a2425a2013-11-04 10:16:08 -08001085 if traceback is not None:
Tor Norbyec667c1f2014-05-28 17:06:51 -07001086 # This can actually happen during the interpreter shutdown in Python 2.7
Tor Norbye3a2425a2013-11-04 10:16:08 -08001087 traceback.print_exc()
1088 return None
1089
1090 if USE_PSYCO_OPTIMIZATION:
1091 try:
1092 import psyco
1093 trace_dispatch = psyco.proxy(trace_dispatch)
1094 processNetCommand = psyco.proxy(processNetCommand)
1095 processInternalCommands = psyco.proxy(processInternalCommands)
1096 doWaitSuspend = psyco.proxy(doWaitSuspend)
1097 getInternalQueue = psyco.proxy(getInternalQueue)
1098 except ImportError:
Tor Norbyec667c1f2014-05-28 17:06:51 -07001099 if hasattr(sys, 'exc_clear'): # jython does not have it
1100 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 -08001101
1102 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"):
1103 sys.stderr.write("pydev debugger: warning: psyco not available for speedups (the debugger will still work correctly, but a bit slower)\n")
1104 sys.stderr.flush()
1105
1106
1107
Tor Norbyec667c1f2014-05-28 17:06:51 -07001108 def SetTraceForFrameAndParents(self, frame, also_add_to_passed_frame=True, overwrite_prev_trace=False):
Tor Norbye3a2425a2013-11-04 10:16:08 -08001109 dispatch_func = self.trace_dispatch
1110
1111 if also_add_to_passed_frame:
Tor Norbyec667c1f2014-05-28 17:06:51 -07001112 self.update_trace(frame, dispatch_func, overwrite_prev_trace)
Tor Norbye3a2425a2013-11-04 10:16:08 -08001113
1114 frame = frame.f_back
1115 while frame:
Tor Norbyec667c1f2014-05-28 17:06:51 -07001116 self.update_trace(frame, dispatch_func, overwrite_prev_trace)
Tor Norbye3a2425a2013-11-04 10:16:08 -08001117
1118 frame = frame.f_back
1119 del frame
1120
1121 def update_trace(self, frame, dispatch_func, overwrite_prev):
1122 if frame.f_trace is None:
1123 frame.f_trace = dispatch_func
1124 else:
1125 if overwrite_prev:
1126 frame.f_trace = dispatch_func
1127 else:
1128 try:
1129 #If it's the trace_exception, go back to the frame trace dispatch!
1130 if frame.f_trace.im_func.__name__ == 'trace_exception':
1131 frame.f_trace = frame.f_trace.im_self.trace_dispatch
1132 except AttributeError:
1133 pass
1134 frame = frame.f_back
1135 del frame
1136
Tor Norbyec667c1f2014-05-28 17:06:51 -07001137 def prepareToRun(self):
1138 ''' Shared code to prepare debugging by installing traces and registering threads '''
1139
1140 # for completeness, we'll register the pydevd.reader & pydevd.writer threads
1141 net = NetCommand(str(CMD_THREAD_CREATE), 0, '<xml><thread name="pydevd.reader" id="-1"/></xml>')
1142 self.writer.addCommand(net)
1143 net = NetCommand(str(CMD_THREAD_CREATE), 0, '<xml><thread name="pydevd.writer" id="-1"/></xml>')
1144 self.writer.addCommand(net)
1145
1146 pydevd_tracing.SetTrace(self.trace_dispatch)
1147 self.patch_threads()
Tor Norbye3a2425a2013-11-04 10:16:08 -08001148
1149
Tor Norbyec667c1f2014-05-28 17:06:51 -07001150 PyDBCommandThread(self).start()
1151 PyDBCheckAliveThread(self).start()
1152
1153 def patch_threads(self):
1154 try:
1155 # not available in jython!
1156 threading.settrace(self.trace_dispatch) # for all future threads
1157 except:
1158 pass
1159
1160 try:
1161 thread.start_new_thread = pydev_start_new_thread
1162 thread.start_new = pydev_start_new_thread
1163 except:
1164 pass
1165
1166
1167 def run(self, file, globals=None, locals=None, set_trace=True):
1168 if os.path.isdir(file):
1169 new_target = os.path.join(file, '__main__.py')
1170 if os.path.isfile(new_target):
1171 file = new_target
Tor Norbye3a2425a2013-11-04 10:16:08 -08001172
1173 if globals is None:
Tor Norbyec667c1f2014-05-28 17:06:51 -07001174 # patch provided by: Scott Schlesier - when script is run, it does not
1175 # use globals from pydevd:
1176 # This will prevent the pydevd script from contaminating the namespace for the script to be debugged
Tor Norbye3a2425a2013-11-04 10:16:08 -08001177
Tor Norbyec667c1f2014-05-28 17:06:51 -07001178 # pretend pydevd is not the main module, and
1179 # convince the file to be debugged that it was loaded as main
Tor Norbye3a2425a2013-11-04 10:16:08 -08001180 sys.modules['pydevd'] = sys.modules['__main__']
1181 sys.modules['pydevd'].__name__ = 'pydevd'
1182
1183 from imp import new_module
1184 m = new_module('__main__')
1185 sys.modules['__main__'] = m
Tor Norbye70ae6f22014-02-06 14:02:54 -08001186 if hasattr(sys.modules['pydevd'], '__loader__'):
1187 setattr(m, '__loader__', getattr(sys.modules['pydevd'], '__loader__'))
1188
Tor Norbye3a2425a2013-11-04 10:16:08 -08001189 m.__file__ = file
1190 globals = m.__dict__
1191 try:
1192 globals['__builtins__'] = __builtins__
1193 except NameError:
Tor Norbyec667c1f2014-05-28 17:06:51 -07001194 pass # Not there on Jython...
Tor Norbye3a2425a2013-11-04 10:16:08 -08001195
1196 if locals is None:
1197 locals = globals
1198
Tor Norbyec667c1f2014-05-28 17:06:51 -07001199 if set_trace:
1200 # Predefined (writable) attributes: __name__ is the module's name;
1201 # __doc__ is the module's documentation string, or None if unavailable;
1202 # __file__ is the pathname of the file from which the module was loaded,
1203 # if it was loaded from a file. The __file__ attribute is not present for
1204 # C modules that are statically linked into the interpreter; for extension modules
1205 # loaded dynamically from a shared library, it is the pathname of the shared library file.
Tor Norbye3a2425a2013-11-04 10:16:08 -08001206
1207
Tor Norbyec667c1f2014-05-28 17:06:51 -07001208 # 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
1209 # debug and run.
1210 if m.__file__.startswith(sys.path[0]):
1211 # print >> sys.stderr, 'Deleting: ', sys.path[0]
1212 del sys.path[0]
Tor Norbye3a2425a2013-11-04 10:16:08 -08001213
Tor Norbyec667c1f2014-05-28 17:06:51 -07001214 # now, the local directory has to be added to the pythonpath
1215 # sys.path.insert(0, os.getcwd())
1216 # Changed: it's not the local directory, but the directory of the file launched
1217 # The file being run ust be in the pythonpath (even if it was not before)
1218 sys.path.insert(0, os.path.split(file)[0])
Tor Norbye3a2425a2013-11-04 10:16:08 -08001219
Tor Norbyec667c1f2014-05-28 17:06:51 -07001220 self.prepareToRun()
Tor Norbye3a2425a2013-11-04 10:16:08 -08001221
Tor Norbyec667c1f2014-05-28 17:06:51 -07001222 while not self.readyToRun:
1223 time.sleep(0.1) # busy wait until we receive run command
Tor Norbye3a2425a2013-11-04 10:16:08 -08001224
Tor Norbye3a2425a2013-11-04 10:16:08 -08001225
Tor Norbyec667c1f2014-05-28 17:06:51 -07001226 pydev_imports.execfile(file, globals, locals) # execute the script
Tor Norbye3a2425a2013-11-04 10:16:08 -08001227
1228 def exiting(self):
1229 sys.stdout.flush()
1230 sys.stderr.flush()
1231 self.checkOutputRedirect()
1232 cmd = self.cmdFactory.makeExitMessage()
1233 self.writer.addCommand(cmd)
1234
1235def set_debug(setup):
1236 setup['DEBUG_RECORD_SOCKET_READS'] = True
1237 setup['DEBUG_TRACE_BREAKPOINTS'] = 1
1238 setup['DEBUG_TRACE_LEVEL'] = 3
1239
1240
1241def processCommandLine(argv):
1242 """ parses the arguments.
1243 removes our arguments from the command line """
1244 setup = {}
1245 setup['client'] = ''
1246 setup['server'] = False
1247 setup['port'] = 0
1248 setup['file'] = ''
1249 setup['multiproc'] = False
1250 setup['save-signatures'] = False
1251 i = 0
1252 del argv[0]
1253 while (i < len(argv)):
1254 if (argv[i] == '--port'):
1255 del argv[i]
1256 setup['port'] = int(argv[i])
1257 del argv[i]
1258 elif (argv[i] == '--vm_type'):
1259 del argv[i]
1260 setup['vm_type'] = argv[i]
1261 del argv[i]
1262 elif (argv[i] == '--client'):
1263 del argv[i]
1264 setup['client'] = argv[i]
1265 del argv[i]
1266 elif (argv[i] == '--server'):
1267 del argv[i]
1268 setup['server'] = True
1269 elif (argv[i] == '--file'):
1270 del argv[i]
1271 setup['file'] = argv[i]
1272 i = len(argv) # pop out, file is our last argument
1273 elif (argv[i] == '--DEBUG_RECORD_SOCKET_READS'):
1274 del argv[i]
1275 setup['DEBUG_RECORD_SOCKET_READS'] = True
1276 elif (argv[i] == '--DEBUG'):
1277 del argv[i]
1278 set_debug(setup)
1279 elif (argv[i] == '--multiproc'):
1280 del argv[i]
1281 setup['multiproc'] = True
1282 elif (argv[i] == '--save-signatures'):
1283 del argv[i]
1284 setup['save-signatures'] = True
1285 else:
1286 raise ValueError("unexpected option " + argv[i])
1287 return setup
1288
1289def usage(doExit=0):
1290 sys.stdout.write('Usage:\n')
1291 sys.stdout.write('pydevd.py --port=N [(--client hostname) | --server] --file executable [file_options]\n')
1292 if doExit:
1293 sys.exit(0)
1294
1295def SetTraceForParents(frame, dispatch_func):
1296 frame = frame.f_back
1297 while frame:
1298 if frame.f_trace is None:
1299 frame.f_trace = dispatch_func
1300
1301 frame = frame.f_back
1302 del frame
1303
1304def exit_hook():
1305 debugger = GetGlobalDebugger()
1306 debugger.exiting()
1307
1308def initStdoutRedirect():
1309 if not getattr(sys, 'stdoutBuf', None):
1310 sys.stdoutBuf = pydevd_io.IOBuf()
1311 sys.stdout = pydevd_io.IORedirector(sys.stdout, sys.stdoutBuf) #@UndefinedVariable
1312
1313def initStderrRedirect():
1314 if not getattr(sys, 'stderrBuf', None):
1315 sys.stderrBuf = pydevd_io.IOBuf()
1316 sys.stderr = pydevd_io.IORedirector(sys.stderr, sys.stderrBuf) #@UndefinedVariable
1317
Tor Norbyec667c1f2014-05-28 17:06:51 -07001318#=======================================================================================================================
1319# settrace
1320#=======================================================================================================================
1321def settrace(
1322 host=None,
1323 stdoutToServer=False,
1324 stderrToServer=False,
1325 port=5678,
1326 suspend=True,
1327 trace_only_current_thread=False,
1328 overwrite_prev_trace=False,
1329 patch_multiprocessing=False,
1330 ):
Tor Norbye3a2425a2013-11-04 10:16:08 -08001331 '''Sets the tracing function with the pydev debug function and initializes needed facilities.
1332
Tor Norbyec667c1f2014-05-28 17:06:51 -07001333 @param host: the user may specify another host, if the debug server is not in the same machine (default is the local
1334 host)
1335
Tor Norbye3a2425a2013-11-04 10:16:08 -08001336 @param stdoutToServer: when this is true, the stdout is passed to the debug server
Tor Norbyec667c1f2014-05-28 17:06:51 -07001337
Tor Norbye3a2425a2013-11-04 10:16:08 -08001338 @param stderrToServer: when this is true, the stderr is passed to the debug server
1339 so that they are printed in its console and not in this process console.
Tor Norbyec667c1f2014-05-28 17:06:51 -07001340
Tor Norbye3a2425a2013-11-04 10:16:08 -08001341 @param port: specifies which port to use for communicating with the server (note that the server must be started
1342 in the same port). @note: currently it's hard-coded at 5678 in the client
Tor Norbyec667c1f2014-05-28 17:06:51 -07001343
Tor Norbye3a2425a2013-11-04 10:16:08 -08001344 @param suspend: whether a breakpoint should be emulated as soon as this function is called.
Tor Norbyec667c1f2014-05-28 17:06:51 -07001345
1346 @param trace_only_current_thread: determines if only the current thread will be traced or all current and future
1347 threads will also have the tracing enabled.
1348
1349 @param overwrite_prev_trace: if True we'll reset the frame.f_trace of frames which are already being traced
1350
1351 @param patch_multiprocessing: if True we'll patch the functions which create new processes so that launched
1352 processes are debugged.
Tor Norbye3a2425a2013-11-04 10:16:08 -08001353 '''
1354 _set_trace_lock.acquire()
1355 try:
Tor Norbyec667c1f2014-05-28 17:06:51 -07001356 _locked_settrace(
1357 host,
1358 stdoutToServer,
1359 stderrToServer,
1360 port,
1361 suspend,
1362 trace_only_current_thread,
1363 overwrite_prev_trace,
1364 patch_multiprocessing,
1365 )
Tor Norbye3a2425a2013-11-04 10:16:08 -08001366 finally:
1367 _set_trace_lock.release()
1368
Tor Norbyec667c1f2014-05-28 17:06:51 -07001369
1370
Tor Norbye3a2425a2013-11-04 10:16:08 -08001371_set_trace_lock = threading.Lock()
1372
Tor Norbyec667c1f2014-05-28 17:06:51 -07001373def _locked_settrace(
1374 host,
1375 stdoutToServer,
1376 stderrToServer,
1377 port,
1378 suspend,
1379 trace_only_current_thread,
1380 overwrite_prev_trace,
1381 patch_multiprocessing,
1382 ):
1383 if patch_multiprocessing:
1384 try:
1385 import pydev_monkey #Jython 2.1 can't use it...
1386 except:
1387 pass
1388 else:
1389 pydev_monkey.patch_new_process_functions()
1390
Tor Norbye3a2425a2013-11-04 10:16:08 -08001391 if host is None:
1392 import pydev_localhost
1393 host = pydev_localhost.get_localhost()
1394
1395 global connected
1396 global bufferStdOutToServer
1397 global bufferStdErrToServer
Tor Norbye3a2425a2013-11-04 10:16:08 -08001398
1399 if not connected :
Tor Norbye3a2425a2013-11-04 10:16:08 -08001400 pydevd_vm_type.SetupType()
1401
1402 debugger = PyDB()
Tor Norbyec667c1f2014-05-28 17:06:51 -07001403 debugger.connect(host, port) # Note: connect can raise error.
1404
1405 # Mark connected only if it actually succeeded.
1406 connected = True
1407 bufferStdOutToServer = stdoutToServer
1408 bufferStdErrToServer = stderrToServer
Tor Norbye3a2425a2013-11-04 10:16:08 -08001409
1410 net = NetCommand(str(CMD_THREAD_CREATE), 0, '<xml><thread name="pydevd.reader" id="-1"/></xml>')
1411 debugger.writer.addCommand(net)
1412 net = NetCommand(str(CMD_THREAD_CREATE), 0, '<xml><thread name="pydevd.writer" id="-1"/></xml>')
1413 debugger.writer.addCommand(net)
1414
1415 if bufferStdOutToServer:
1416 initStdoutRedirect()
1417
1418 if bufferStdErrToServer:
1419 initStderrRedirect()
1420
Tor Norbyec667c1f2014-05-28 17:06:51 -07001421 debugger.SetTraceForFrameAndParents(GetFrame(), False, overwrite_prev_trace=overwrite_prev_trace)
1422
1423
1424 CustomFramesContainer.custom_frames_lock.acquire()
1425 try:
1426 for _frameId, custom_frame in CustomFramesContainer.custom_frames.items():
1427 debugger.SetTraceForFrameAndParents(custom_frame.frame, False)
1428 finally:
1429 CustomFramesContainer.custom_frames_lock.release()
1430
Tor Norbye3a2425a2013-11-04 10:16:08 -08001431
1432 t = threadingCurrentThread()
1433 try:
1434 additionalInfo = t.additionalInfo
1435 except AttributeError:
1436 additionalInfo = PyDBAdditionalThreadInfo()
1437 t.additionalInfo = additionalInfo
1438
1439 while not debugger.readyToRun:
Tor Norbyec667c1f2014-05-28 17:06:51 -07001440 time.sleep(0.1) # busy wait until we receive run command
Tor Norbye3a2425a2013-11-04 10:16:08 -08001441
Tor Norbyec667c1f2014-05-28 17:06:51 -07001442 # note that we do that through pydevd_tracing.SetTrace so that the tracing
1443 # is not warned to the user!
Tor Norbye3a2425a2013-11-04 10:16:08 -08001444 pydevd_tracing.SetTrace(debugger.trace_dispatch)
1445
1446 if not trace_only_current_thread:
Tor Norbyec667c1f2014-05-28 17:06:51 -07001447 # Trace future threads?
1448 debugger.patch_threads()
Tor Norbye3a2425a2013-11-04 10:16:08 -08001449
Tor Norbyec667c1f2014-05-28 17:06:51 -07001450 # As this is the first connection, also set tracing for any untraced threads
1451 debugger.setTracingForUntracedContexts(ignore_frame=GetFrame(), overwrite_prev_trace=overwrite_prev_trace)
Tor Norbye3a2425a2013-11-04 10:16:08 -08001452
1453 sys.exitfunc = exit_hook
Tor Norbyec667c1f2014-05-28 17:06:51 -07001454 #Suspend as the last thing after all tracing is in place.
1455 if suspend:
1456 debugger.setSuspend(t, CMD_SET_BREAK)
Tor Norbye3a2425a2013-11-04 10:16:08 -08001457
1458 PyDBCommandThread(debugger).start()
1459 PyDBCheckAliveThread(debugger).start()
1460
1461 else:
Tor Norbyec667c1f2014-05-28 17:06:51 -07001462 # ok, we're already in debug mode, with all set, so, let's just set the break
Tor Norbye3a2425a2013-11-04 10:16:08 -08001463 debugger = GetGlobalDebugger()
1464
1465 debugger.SetTraceForFrameAndParents(GetFrame(), False)
1466
1467 t = threadingCurrentThread()
1468 try:
1469 additionalInfo = t.additionalInfo
1470 except AttributeError:
1471 additionalInfo = PyDBAdditionalThreadInfo()
1472 t.additionalInfo = additionalInfo
1473
1474 pydevd_tracing.SetTrace(debugger.trace_dispatch)
1475
1476 if not trace_only_current_thread:
Tor Norbyec667c1f2014-05-28 17:06:51 -07001477 # Trace future threads?
1478 debugger.patch_threads()
Tor Norbye3a2425a2013-11-04 10:16:08 -08001479
Tor Norbye3a2425a2013-11-04 10:16:08 -08001480
1481 if suspend:
1482 debugger.setSuspend(t, CMD_SET_BREAK)
1483
Tor Norbyec667c1f2014-05-28 17:06:51 -07001484
Tor Norbye3a2425a2013-11-04 10:16:08 -08001485def stoptrace():
1486 global connected
1487 if connected:
1488 pydevd_tracing.RestoreSysSetTraceFunc()
1489 sys.settrace(None)
1490 try:
1491 #not available in jython!
1492 threading.settrace(None) # for all future threads
1493 except:
1494 pass
1495
1496 try:
1497 thread.start_new_thread = _original_start_new_thread
1498 thread.start_new = _original_start_new_thread
1499 except:
1500 pass
1501
1502 debugger = GetGlobalDebugger()
1503
1504 if debugger:
1505 debugger.trace_dispatch = None
1506
1507 debugger.SetTraceForFrameAndParents(GetFrame(), False)
1508
1509 debugger.exiting()
1510
1511 killAllPydevThreads()
1512
1513 connected = False
1514
1515class Dispatcher(object):
1516 def __init__(self):
1517 self.port = None
1518
1519 def connect(self, host, port):
1520 self.host = host
1521 self.port = port
1522 self.client = StartClient(self.host, self.port)
1523 self.reader = DispatchReader(self)
1524 self.reader.dontTraceMe = False #we run reader in the same thread so we don't want to loose tracing
1525 self.reader.run()
1526
1527 def close(self):
1528 try:
1529 self.reader.doKillPydevThread()
1530 except :
1531 pass
1532
1533class DispatchReader(ReaderThread):
1534 def __init__(self, dispatcher):
1535 self.dispatcher = dispatcher
1536 ReaderThread.__init__(self, self.dispatcher.client)
1537
1538 def handleExcept(self):
1539 ReaderThread.handleExcept(self)
1540
1541 def processCommand(self, cmd_id, seq, text):
1542 if cmd_id == 99:
1543 self.dispatcher.port = int(text)
1544 self.killReceived = True
1545
1546
1547def dispatch():
1548 argv = sys.original_argv[:]
1549 setup = processCommandLine(argv)
1550 host = setup['client']
1551 port = setup['port']
1552 dispatcher = Dispatcher()
1553 try:
1554 dispatcher.connect(host, port)
1555 port = dispatcher.port
1556 finally:
1557 dispatcher.close()
1558 return host, port
1559
1560
1561def settrace_forked():
1562 host, port = dispatch()
1563
1564 import pydevd_tracing
1565 pydevd_tracing.RestoreSysSetTraceFunc()
1566
1567 if port is not None:
1568 global connected
1569 connected = False
Tor Norbyec667c1f2014-05-28 17:06:51 -07001570
1571 CustomFramesContainerInit()
1572
1573 settrace(
1574 host,
1575 port=port,
1576 suspend=False,
1577 trace_only_current_thread=False,
1578 overwrite_prev_trace=True,
1579 patch_multiprocessing=True,
1580 )
Tor Norbye3a2425a2013-11-04 10:16:08 -08001581#=======================================================================================================================
1582# main
1583#=======================================================================================================================
1584if __name__ == '__main__':
1585 # parse the command line. --file is our last argument that is required
1586 try:
1587 sys.original_argv = sys.argv[:]
1588 setup = processCommandLine(sys.argv)
1589 except ValueError:
1590 traceback.print_exc()
1591 usage(1)
1592
1593
Tor Norbye3a2425a2013-11-04 10:16:08 -08001594 fix_getpass.fixGetpass()
1595
Tor Norbye3a2425a2013-11-04 10:16:08 -08001596 pydev_log.debug("Executing file %s" % setup['file'])
1597 pydev_log.debug("arguments: %s"% str(sys.argv))
1598
1599
1600 pydevd_vm_type.SetupType(setup.get('vm_type', None))
1601
1602 if os.getenv('PYCHARM_DEBUG'):
1603 set_debug(setup)
1604
1605 DebugInfoHolder.DEBUG_RECORD_SOCKET_READS = setup.get('DEBUG_RECORD_SOCKET_READS', False)
1606 DebugInfoHolder.DEBUG_TRACE_BREAKPOINTS = setup.get('DEBUG_TRACE_BREAKPOINTS', -1)
1607 DebugInfoHolder.DEBUG_TRACE_LEVEL = setup.get('DEBUG_TRACE_LEVEL', -1)
1608
1609 port = setup['port']
1610 host = setup['client']
Tor Norbyec667c1f2014-05-28 17:06:51 -07001611 f = setup['file']
1612 fix_app_engine_debug = False
Tor Norbye3a2425a2013-11-04 10:16:08 -08001613
1614 if setup['multiproc']:
1615 pydev_log.debug("Started in multiproc mode\n")
1616
1617 dispatcher = Dispatcher()
1618 try:
1619 dispatcher.connect(host, port)
1620 if dispatcher.port is not None:
1621 port = dispatcher.port
1622 pydev_log.debug("Received port %d\n" %port)
1623 pydev_log.info("pydev debugger: process %d is connecting\n"% os.getpid())
1624
1625 try:
1626 pydev_monkey.patch_new_process_functions()
1627 except:
1628 pydev_log.error("Error patching process functions\n")
1629 traceback.print_exc()
1630 else:
1631 pydev_log.error("pydev debugger: couldn't get port for new debug process\n")
1632 finally:
1633 dispatcher.close()
1634 else:
1635 pydev_log.info("pydev debugger: starting\n")
1636
1637 try:
1638 pydev_monkey.patch_new_process_functions_with_warning()
1639 except:
1640 pydev_log.error("Error patching process functions\n")
1641 traceback.print_exc()
1642
Tor Norbyec667c1f2014-05-28 17:06:51 -07001643 # Only do this patching if we're not running with multiprocess turned on.
1644 if f.find('dev_appserver.py') != -1:
1645 if os.path.basename(f).startswith('dev_appserver.py'):
1646 appserver_dir = os.path.dirname(f)
1647 version_file = os.path.join(appserver_dir, 'VERSION')
1648 if os.path.exists(version_file):
1649 try:
1650 stream = open(version_file, 'r')
1651 try:
1652 for line in stream.read().splitlines():
1653 line = line.strip()
1654 if line.startswith('release:'):
1655 line = line[8:].strip()
1656 version = line.replace('"', '')
1657 version = version.split('.')
1658 if int(version[0]) > 1:
1659 fix_app_engine_debug = True
1660
1661 elif int(version[0]) == 1:
1662 if int(version[1]) >= 7:
1663 # Only fix from 1.7 onwards
1664 fix_app_engine_debug = True
1665 break
1666 finally:
1667 stream.close()
1668 except:
1669 traceback.print_exc()
1670
1671 try:
1672 # In the default run (i.e.: run directly on debug mode), we try to patch stackless as soon as possible
1673 # on a run where we have a remote debug, we may have to be more careful because patching stackless means
1674 # that if the user already had a stackless.set_schedule_callback installed, he'd loose it and would need
1675 # to call it again (because stackless provides no way of getting the last function which was registered
1676 # in set_schedule_callback).
1677 #
1678 # So, ideally, if there's an application using stackless and the application wants to use the remote debugger
1679 # and benefit from stackless debugging, the application itself must call:
1680 #
1681 # import pydevd_stackless
1682 # pydevd_stackless.patch_stackless()
1683 #
1684 # itself to be able to benefit from seeing the tasklets created before the remote debugger is attached.
1685 import pydevd_stackless
1686 pydevd_stackless.patch_stackless()
1687 except:
1688 pass # It's ok not having stackless there...
1689
1690 if fix_app_engine_debug:
1691 sys.stderr.write("pydev debugger: google app engine integration enabled\n")
1692 curr_dir = os.path.dirname(__file__)
1693 app_engine_startup_file = os.path.join(curr_dir, 'pydev_app_engine_debug_startup.py')
1694
1695 sys.argv.insert(1, '--python_startup_script=' + app_engine_startup_file)
1696 import json
1697 setup['pydevd'] = __file__
1698 sys.argv.insert(2, '--python_startup_args=%s' % json.dumps(setup),)
1699 sys.argv.insert(3, '--automatic_restart=no')
1700 sys.argv.insert(4, '--max_module_instances=1')
1701
1702 debugger = PyDB()
1703 # Run the dev_appserver
1704 debugger.run(setup['file'], None, None, set_trace=False)
1705
1706 else:
1707 # as to get here all our imports are already resolved, the psyco module can be
1708 # changed and we'll still get the speedups in the debugger, as those functions
1709 # are already compiled at this time.
1710 try:
1711 import psyco
1712 except ImportError:
1713 if hasattr(sys, 'exc_clear'): # jython does not have it
1714 sys.exc_clear() # don't keep the traceback -- clients don't want to see it
1715 pass # that's ok, no need to mock psyco if it's not available anyways
1716 else:
1717 # if it's available, let's change it for a stub (pydev already made use of it)
1718 import pydevd_psyco_stub
1719 sys.modules['psyco'] = pydevd_psyco_stub
Tor Norbye3a2425a2013-11-04 10:16:08 -08001720
1721 debugger = PyDB()
1722
1723 if setup['save-signatures']:
1724 if pydevd_vm_type.GetVmType() == pydevd_vm_type.PydevdVmType.JYTHON:
1725 sys.stderr.write("Collecting run-time type information is not supported for Jython\n")
1726 else:
1727 debugger.signature_factory = SignatureFactory()
1728
1729 debugger.connect(host, port)
1730
1731 connected = True #Mark that we're connected when started from inside ide.
1732
1733 debugger.run(setup['file'], None, None)