blob: f7bfb322c7d509292b00ffaf5806d033ed4f3857 [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
2from django_debug import DjangoLineBreakpoint
3from pydevd_signature import SignatureFactory
4from pydevd_frame import add_exception_to_frame
Tor Norbye3a2425a2013-11-04 10:16:08 -08005import pydev_imports
6from pydevd_breakpoints import * #@UnusedWildImport
7import fix_getpass
8
9from pydevd_comm import CMD_CHANGE_VARIABLE, \
10 CMD_EVALUATE_EXPRESSION, \
11 CMD_EXEC_EXPRESSION, \
12 CMD_GET_COMPLETIONS, \
13 CMD_GET_FRAME, \
14 CMD_GET_VARIABLE, \
15 CMD_LIST_THREADS, \
16 CMD_REMOVE_BREAK, \
17 CMD_RUN, \
18 CMD_SET_BREAK, \
19 CMD_SET_NEXT_STATEMENT,\
20 CMD_STEP_INTO, \
21 CMD_STEP_OVER, \
22 CMD_STEP_RETURN, \
23 CMD_THREAD_CREATE, \
24 CMD_THREAD_KILL, \
25 CMD_THREAD_RUN, \
26 CMD_THREAD_SUSPEND, \
27 CMD_RUN_TO_LINE, \
28 CMD_RELOAD_CODE, \
29 CMD_VERSION, \
30 CMD_CONSOLE_EXEC, \
31 CMD_ADD_EXCEPTION_BREAK, \
32 CMD_REMOVE_EXCEPTION_BREAK, \
33 CMD_LOAD_SOURCE, \
34 CMD_ADD_DJANGO_EXCEPTION_BREAK, \
35 CMD_REMOVE_DJANGO_EXCEPTION_BREAK, \
36 CMD_SMART_STEP_INTO,\
37 InternalChangeVariable, \
38 InternalGetCompletions, \
39 InternalEvaluateExpression, \
40 InternalConsoleExec, \
41 InternalGetFrame, \
42 InternalGetVariable, \
43 InternalTerminateThread, \
44 InternalRunThread, \
45 InternalStepThread, \
46 NetCommand, \
47 NetCommandFactory, \
48 PyDBDaemonThread, \
49 _queue, \
50 ReaderThread, \
51 SetGlobalDebugger, \
52 WriterThread, \
53 PydevdFindThreadById, \
54 PydevdLog, \
55 StartClient, \
56 StartServer, \
57 InternalSetNextStatementThread
58
59from pydevd_file_utils import NormFileToServer, GetFilenameAndBase
60import pydevd_file_utils
61import pydevd_vars
62import traceback
63import pydevd_vm_type
64import pydevd_tracing
65import pydevd_io
66import pydev_monkey
67from pydevd_additional_thread_info import PyDBAdditionalThreadInfo
68
69if USE_LIB_COPY:
70 import _pydev_time as time
71 import _pydev_threading as threading
72else:
73 import time
74 import threading
75
76import os
77
78
79threadingEnumerate = threading.enumerate
80threadingCurrentThread = threading.currentThread
81
82
83DONT_TRACE = {
84 #commonly used things from the stdlib that we don't want to trace
85 'threading.py':1,
86 'Queue.py':1,
87 'queue.py':1,
88 'socket.py':1,
89
90 #things from pydev that we don't want to trace
91 'pydevd_additional_thread_info.py':1,
92 'pydevd_comm.py':1,
93 'pydevd_constants.py':1,
94 'pydevd_exec.py':1,
95 'pydevd_exec2.py':1,
96 'pydevd_file_utils.py':1,
97 'pydevd_frame.py':1,
98 'pydevd_io.py':1 ,
99 'pydevd_resolver.py':1 ,
100 'pydevd_tracing.py':1 ,
101 'pydevd_signature.py':1,
102 'pydevd_utils.py':1,
103 'pydevd_vars.py':1,
104 'pydevd_vm_type.py':1,
105 'pydevd.py':1 ,
106 'pydevd_psyco_stub.py':1,
107 '_pydev_execfile.py':1,
108 '_pydev_jython_execfile.py':1
109 }
110
111if IS_PY3K:
112 #if we try to trace io.py it seems it can get halted (see http://bugs.python.org/issue4716)
113 DONT_TRACE['io.py'] = 1
114
115
116connected = False
117bufferStdOutToServer = False
118bufferStdErrToServer = False
119remote = False
120
121PyDBUseLocks = True
122
123
124#=======================================================================================================================
125# PyDBCommandThread
126#=======================================================================================================================
127class PyDBCommandThread(PyDBDaemonThread):
128
129 def __init__(self, pyDb):
130 PyDBDaemonThread.__init__(self)
131 self.pyDb = pyDb
132 self.setName('pydevd.CommandThread')
133
134 def OnRun(self):
135 for i in range(1, 10):
136 time.sleep(0.5) #this one will only start later on (because otherwise we may not have any non-daemon threads
137 if self.killReceived:
138 return
139
140 if self.dontTraceMe:
141 self.pyDb.SetTrace(None) # no debugging on this thread
142
143 try:
144 while not self.killReceived:
145 try:
146 self.pyDb.processInternalCommands()
147 except:
148 PydevdLog(0, 'Finishing debug communication...(2)')
149 time.sleep(0.5)
150 except:
151 pydev_log.debug(sys.exc_info()[0])
152
153 #only got this error in interpreter shutdown
154 #PydevdLog(0, 'Finishing debug communication...(3)')
155
156
157def killAllPydevThreads():
158 threads = threadingEnumerate()
159 for t in threads:
160 if hasattr(t, 'doKillPydevThread'):
161 t.doKillPydevThread()
162
163
164#=======================================================================================================================
165# PyDBCheckAliveThread
166#=======================================================================================================================
167class PyDBCheckAliveThread(PyDBDaemonThread):
168
169 def __init__(self, pyDb):
170 PyDBDaemonThread.__init__(self)
171 self.pyDb = pyDb
172 self.setDaemon(False)
173 self.setName('pydevd.CheckAliveThread')
174
175 def OnRun(self):
176 if self.dontTraceMe:
177 self.pyDb.SetTrace(None) # no debugging on this thread
178 while not self.killReceived:
179 if not self.pyDb.haveAliveThreads():
180 try:
181 pydev_log.debug("No alive threads, finishing debug session")
182 self.pyDb.FinishDebuggingSession()
183 killAllPydevThreads()
184 except:
185 traceback.print_exc()
186
187 self.stop()
188 self.killReceived = True
189 return
190
191 time.sleep(0.3)
192
193 def doKillPydevThread(self):
194 pass
195
196if USE_LIB_COPY:
197 import _pydev_thread as thread
198else:
199 try:
200 import thread
201 except ImportError:
202 import _thread as thread #Py3K changed it.
203
204_original_start_new_thread = thread.start_new_thread
205
206if getattr(thread, '_original_start_new_thread', None) is None:
207 thread._original_start_new_thread = thread.start_new_thread
208
209#=======================================================================================================================
210# NewThreadStartup
211#=======================================================================================================================
212class NewThreadStartup:
213
214 def __init__(self, original_func, args, kwargs):
215 self.original_func = original_func
216 self.args = args
217 self.kwargs = kwargs
218
219 def __call__(self):
220 global_debugger = GetGlobalDebugger()
221 global_debugger.SetTrace(global_debugger.trace_dispatch)
222 self.original_func(*self.args, **self.kwargs)
223
224thread.NewThreadStartup = NewThreadStartup
225
226#=======================================================================================================================
227# pydev_start_new_thread
228#=======================================================================================================================
229def _pydev_start_new_thread(function, args, kwargs={}):
230 '''
231 We need to replace the original thread.start_new_thread with this function so that threads started through
232 it and not through the threading module are properly traced.
233 '''
234 if USE_LIB_COPY:
235 import _pydev_thread as thread
236 else:
237 try:
238 import thread
239 except ImportError:
240 import _thread as thread #Py3K changed it.
241
242 return thread._original_start_new_thread(thread.NewThreadStartup(function, args, kwargs), ())
243
244class PydevStartNewThread(object):
245 def __get__(self, obj, type=None):
246 return self
247
248 def __call__(self, function, args, kwargs={}):
249 return _pydev_start_new_thread(function, args, kwargs)
250
251pydev_start_new_thread = PydevStartNewThread()
252
253#=======================================================================================================================
254# PyDB
255#=======================================================================================================================
256class PyDB:
257 """ Main debugging class
258 Lots of stuff going on here:
259
260 PyDB starts two threads on startup that connect to remote debugger (RDB)
261 The threads continuously read & write commands to RDB.
262 PyDB communicates with these threads through command queues.
263 Every RDB command is processed by calling processNetCommand.
264 Every PyDB net command is sent to the net by posting NetCommand to WriterThread queue
265
266 Some commands need to be executed on the right thread (suspend/resume & friends)
267 These are placed on the internal command queue.
268 """
269
270 RUNNING_THREAD_IDS = {} #this is a dict of thread ids pointing to thread ids. Whenever a command
271 #is passed to the java end that acknowledges that a thread was created,
272 #the thread id should be passed here -- and if at some time we do not find
273 #that thread alive anymore, we must remove it from this list and make
274 #the java side know that the thread was killed.
275
276 def __init__(self):
277 SetGlobalDebugger(self)
278 pydevd_tracing.ReplaceSysSetTraceFunc()
279 self.reader = None
280 self.writer = None
281 self.quitting = None
282 self.cmdFactory = NetCommandFactory()
283 self._cmd_queue = {} # the hash of Queues. Key is thread id, value is thread
284 self.breakpoints = {}
285 self.django_breakpoints = {}
286 self.exception_set = {}
287 self.always_exception_set = set()
288 self.django_exception_break = {}
289 self.readyToRun = False
290 self._main_lock = threading.Lock()
291 self._lock_running_thread_ids = threading.Lock()
292 self._finishDebuggingSession = False
293 self._terminationEventSent = False
294 self.force_post_mortem_stop = 0
295 self.signature_factory = None
296 self.SetTrace = pydevd_tracing.SetTrace
297
298 #this is a dict of thread ids pointing to thread ids. Whenever a command is passed to the java end that
299 #acknowledges that a thread was created, the thread id should be passed here -- and if at some time we do not
300 #find that thread alive anymore, we must remove it from this list and make the java side know that the thread
301 #was killed.
302 self._running_thread_ids = {}
303
304 def haveAliveThreads(self):
305 for t in threadingEnumerate():
306 if not isinstance(t, PyDBDaemonThread) and t.isAlive() and not t.isDaemon():
307 return True
308
309 return False
310
311 def FinishDebuggingSession(self):
312 self._finishDebuggingSession = True
313
314 def acquire(self):
315 if PyDBUseLocks:
316 self.lock.acquire()
317 return True
318
319 def release(self):
320 if PyDBUseLocks:
321 self.lock.release()
322 return True
323
324 def initializeNetwork(self, sock):
325 try:
326 sock.settimeout(None) # infinite, no timeouts from now on - jython does not have it
327 except:
328 pass
329 self.writer = WriterThread(sock)
330 self.reader = ReaderThread(sock)
331 self.writer.start()
332 self.reader.start()
333
334 time.sleep(0.1) # give threads time to start
335
336 def connect(self, host, port):
337 if host:
338 s = StartClient(host, port)
339 else:
340 s = StartServer(port)
341
342 self.initializeNetwork(s)
343
344
345 def getInternalQueue(self, thread_id):
346 """ returns internal command queue for a given thread.
347 if new queue is created, notify the RDB about it """
348 try:
349 return self._cmd_queue[thread_id]
350 except KeyError:
351 return self._cmd_queue.setdefault(thread_id, _queue.Queue()) #@UndefinedVariable
352
353
354 def postInternalCommand(self, int_cmd, thread_id):
355 """ if thread_id is *, post to all """
356 if thread_id == "*":
357 for k in self._cmd_queue.keys():
358 self._cmd_queue[k].put(int_cmd)
359
360 else:
361 queue = self.getInternalQueue(thread_id)
362 queue.put(int_cmd)
363
364 def checkOutputRedirect(self):
365 global bufferStdOutToServer
366 global bufferStdErrToServer
367
368 if bufferStdOutToServer:
369 initStdoutRedirect()
370 self.checkOutput(sys.stdoutBuf, 1) #@UndefinedVariable
371
372 if bufferStdErrToServer:
373 initStderrRedirect()
374 self.checkOutput(sys.stderrBuf, 2) #@UndefinedVariable
375
376 def checkOutput(self, out, outCtx):
377 '''Checks the output to see if we have to send some buffered output to the debug server
378
379 @param out: sys.stdout or sys.stderr
380 @param outCtx: the context indicating: 1=stdout and 2=stderr (to know the colors to write it)
381 '''
382
383 try:
384 v = out.getvalue()
385
386 if v:
387 self.cmdFactory.makeIoMessage(v, outCtx, self)
388 except:
389 traceback.print_exc()
390
391
392 def processInternalCommands(self):
393 '''This function processes internal commands
394 '''
395 curr_thread_id = GetThreadId(threadingCurrentThread())
396 program_threads_alive = {}
397 all_threads = threadingEnumerate()
398 program_threads_dead = []
399
400
401 self._main_lock.acquire()
402 try:
403
404 self.checkOutputRedirect()
405
406 self._lock_running_thread_ids.acquire()
407 try:
408 for t in all_threads:
409 thread_id = GetThreadId(t)
410
411 if not isinstance(t, PyDBDaemonThread) and t.isAlive():
412 program_threads_alive[thread_id] = t
413
414 if not DictContains(self._running_thread_ids, thread_id):
415 if not hasattr(t, 'additionalInfo'):
416 #see http://sourceforge.net/tracker/index.php?func=detail&aid=1955428&group_id=85796&atid=577329
417 #Let's create the additional info right away!
418 t.additionalInfo = PyDBAdditionalThreadInfo()
419 self._running_thread_ids[thread_id] = t
420 self.writer.addCommand(self.cmdFactory.makeThreadCreatedMessage(t))
421
422
423 queue = self.getInternalQueue(thread_id)
424 cmdsToReadd = [] #some commands must be processed by the thread itself... if that's the case,
425 #we will re-add the commands to the queue after executing.
426 try:
427 while True:
428 int_cmd = queue.get(False)
429 if int_cmd.canBeExecutedBy(curr_thread_id):
430 PydevdLog(2, "processing internal command ", str(int_cmd))
431 int_cmd.doIt(self)
432 else:
433 PydevdLog(2, "NOT processing internal command ", str(int_cmd))
434 cmdsToReadd.append(int_cmd)
435
436 except _queue.Empty: #@UndefinedVariable
437 for int_cmd in cmdsToReadd:
438 queue.put(int_cmd)
439 # this is how we exit
440
441
442 thread_ids = list(self._running_thread_ids.keys())
443 for tId in thread_ids:
444 if not DictContains(program_threads_alive, tId):
445 program_threads_dead.append(tId)
446 finally:
447 self._lock_running_thread_ids.release()
448
449 for tId in program_threads_dead:
450 try:
451 self.processThreadNotAlive(tId)
452 except:
453 sys.stderr.write('Error iterating through %s (%s) - %s\n' % (
454 program_threads_alive, program_threads_alive.__class__, dir(program_threads_alive)))
455 raise
456
457
458 if len(program_threads_alive) == 0:
459 self.FinishDebuggingSession()
460 for t in all_threads:
461 if hasattr(t, 'doKillPydevThread'):
462 t.doKillPydevThread()
463
464 finally:
465 self._main_lock.release()
466
467
468 def setTracingForUntracedContexts(self):
469 #Enable the tracing for existing threads (because there may be frames being executed that
470 #are currently untraced).
471 threads = threadingEnumerate()
472 for t in threads:
473 if not t.getName().startswith('pydevd.'):
474 #TODO: optimize so that we only actually add that tracing if it's in
475 #the new breakpoint context.
476 additionalInfo = None
477 try:
478 additionalInfo = t.additionalInfo
479 except AttributeError:
480 pass #that's ok, no info currently set
481
482 if additionalInfo is not None:
483 for frame in additionalInfo.IterFrames():
484 self.SetTraceForFrameAndParents(frame)
485 del frame
486
487
488 def processNetCommand(self, cmd_id, seq, text):
489 '''Processes a command received from the Java side
490
491 @param cmd_id: the id of the command
492 @param seq: the sequence of the command
493 @param text: the text received in the command
494
495 @note: this method is run as a big switch... after doing some tests, it's not clear whether changing it for
496 a dict id --> function call will have better performance result. A simple test with xrange(10000000) showed
497 that the gains from having a fast access to what should be executed are lost because of the function call in
498 a way that if we had 10 elements in the switch the if..elif are better -- but growing the number of choices
499 makes the solution with the dispatch look better -- so, if this gets more than 20-25 choices at some time,
500 it may be worth refactoring it (actually, reordering the ifs so that the ones used mostly come before
501 probably will give better performance).
502 '''
503
504 self._main_lock.acquire()
505 try:
506 try:
507 cmd = None
508 if cmd_id == CMD_RUN:
509 self.readyToRun = True
510
511 elif cmd_id == CMD_VERSION:
512 # response is version number
513 local_version, pycharm_os = text.split('\t', 1)
514
515 pydevd_file_utils.set_pycharm_os(pycharm_os)
516
517 cmd = self.cmdFactory.makeVersionMessage(seq)
518
519 elif cmd_id == CMD_LIST_THREADS:
520 # response is a list of threads
521 cmd = self.cmdFactory.makeListThreadsMessage(seq)
522
523 elif cmd_id == CMD_THREAD_KILL:
524 int_cmd = InternalTerminateThread(text)
525 self.postInternalCommand(int_cmd, text)
526
527 elif cmd_id == CMD_THREAD_SUSPEND:
528 #Yes, thread suspend is still done at this point, not through an internal command!
529 t = PydevdFindThreadById(text)
530 if t:
531 additionalInfo = None
532 try:
533 additionalInfo = t.additionalInfo
534 except AttributeError:
535 pass #that's ok, no info currently set
536
537 if additionalInfo is not None:
538 for frame in additionalInfo.IterFrames():
539 self.SetTraceForFrameAndParents(frame)
540 del frame
541
542 self.setSuspend(t, CMD_THREAD_SUSPEND)
543
544 elif cmd_id == CMD_THREAD_RUN:
545 t = PydevdFindThreadById(text)
546 if t:
547 thread_id = GetThreadId(t)
548 int_cmd = InternalRunThread(thread_id)
549 self.postInternalCommand(int_cmd, thread_id)
550
551 elif cmd_id == CMD_STEP_INTO or cmd_id == CMD_STEP_OVER or cmd_id == CMD_STEP_RETURN:
552 #we received some command to make a single step
553 t = PydevdFindThreadById(text)
554 if t:
555 thread_id = GetThreadId(t)
556 int_cmd = InternalStepThread(thread_id, cmd_id)
557 self.postInternalCommand(int_cmd, thread_id)
558
559 elif cmd_id == CMD_RUN_TO_LINE or cmd_id == CMD_SET_NEXT_STATEMENT or cmd_id == CMD_SMART_STEP_INTO:
560 #we received some command to make a single step
561 thread_id, line, func_name = text.split('\t', 2)
562 t = PydevdFindThreadById(thread_id)
563 if t:
564 int_cmd = InternalSetNextStatementThread(thread_id, cmd_id, line, func_name)
565 self.postInternalCommand(int_cmd, thread_id)
566
567
568 elif cmd_id == CMD_RELOAD_CODE:
569 #we received some command to make a reload of a module
570 module_name = text.strip()
571 from pydevd_reload import xreload
572 if not DictContains(sys.modules, module_name):
573 if '.' in module_name:
574 new_module_name = module_name.split('.')[-1]
575 if DictContains(sys.modules, new_module_name):
576 module_name = new_module_name
577
578 if not DictContains(sys.modules, module_name):
579 sys.stderr.write('pydev debugger: Unable to find module to reload: "'+module_name+'".\n')
580 sys.stderr.write('pydev debugger: This usually means you are trying to reload the __main__ module (which cannot be reloaded).\n')
581 sys.stderr.flush()
582
583 else:
584 sys.stderr.write('pydev debugger: Reloading: '+module_name+'\n')
585 sys.stderr.flush()
586 xreload(sys.modules[module_name])
587
588
589 elif cmd_id == CMD_CHANGE_VARIABLE:
590 #the text is: thread\tstackframe\tFRAME|GLOBAL\tattribute_to_change\tvalue_to_change
591 try:
592 thread_id, frame_id, scope, attr_and_value = text.split('\t', 3)
593
594 tab_index = attr_and_value.rindex('\t')
595 attr = attr_and_value[0:tab_index].replace('\t', '.')
596 value = attr_and_value[tab_index + 1:]
597 int_cmd = InternalChangeVariable(seq, thread_id, frame_id, scope, attr, value)
598 self.postInternalCommand(int_cmd, thread_id)
599
600 except:
601 traceback.print_exc()
602
603 elif cmd_id == CMD_GET_VARIABLE:
604 #we received some command to get a variable
605 #the text is: thread_id\tframe_id\tFRAME|GLOBAL\tattributes*
606 try:
607 thread_id, frame_id, scopeattrs = text.split('\t', 2)
608
609 if scopeattrs.find('\t') != -1: # there are attributes beyond scope
610 scope, attrs = scopeattrs.split('\t', 1)
611 else:
612 scope, attrs = (scopeattrs, None)
613
614 int_cmd = InternalGetVariable(seq, thread_id, frame_id, scope, attrs)
615 self.postInternalCommand(int_cmd, thread_id)
616
617 except:
618 traceback.print_exc()
619
620 elif cmd_id == CMD_GET_COMPLETIONS:
621 #we received some command to get a variable
622 #the text is: thread_id\tframe_id\tactivation token
623 try:
624 thread_id, frame_id, scope, act_tok = text.split('\t', 3)
625
626 int_cmd = InternalGetCompletions(seq, thread_id, frame_id, act_tok)
627 self.postInternalCommand(int_cmd, thread_id)
628
629 except:
630 traceback.print_exc()
631
632 elif cmd_id == CMD_GET_FRAME:
633 thread_id, frame_id, scope = text.split('\t', 2)
634
635 int_cmd = InternalGetFrame(seq, thread_id, frame_id)
636 self.postInternalCommand(int_cmd, thread_id)
637
638 elif cmd_id == CMD_SET_BREAK:
639 #func name: 'None': match anything. Empty: match global, specified: only method context.
640
641 #command to add some breakpoint.
642 # text is file\tline. Add to breakpoints dictionary
643 type, file, line, condition, expression = text.split('\t', 4)
644
645 if condition.startswith('**FUNC**'):
646 func_name, condition = condition.split('\t', 1)
647
648 #We must restore new lines and tabs as done in
649 #AbstractDebugTarget.breakpointAdded
650 condition = condition.replace("@_@NEW_LINE_CHAR@_@", '\n').\
651 replace("@_@TAB_CHAR@_@", '\t').strip()
652
653 func_name = func_name[8:]
654 else:
655 func_name = 'None' #Match anything if not specified.
656
657
658 file = NormFileToServer(file)
659
660 if not pydevd_file_utils.exists(file):
661 sys.stderr.write('pydev debugger: warning: trying to add breakpoint'\
662 ' to file that does not exist: %s (will have no effect)\n' % (file,))
663 sys.stderr.flush()
664
665 line = int(line)
666
667 if len(condition) <= 0 or condition is None or condition == "None":
668 condition = None
669
670 if len(expression) <= 0 or expression is None or expression == "None":
671 expression = None
672
673 if type == 'python-line':
674 breakpoint = LineBreakpoint(type, True, condition, func_name, expression)
675 breakpoint.add(self.breakpoints, file, line, func_name)
676 elif type == 'django-line':
677 breakpoint = DjangoLineBreakpoint(type, file, line, True, condition, func_name, expression)
678 breakpoint.add(self.django_breakpoints, file, line, func_name)
679 else:
680 raise NameError(type)
681
682 self.setTracingForUntracedContexts()
683
684 elif cmd_id == CMD_REMOVE_BREAK:
685 #command to remove some breakpoint
686 #text is file\tline. Remove from breakpoints dictionary
687 type, file, line = text.split('\t', 2)
688 file = NormFileToServer(file)
689 try:
690 line = int(line)
691 except ValueError:
692 pass
693
694 else:
695 found = False
696 try:
697 if type == 'django-line':
698 del self.django_breakpoints[file][line]
699 elif type == 'python-line':
700 del self.breakpoints[file][line] #remove the breakpoint in that line
701 else:
702 try:
703 del self.django_breakpoints[file][line]
704 found = True
705 except:
706 pass
707 try:
708 del self.breakpoints[file][line] #remove the breakpoint in that line
709 found = True
710 except:
711 pass
712
713 if DebugInfoHolder.DEBUG_TRACE_BREAKPOINTS > 0:
714 sys.stderr.write('Removed breakpoint:%s - %s\n' % (file, line))
715 sys.stderr.flush()
716 except KeyError:
717 found = False
718
719 if not found:
720 #ok, it's not there...
721 if DebugInfoHolder.DEBUG_TRACE_BREAKPOINTS > 0:
722 #Sometimes, when adding a breakpoint, it adds a remove command before (don't really know why)
723 sys.stderr.write("breakpoint not found: %s - %s\n" % (file, line))
724 sys.stderr.flush()
725
726 elif cmd_id == CMD_EVALUATE_EXPRESSION or cmd_id == CMD_EXEC_EXPRESSION:
727 #command to evaluate the given expression
728 #text is: thread\tstackframe\tLOCAL\texpression
729 thread_id, frame_id, scope, expression, trim = text.split('\t', 4)
730 int_cmd = InternalEvaluateExpression(seq, thread_id, frame_id, expression,
731 cmd_id == CMD_EXEC_EXPRESSION, int(trim) == 1)
732 self.postInternalCommand(int_cmd, thread_id)
733
734 elif cmd_id == CMD_CONSOLE_EXEC:
735 #command to exec expression in console, in case expression is only partially valid 'False' is returned
736 #text is: thread\tstackframe\tLOCAL\texpression
737
738 thread_id, frame_id, scope, expression = text.split('\t', 3)
739
740 int_cmd = InternalConsoleExec(seq, thread_id, frame_id, expression)
741 self.postInternalCommand(int_cmd, thread_id)
742
743 elif cmd_id == CMD_ADD_EXCEPTION_BREAK:
744 exception, notify_always, notify_on_terminate = text.split('\t', 2)
745
746 eb = ExceptionBreakpoint(exception, notify_always, notify_on_terminate)
747
748 self.exception_set[exception] = eb
749
750 if eb.notify_on_terminate:
751 update_exception_hook(self)
752 if DebugInfoHolder.DEBUG_TRACE_BREAKPOINTS > 0:
753 pydev_log.error("Exceptions to hook on terminate: %s\n" % (self.exception_set,))
754
755 if eb.notify_always:
756 self.always_exception_set.add(exception)
757 if DebugInfoHolder.DEBUG_TRACE_BREAKPOINTS > 0:
758 pydev_log.error("Exceptions to hook always: %s\n" % (self.always_exception_set,))
759 self.setTracingForUntracedContexts()
760
761 elif cmd_id == CMD_REMOVE_EXCEPTION_BREAK:
762 exception = text
763 try:
764 del self.exception_set[exception]
765 self.always_exception_set.remove(exception)
766 except:
767 pass
768 update_exception_hook(self)
769
770 elif cmd_id == CMD_LOAD_SOURCE:
771 path = text
772 try:
773 f = open(path, 'r')
774 source = f.read()
775 self.cmdFactory.makeLoadSourceMessage(seq, source, self)
776 except:
777 return self.cmdFactory.makeErrorMessage(seq, pydevd_tracing.GetExceptionTracebackStr())
778
779 elif cmd_id == CMD_ADD_DJANGO_EXCEPTION_BREAK:
780 exception = text
781
782 self.django_exception_break[exception] = True
783 self.setTracingForUntracedContexts()
784
785 elif cmd_id == CMD_REMOVE_DJANGO_EXCEPTION_BREAK:
786 exception = text
787
788 try:
789 del self.django_exception_break[exception]
790 except :
791 pass
792
793 else:
794 #I have no idea what this is all about
795 cmd = self.cmdFactory.makeErrorMessage(seq, "unexpected command " + str(cmd_id))
796
797 if cmd is not None:
798 self.writer.addCommand(cmd)
799 del cmd
800
801 except Exception:
802 traceback.print_exc()
803 cmd = self.cmdFactory.makeErrorMessage(seq,
804 "Unexpected exception in processNetCommand.\nInitial params: %s" % ((cmd_id, seq, text),))
805
806 self.writer.addCommand(cmd)
807 finally:
808 self._main_lock.release()
809
810 def processThreadNotAlive(self, threadId):
811 """ if thread is not alive, cancel trace_dispatch processing """
812 self._lock_running_thread_ids.acquire()
813 try:
814 thread = self._running_thread_ids.pop(threadId, None)
815 if thread is None:
816 return
817
818 wasNotified = thread.additionalInfo.pydev_notify_kill
819 if not wasNotified:
820 thread.additionalInfo.pydev_notify_kill = True
821
822 finally:
823 self._lock_running_thread_ids.release()
824
825 cmd = self.cmdFactory.makeThreadKilledMessage(threadId)
826 self.writer.addCommand(cmd)
827
828
829 def setSuspend(self, thread, stop_reason):
830 thread.additionalInfo.suspend_type = PYTHON_SUSPEND
831 thread.additionalInfo.pydev_state = STATE_SUSPEND
832 thread.stop_reason = stop_reason
833
834
835 def doWaitSuspend(self, thread, frame, event, arg): #@UnusedVariable
836 """ busy waits until the thread state changes to RUN
837 it expects thread's state as attributes of the thread.
838 Upon running, processes any outstanding Stepping commands.
839 """
840 self.processInternalCommands()
841
842 message = getattr(thread.additionalInfo, "message", None)
843
844 cmd = self.cmdFactory.makeThreadSuspendMessage(GetThreadId(thread), frame, thread.stop_reason, message)
845 self.writer.addCommand(cmd)
846
847 info = thread.additionalInfo
848
849 while info.pydev_state == STATE_SUSPEND and not self._finishDebuggingSession:
850 self.processInternalCommands()
851 time.sleep(0.01)
852
853 #process any stepping instructions
854 if info.pydev_step_cmd == CMD_STEP_INTO:
855 info.pydev_step_stop = None
856 info.pydev_smart_step_stop = None
857
858 elif info.pydev_step_cmd == CMD_STEP_OVER:
859 info.pydev_step_stop = frame
860 info.pydev_smart_step_stop = None
861 self.SetTraceForFrameAndParents(frame)
862
863 elif info.pydev_step_cmd == CMD_SMART_STEP_INTO:
864 self.SetTraceForFrameAndParents(frame)
865 info.pydev_step_stop = None
866 info.pydev_smart_step_stop = frame
867
868 elif info.pydev_step_cmd == CMD_RUN_TO_LINE or info.pydev_step_cmd == CMD_SET_NEXT_STATEMENT :
869 self.SetTraceForFrameAndParents(frame)
870
871 if event == 'line' or event == 'exception':
872 #If we're already in the correct context, we have to stop it now, because we can act only on
873 #line events -- if a return was the next statement it wouldn't work (so, we have this code
874 #repeated at pydevd_frame).
875 stop = False
876 curr_func_name = frame.f_code.co_name
877
878 #global context is set with an empty name
879 if curr_func_name in ('?', '<module>'):
880 curr_func_name = ''
881
882 if curr_func_name == info.pydev_func_name:
883 line = info.pydev_next_line
884 if frame.f_lineno == line:
885 stop = True
886 else :
887 if frame.f_trace is None:
888 frame.f_trace = self.trace_dispatch
889 frame.f_lineno = line
890 frame.f_trace = None
891 stop = True
892 if stop:
893 info.pydev_state = STATE_SUSPEND
894 self.doWaitSuspend(thread, frame, event, arg)
895 return
896
897
898 elif info.pydev_step_cmd == CMD_STEP_RETURN:
899 back_frame = frame.f_back
900 if back_frame is not None:
901 #steps back to the same frame (in a return call it will stop in the 'back frame' for the user)
902 info.pydev_step_stop = frame
903 self.SetTraceForFrameAndParents(frame)
904 else:
905 #No back frame?!? -- this happens in jython when we have some frame created from an awt event
906 #(the previous frame would be the awt event, but this doesn't make part of 'jython', only 'java')
907 #so, if we're doing a step return in this situation, it's the same as just making it run
908 info.pydev_step_stop = None
909 info.pydev_step_cmd = None
910 info.pydev_state = STATE_RUN
911
912 del frame
913 cmd = self.cmdFactory.makeThreadRunMessage(GetThreadId(thread), info.pydev_step_cmd)
914 self.writer.addCommand(cmd)
915
916
917 def handle_post_mortem_stop(self, additionalInfo, t):
918 pydev_log.debug("We are stopping in post-mortem\n")
919 self.force_post_mortem_stop -= 1
920 frame, frames_byid = additionalInfo.pydev_force_stop_at_exception
921 thread_id = GetThreadId(t)
922 pydevd_vars.addAdditionalFrameById(thread_id, frames_byid)
923 try:
924 try:
925 add_exception_to_frame(frame, additionalInfo.exception)
926 self.setSuspend(t, CMD_ADD_EXCEPTION_BREAK)
927 self.doWaitSuspend(t, frame, 'exception', None)
928 except:
929 pydev_log.error("We've got an error while stopping in post-mortem: %s\n"%sys.exc_info()[0])
930 finally:
931 additionalInfo.pydev_force_stop_at_exception = None
932 pydevd_vars.removeAdditionalFrameById(thread_id)
933
934 def trace_dispatch(self, frame, event, arg):
935 ''' This is the callback used when we enter some context in the debugger.
936
937 We also decorate the thread we are in with info about the debugging.
938 The attributes added are:
939 pydev_state
940 pydev_step_stop
941 pydev_step_cmd
942 pydev_notify_kill
943 '''
944 try:
945 if self._finishDebuggingSession and not self._terminationEventSent:
946 #that was not working very well because jython gave some socket errors
947 t = threadingCurrentThread()
948 try:
949 threads = threadingEnumerate()
950 for t in threads:
951 if hasattr(t, 'doKillPydevThread'):
952 t.doKillPydevThread()
953 except:
954 traceback.print_exc()
955 self._terminationEventSent = True
956 return None
957
958 filename, base = GetFilenameAndBase(frame)
959
960 is_file_to_ignore = DictContains(DONT_TRACE, base) #we don't want to debug threading or anything related to pydevd
961
962 if is_file_to_ignore:
963 return None
964
965 #print('trace_dispatch', base, frame.f_lineno, event, frame.f_code.co_name)
966 try:
967 #this shouldn't give an exception, but it could happen... (python bug)
968 #see http://mail.python.org/pipermail/python-bugs-list/2007-June/038796.html
969 #and related bug: http://bugs.python.org/issue1733757
970 t = threadingCurrentThread()
971 except:
972 frame.f_trace = self.trace_dispatch
973 return self.trace_dispatch
974
975 try:
976 additionalInfo = t.additionalInfo
977 if additionalInfo is None:
978 raise AttributeError()
979 except:
980 t.additionalInfo = PyDBAdditionalThreadInfo()
981 additionalInfo = t.additionalInfo
982
983 if additionalInfo is None:
984 return None
985
986 if additionalInfo.is_tracing:
987 f = frame
988 while f is not None:
989 fname, bs = GetFilenameAndBase(f)
990 if bs == 'pydevd_frame.py':
991 if 'trace_dispatch' == f.f_code.co_name:
992 return None #we don't wan't to trace code invoked from pydevd_frame.trace_dispatch
993 f = f.f_back
994
995 # if thread is not alive, cancel trace_dispatch processing
996 if not t.isAlive():
997 self.processThreadNotAlive(GetThreadId(t))
998 return None # suspend tracing
999
1000 if is_file_to_ignore:
1001 return None
1002
1003 #each new frame...
1004 return additionalInfo.CreateDbFrame((self, filename, additionalInfo, t, frame)).trace_dispatch(frame, event, arg)
1005
1006 except SystemExit:
1007 return None
1008
1009 except TypeError:
1010 return None
1011
1012 except Exception:
1013 #Log it
1014 if traceback is not None:
1015 #This can actually happen during the interpreter shutdown in Python 2.7
1016 traceback.print_exc()
1017 return None
1018
1019 if USE_PSYCO_OPTIMIZATION:
1020 try:
1021 import psyco
1022 trace_dispatch = psyco.proxy(trace_dispatch)
1023 processNetCommand = psyco.proxy(processNetCommand)
1024 processInternalCommands = psyco.proxy(processInternalCommands)
1025 doWaitSuspend = psyco.proxy(doWaitSuspend)
1026 getInternalQueue = psyco.proxy(getInternalQueue)
1027 except ImportError:
1028 if hasattr(sys, 'exc_clear'): #jython does not have it
1029 sys.exc_clear() #don't keep the traceback (let's keep it clear for when we go to the point of executing client code)
1030
1031 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"):
1032 sys.stderr.write("pydev debugger: warning: psyco not available for speedups (the debugger will still work correctly, but a bit slower)\n")
1033 sys.stderr.flush()
1034
1035
1036
1037 def SetTraceForFrameAndParents(self, frame, also_add_to_passed_frame=True, overwrite_prev=False):
1038 dispatch_func = self.trace_dispatch
1039
1040 if also_add_to_passed_frame:
1041 self.update_trace(frame, dispatch_func, overwrite_prev)
1042
1043 frame = frame.f_back
1044 while frame:
1045 self.update_trace(frame, dispatch_func, overwrite_prev)
1046
1047 frame = frame.f_back
1048 del frame
1049
1050 def update_trace(self, frame, dispatch_func, overwrite_prev):
1051 if frame.f_trace is None:
1052 frame.f_trace = dispatch_func
1053 else:
1054 if overwrite_prev:
1055 frame.f_trace = dispatch_func
1056 else:
1057 try:
1058 #If it's the trace_exception, go back to the frame trace dispatch!
1059 if frame.f_trace.im_func.__name__ == 'trace_exception':
1060 frame.f_trace = frame.f_trace.im_self.trace_dispatch
1061 except AttributeError:
1062 pass
1063 frame = frame.f_back
1064 del frame
1065
1066
1067
1068 def run(self, file, globals=None, locals=None):
1069
1070 if globals is None:
1071 #patch provided by: Scott Schlesier - when script is run, it does not
1072 #use globals from pydevd:
1073 #This will prevent the pydevd script from contaminating the namespace for the script to be debugged
1074
1075 #pretend pydevd is not the main module, and
1076 #convince the file to be debugged that it was loaded as main
1077 sys.modules['pydevd'] = sys.modules['__main__']
1078 sys.modules['pydevd'].__name__ = 'pydevd'
1079
1080 from imp import new_module
1081 m = new_module('__main__')
1082 sys.modules['__main__'] = m
Tor Norbye70ae6f22014-02-06 14:02:54 -08001083 if hasattr(sys.modules['pydevd'], '__loader__'):
1084 setattr(m, '__loader__', getattr(sys.modules['pydevd'], '__loader__'))
1085
Tor Norbye3a2425a2013-11-04 10:16:08 -08001086 m.__file__ = file
1087 globals = m.__dict__
1088 try:
1089 globals['__builtins__'] = __builtins__
1090 except NameError:
1091 pass #Not there on Jython...
1092
1093 if locals is None:
1094 locals = globals
1095
1096 #Predefined (writable) attributes: __name__ is the module's name;
1097 #__doc__ is the module's documentation string, or None if unavailable;
1098 #__file__ is the pathname of the file from which the module was loaded,
1099 #if it was loaded from a file. The __file__ attribute is not present for
1100 #C modules that are statically linked into the interpreter; for extension modules
1101 #loaded dynamically from a shared library, it is the pathname of the shared library file.
1102
1103
1104 #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
1105 #debug and run.
1106 if m.__file__.startswith(sys.path[0]):
1107 #print >> sys.stderr, 'Deleting: ', sys.path[0]
1108 del sys.path[0]
1109
1110 #now, the local directory has to be added to the pythonpath
1111 #sys.path.insert(0, os.getcwd())
1112 #Changed: it's not the local directory, but the directory of the file launched
1113 #The file being run ust be in the pythonpath (even if it was not before)
1114 sys.path.insert(0, os.path.split(file)[0])
1115
1116 # for completness, we'll register the pydevd.reader & pydevd.writer threads
1117 net = NetCommand(str(CMD_THREAD_CREATE), 0, '<xml><thread name="pydevd.reader" id="-1"/></xml>')
1118 self.writer.addCommand(net)
1119 net = NetCommand(str(CMD_THREAD_CREATE), 0, '<xml><thread name="pydevd.writer" id="-1"/></xml>')
1120 self.writer.addCommand(net)
1121
1122 pydevd_tracing.SetTrace(self.trace_dispatch)
1123 try:
1124 #not available in jython!
1125 threading.settrace(self.trace_dispatch) # for all future threads
1126 except:
1127 pass
1128
1129 try:
1130 thread.start_new_thread = pydev_start_new_thread
1131 thread.start_new = pydev_start_new_thread
1132 except:
1133 pass
1134
1135 while not self.readyToRun:
1136 time.sleep(0.1) # busy wait until we receive run command
1137
1138 PyDBCommandThread(debugger).start()
1139 PyDBCheckAliveThread(debugger).start()
1140
1141 if pydevd_vm_type.GetVmType() == pydevd_vm_type.PydevdVmType.JYTHON and sys.version_info[1] == 5 and sys.version_info[2] >= 3:
1142 from _pydev_jython_execfile import jython_execfile
1143 jython_execfile(sys.argv)
1144 else:
1145 pydev_imports.execfile(file, globals, locals) #execute the script
1146
1147 def exiting(self):
1148 sys.stdout.flush()
1149 sys.stderr.flush()
1150 self.checkOutputRedirect()
1151 cmd = self.cmdFactory.makeExitMessage()
1152 self.writer.addCommand(cmd)
1153
1154def set_debug(setup):
1155 setup['DEBUG_RECORD_SOCKET_READS'] = True
1156 setup['DEBUG_TRACE_BREAKPOINTS'] = 1
1157 setup['DEBUG_TRACE_LEVEL'] = 3
1158
1159
1160def processCommandLine(argv):
1161 """ parses the arguments.
1162 removes our arguments from the command line """
1163 setup = {}
1164 setup['client'] = ''
1165 setup['server'] = False
1166 setup['port'] = 0
1167 setup['file'] = ''
1168 setup['multiproc'] = False
1169 setup['save-signatures'] = False
1170 i = 0
1171 del argv[0]
1172 while (i < len(argv)):
1173 if (argv[i] == '--port'):
1174 del argv[i]
1175 setup['port'] = int(argv[i])
1176 del argv[i]
1177 elif (argv[i] == '--vm_type'):
1178 del argv[i]
1179 setup['vm_type'] = argv[i]
1180 del argv[i]
1181 elif (argv[i] == '--client'):
1182 del argv[i]
1183 setup['client'] = argv[i]
1184 del argv[i]
1185 elif (argv[i] == '--server'):
1186 del argv[i]
1187 setup['server'] = True
1188 elif (argv[i] == '--file'):
1189 del argv[i]
1190 setup['file'] = argv[i]
1191 i = len(argv) # pop out, file is our last argument
1192 elif (argv[i] == '--DEBUG_RECORD_SOCKET_READS'):
1193 del argv[i]
1194 setup['DEBUG_RECORD_SOCKET_READS'] = True
1195 elif (argv[i] == '--DEBUG'):
1196 del argv[i]
1197 set_debug(setup)
1198 elif (argv[i] == '--multiproc'):
1199 del argv[i]
1200 setup['multiproc'] = True
1201 elif (argv[i] == '--save-signatures'):
1202 del argv[i]
1203 setup['save-signatures'] = True
1204 else:
1205 raise ValueError("unexpected option " + argv[i])
1206 return setup
1207
1208def usage(doExit=0):
1209 sys.stdout.write('Usage:\n')
1210 sys.stdout.write('pydevd.py --port=N [(--client hostname) | --server] --file executable [file_options]\n')
1211 if doExit:
1212 sys.exit(0)
1213
1214def SetTraceForParents(frame, dispatch_func):
1215 frame = frame.f_back
1216 while frame:
1217 if frame.f_trace is None:
1218 frame.f_trace = dispatch_func
1219
1220 frame = frame.f_back
1221 del frame
1222
1223def exit_hook():
1224 debugger = GetGlobalDebugger()
1225 debugger.exiting()
1226
1227def initStdoutRedirect():
1228 if not getattr(sys, 'stdoutBuf', None):
1229 sys.stdoutBuf = pydevd_io.IOBuf()
1230 sys.stdout = pydevd_io.IORedirector(sys.stdout, sys.stdoutBuf) #@UndefinedVariable
1231
1232def initStderrRedirect():
1233 if not getattr(sys, 'stderrBuf', None):
1234 sys.stderrBuf = pydevd_io.IOBuf()
1235 sys.stderr = pydevd_io.IORedirector(sys.stderr, sys.stderrBuf) #@UndefinedVariable
1236
1237def settrace(host='localhost', stdoutToServer=False, stderrToServer=False, port=5678, suspend=True, trace_only_current_thread=False, overwrite_prev_trace=False):
1238 '''Sets the tracing function with the pydev debug function and initializes needed facilities.
1239
1240 @param host: the user may specify another host, if the debug server is not in the same machine
1241 @param stdoutToServer: when this is true, the stdout is passed to the debug server
1242 @param stderrToServer: when this is true, the stderr is passed to the debug server
1243 so that they are printed in its console and not in this process console.
1244 @param port: specifies which port to use for communicating with the server (note that the server must be started
1245 in the same port). @note: currently it's hard-coded at 5678 in the client
1246 @param suspend: whether a breakpoint should be emulated as soon as this function is called.
1247 @param trace_only_current_thread: determines if only the current thread will be traced or all future threads will also have the tracing enabled.
1248 '''
1249 _set_trace_lock.acquire()
1250 try:
1251 _locked_settrace(host, stdoutToServer, stderrToServer, port, suspend, trace_only_current_thread, overwrite_prev_trace)
1252 finally:
1253 _set_trace_lock.release()
1254
1255_set_trace_lock = threading.Lock()
1256
1257def _locked_settrace(host, stdoutToServer, stderrToServer, port, suspend, trace_only_current_thread, overwrite_prev_trace):
1258 if host is None:
1259 import pydev_localhost
1260 host = pydev_localhost.get_localhost()
1261
1262 global connected
1263 global bufferStdOutToServer
1264 global bufferStdErrToServer
1265 global remote
1266
1267 remote = True
1268
1269 if not connected :
1270 connected = True
1271 bufferStdOutToServer = stdoutToServer
1272 bufferStdErrToServer = stderrToServer
1273
1274 pydevd_vm_type.SetupType()
1275
1276 debugger = PyDB()
1277 debugger.connect(host, port)
1278
1279 net = NetCommand(str(CMD_THREAD_CREATE), 0, '<xml><thread name="pydevd.reader" id="-1"/></xml>')
1280 debugger.writer.addCommand(net)
1281 net = NetCommand(str(CMD_THREAD_CREATE), 0, '<xml><thread name="pydevd.writer" id="-1"/></xml>')
1282 debugger.writer.addCommand(net)
1283
1284 if bufferStdOutToServer:
1285 initStdoutRedirect()
1286
1287 if bufferStdErrToServer:
1288 initStderrRedirect()
1289
1290 debugger.SetTraceForFrameAndParents(GetFrame(), False, overwrite_prev=overwrite_prev_trace)
1291
1292 t = threadingCurrentThread()
1293 try:
1294 additionalInfo = t.additionalInfo
1295 except AttributeError:
1296 additionalInfo = PyDBAdditionalThreadInfo()
1297 t.additionalInfo = additionalInfo
1298
1299 while not debugger.readyToRun:
1300 time.sleep(0.1) # busy wait until we receive run command
1301
1302 if suspend:
1303 debugger.setSuspend(t, CMD_SET_BREAK)
1304
1305 #note that we do that through pydevd_tracing.SetTrace so that the tracing
1306 #is not warned to the user!
1307 pydevd_tracing.SetTrace(debugger.trace_dispatch)
1308
1309 if not trace_only_current_thread:
1310 #Trace future threads?
1311 try:
1312 #not available in jython!
1313 threading.settrace(debugger.trace_dispatch) # for all future threads
1314 except:
1315 pass
1316
1317 try:
1318 thread.start_new_thread = pydev_start_new_thread
1319 thread.start_new = pydev_start_new_thread
1320 except:
1321 pass
1322
1323 sys.exitfunc = exit_hook
1324
1325 PyDBCommandThread(debugger).start()
1326 PyDBCheckAliveThread(debugger).start()
1327
1328 else:
1329 #ok, we're already in debug mode, with all set, so, let's just set the break
1330 debugger = GetGlobalDebugger()
1331
1332 debugger.SetTraceForFrameAndParents(GetFrame(), False)
1333
1334 t = threadingCurrentThread()
1335 try:
1336 additionalInfo = t.additionalInfo
1337 except AttributeError:
1338 additionalInfo = PyDBAdditionalThreadInfo()
1339 t.additionalInfo = additionalInfo
1340
1341 pydevd_tracing.SetTrace(debugger.trace_dispatch)
1342
1343 if not trace_only_current_thread:
1344 #Trace future threads?
1345 try:
1346 #not available in jython!
1347 threading.settrace(debugger.trace_dispatch) # for all future threads
1348 except:
1349 pass
1350
1351 try:
1352 thread.start_new_thread = pydev_start_new_thread
1353 thread.start_new = pydev_start_new_thread
1354 except:
1355 pass
1356
1357 if suspend:
1358 debugger.setSuspend(t, CMD_SET_BREAK)
1359
1360def stoptrace():
1361 global connected
1362 if connected:
1363 pydevd_tracing.RestoreSysSetTraceFunc()
1364 sys.settrace(None)
1365 try:
1366 #not available in jython!
1367 threading.settrace(None) # for all future threads
1368 except:
1369 pass
1370
1371 try:
1372 thread.start_new_thread = _original_start_new_thread
1373 thread.start_new = _original_start_new_thread
1374 except:
1375 pass
1376
1377 debugger = GetGlobalDebugger()
1378
1379 if debugger:
1380 debugger.trace_dispatch = None
1381
1382 debugger.SetTraceForFrameAndParents(GetFrame(), False)
1383
1384 debugger.exiting()
1385
1386 killAllPydevThreads()
1387
1388 connected = False
1389
1390class Dispatcher(object):
1391 def __init__(self):
1392 self.port = None
1393
1394 def connect(self, host, port):
1395 self.host = host
1396 self.port = port
1397 self.client = StartClient(self.host, self.port)
1398 self.reader = DispatchReader(self)
1399 self.reader.dontTraceMe = False #we run reader in the same thread so we don't want to loose tracing
1400 self.reader.run()
1401
1402 def close(self):
1403 try:
1404 self.reader.doKillPydevThread()
1405 except :
1406 pass
1407
1408class DispatchReader(ReaderThread):
1409 def __init__(self, dispatcher):
1410 self.dispatcher = dispatcher
1411 ReaderThread.__init__(self, self.dispatcher.client)
1412
1413 def handleExcept(self):
1414 ReaderThread.handleExcept(self)
1415
1416 def processCommand(self, cmd_id, seq, text):
1417 if cmd_id == 99:
1418 self.dispatcher.port = int(text)
1419 self.killReceived = True
1420
1421
1422def dispatch():
1423 argv = sys.original_argv[:]
1424 setup = processCommandLine(argv)
1425 host = setup['client']
1426 port = setup['port']
1427 dispatcher = Dispatcher()
1428 try:
1429 dispatcher.connect(host, port)
1430 port = dispatcher.port
1431 finally:
1432 dispatcher.close()
1433 return host, port
1434
1435
1436def settrace_forked():
1437 host, port = dispatch()
1438
1439 import pydevd_tracing
1440 pydevd_tracing.RestoreSysSetTraceFunc()
1441
1442 if port is not None:
1443 global connected
1444 connected = False
1445 settrace(host, port=port, suspend=False, overwrite_prev_trace=True)
1446#=======================================================================================================================
1447# main
1448#=======================================================================================================================
1449if __name__ == '__main__':
1450 # parse the command line. --file is our last argument that is required
1451 try:
1452 sys.original_argv = sys.argv[:]
1453 setup = processCommandLine(sys.argv)
1454 except ValueError:
1455 traceback.print_exc()
1456 usage(1)
1457
1458
1459 #as to get here all our imports are already resolved, the psyco module can be
1460 #changed and we'll still get the speedups in the debugger, as those functions
1461 #are already compiled at this time.
1462 try:
1463 import psyco
1464 except ImportError:
1465 if hasattr(sys, 'exc_clear'): #jython does not have it
1466 sys.exc_clear() #don't keep the traceback -- clients don't want to see it
1467 pass #that's ok, no need to mock psyco if it's not available anyways
1468 else:
1469 #if it's available, let's change it for a stub (pydev already made use of it)
1470 import pydevd_psyco_stub
1471 sys.modules['psyco'] = pydevd_psyco_stub
1472
1473 fix_getpass.fixGetpass()
1474
1475
1476 pydev_log.debug("Executing file %s" % setup['file'])
1477 pydev_log.debug("arguments: %s"% str(sys.argv))
1478
1479
1480 pydevd_vm_type.SetupType(setup.get('vm_type', None))
1481
1482 if os.getenv('PYCHARM_DEBUG'):
1483 set_debug(setup)
1484
1485 DebugInfoHolder.DEBUG_RECORD_SOCKET_READS = setup.get('DEBUG_RECORD_SOCKET_READS', False)
1486 DebugInfoHolder.DEBUG_TRACE_BREAKPOINTS = setup.get('DEBUG_TRACE_BREAKPOINTS', -1)
1487 DebugInfoHolder.DEBUG_TRACE_LEVEL = setup.get('DEBUG_TRACE_LEVEL', -1)
1488
1489 port = setup['port']
1490 host = setup['client']
1491
1492 if setup['multiproc']:
1493 pydev_log.debug("Started in multiproc mode\n")
1494
1495 dispatcher = Dispatcher()
1496 try:
1497 dispatcher.connect(host, port)
1498 if dispatcher.port is not None:
1499 port = dispatcher.port
1500 pydev_log.debug("Received port %d\n" %port)
1501 pydev_log.info("pydev debugger: process %d is connecting\n"% os.getpid())
1502
1503 try:
1504 pydev_monkey.patch_new_process_functions()
1505 except:
1506 pydev_log.error("Error patching process functions\n")
1507 traceback.print_exc()
1508 else:
1509 pydev_log.error("pydev debugger: couldn't get port for new debug process\n")
1510 finally:
1511 dispatcher.close()
1512 else:
1513 pydev_log.info("pydev debugger: starting\n")
1514
1515 try:
1516 pydev_monkey.patch_new_process_functions_with_warning()
1517 except:
1518 pydev_log.error("Error patching process functions\n")
1519 traceback.print_exc()
1520
1521
1522 debugger = PyDB()
1523
1524 if setup['save-signatures']:
1525 if pydevd_vm_type.GetVmType() == pydevd_vm_type.PydevdVmType.JYTHON:
1526 sys.stderr.write("Collecting run-time type information is not supported for Jython\n")
1527 else:
1528 debugger.signature_factory = SignatureFactory()
1529
1530 debugger.connect(host, port)
1531
1532 connected = True #Mark that we're connected when started from inside ide.
1533
1534 debugger.run(setup['file'], None, None)