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