DebugClients/Ruby/Debuggee.rb

changeset 2438
61bfcff921d8
parent 2302
f29e9405c851
child 2623
3e5b1e3a71f5
equal deleted inserted replaced
2436:f75dbdd22959 2438:61bfcff921d8
15 15
16 =begin edoc 16 =begin edoc
17 File implementing the real debugger, which is connected to the IDE frontend. 17 File implementing the real debugger, which is connected to the IDE frontend.
18 =end 18 =end
19 19
20 require 'continuation'
21
20 require 'DebugQuit' 22 require 'DebugQuit'
21 require 'rbconfig' 23 require 'rbconfig'
22 24
23 class DEBUGGER__ 25 class DEBUGGER__
24 =begin edoc 26 =begin edoc
25 Class implementing the real debugger. 27 Class implementing the real debugger.
26 =end 28 =end
27 class Mutex
28 =begin edoc
29 Class implementing a mutex.
30 =end
31 def initialize
32 =begin edoc
33 Constructor
34 =end
35 @locker = nil
36 @waiting = []
37 @locked = false;
38 end
39
40 def locked?
41 =begin edoc
42 Method returning the locked state.
43
44 @return flag indicating the locked state (boolean)
45 =end
46 @locked
47 end
48
49 def lock
50 =begin edoc
51 Method to lock the mutex.
52
53 @return the mutex
54 =end
55 return if @locker == Thread.current
56 while (Thread.critical = true; @locked)
57 @waiting.push Thread.current
58 Thread.stop
59 end
60 @locked = true
61 @locker = Thread.current
62 Thread.critical = false
63 self
64 end
65
66 def unlock
67 =begin edoc
68 Method to unlock the mutex.
69
70 @return the mutex
71 =end
72 return unless @locked
73 unless @locker == Thread.current
74 raise RuntimeError, "unlocked by other"
75 end
76 Thread.critical = true
77 t = @waiting.shift
78 @locked = false
79 @locker = nil
80 Thread.critical = false
81 t.run if t
82 self
83 end
84 end
85 MUTEX = Mutex.new 29 MUTEX = Mutex.new
86 30
87 class Context 31 class Context
88 =begin edoc 32 =begin edoc
89 Class defining the current execution context. 33 Class defining the current execution context.
184 128
185 def check_suspend 129 def check_suspend
186 =begin edoc 130 =begin edoc
187 Method to check the suspend state. 131 Method to check the suspend state.
188 =end 132 =end
189 while (Thread.critical = true; @suspend_next) 133 while MUTEX.synchronize {
190 DEBUGGER__.waiting.push Thread.current 134 if @suspend_next
191 @suspend_next = false 135 DEBUGGER__.waiting.push Thread.current
192 Thread.stop 136 @suspend_next = false
193 end 137 true
194 Thread.critical = false 138 end
139 }
140 end
195 end 141 end
196 142
197 def stdout 143 def stdout
198 =begin edoc 144 =begin edoc
199 Method returning the stdout object. 145 Method returning the stdout object.
313 # bp[5] condition 259 # bp[5] condition
314 # bp[6] ignore count 260 # bp[6] ignore count
315 # bp[7] special condition 261 # bp[7] special condition
316 # bp[8] hash of special values 262 # bp[8] hash of special values
317 return false if break_points.empty? 263 return false if break_points.empty?
318 for b in break_points 264 break_points.each do |b|
319 if b[0] 265 if b[0]
320 if b[1] == 0 and b[2] == file and b[3] == pos # breakpoint 266 if b[1] == 0 and b[2] == file and b[3] == pos # breakpoint
321 # Evaluate condition 267 # Evaluate condition
322 if b[5] 268 if b[5]
323 begin 269 begin
439 385
440 @param file filename of the breakpoint (String) 386 @param file filename of the breakpoint (String)
441 @param pos line number of the breakpoint (int) 387 @param pos line number of the breakpoint (int)
442 @param enable flag indicating the new enabled state (boolean) 388 @param enable flag indicating the new enabled state (boolean)
443 =end 389 =end
444 for bp in break_points 390 break_points.each do |bp|
445 if (bp[1] == 0 and bp[2] == file and bp[3] == pos) 391 if (bp[1] == 0 and bp[2] == file and bp[3] == pos)
446 bp[0] = enable 392 bp[0] = enable
447 break 393 break
448 end 394 end
449 end 395 end
455 401
456 @param file filename of the breakpoint (String) 402 @param file filename of the breakpoint (String)
457 @param pos line number of the breakpoint (int) 403 @param pos line number of the breakpoint (int)
458 @param count ignore count to be set (int) 404 @param count ignore count to be set (int)
459 =end 405 =end
460 for bp in break_points 406 break_points.each do |bp|
461 if (bp[2] == file and bp[3] == pos) 407 if (bp[2] == file and bp[3] == pos)
462 bp[6] = count 408 bp[6] = count
463 break 409 break
464 end 410 end
465 end 411 end
506 Method to set the enabled state of a watch expression. 452 Method to set the enabled state of a watch expression.
507 453
508 @param cond expression of the watch expression (String) 454 @param cond expression of the watch expression (String)
509 @param enable flag indicating the new enabled state (boolean) 455 @param enable flag indicating the new enabled state (boolean)
510 =end 456 =end
511 for bp in break_points 457 break_points.each do |bp|
512 if (bp[1] == 1 and bp[2] == cond) 458 if (bp[1] == 1 and bp[2] == cond)
513 bp[0] = enable 459 bp[0] = enable
514 break 460 break
515 end 461 end
516 end 462 end
521 Method to set the ignore count of a watch expression. 467 Method to set the ignore count of a watch expression.
522 468
523 @param cond expression of the watch expression (String) 469 @param cond expression of the watch expression (String)
524 @param count ignore count to be set (int) 470 @param count ignore count to be set (int)
525 =end 471 =end
526 for bp in break_points 472 break_points.each do |bp|
527 if (bp[1] == 1 and bp[2] == cond) 473 if (bp[1] == 1 and bp[2] == cond)
528 bp[6] = count 474 bp[6] = count
529 break 475 break
530 end 476 end
531 end 477 end
574 if file =~ /\(eval\)/ 520 if file =~ /\(eval\)/
575 return true 521 return true
576 end 522 end
577 523
578 if not traceRuby? and 524 if not traceRuby? and
579 (file =~ /#{Config::CONFIG['sitelibdir']}/ or 525 (file =~ /#{RbConfig::CONFIG['sitelibdir']}/ or
580 file =~ /#{Config::CONFIG['rubylibdir']}/) 526 file =~ /#{RbConfig::CONFIG['rubylibdir']}/)
581 return true 527 return true
582 end 528 end
583 529
584 if ["AsyncFile.rb", "AsyncIO.rb", "Config.rb", "DebugClient.rb", 530 if ["AsyncFile.rb", "AsyncIO.rb", "Config.rb", "DebugClient.rb",
585 "DebugClientBaseModule.rb", "DebugClientCapabilities.rb", 531 "DebugClientBaseModule.rb", "DebugClientCapabilities.rb",
618 @frames.unshift [binding_, file, line, id] 564 @frames.unshift [binding_, file, line, id]
619 565
620 when 'return', 'end' 566 when 'return', 'end'
621 @frames.shift 567 @frames.shift
622 568
623 when 'end'
624 @frames.shift
625
626 when 'raise' 569 when 'raise'
627 excn_handle(file, line, id, binding_) 570 excn_handle(file, line, id, binding_)
628 571
629 end 572 end
630 @last_file = file 573 @last_file = file
660 debug_command(file, line, id, binding_) 603 debug_command(file, line, id, binding_)
661 end 604 end
662 605
663 when 'c-call' 606 when 'c-call'
664 frame_set_pos(file, line) 607 frame_set_pos(file, line)
665 if id == :require and klass == Kernel 608 ## if id == :require and klass == Kernel
666 @frames.unshift [binding_, file, line, id] 609 ## @frames.unshift [binding_, file, line, id]
667 else 610 ## else
668 frame_set_pos(file, line) 611 ## frame_set_pos(file, line)
669 end 612 ## end
670 613 ##
671 when 'c-return' 614 ## when 'c-return'
672 if id == :require and klass == Kernel 615 ## if id == :require and klass == Kernel
673 if @frames.size == @finish_pos 616 ## if @frames.size == @finish_pos
674 @stop_next = 1 617 ## @stop_next = 1
675 @finish_pos = 0 618 ## @finish_pos = 0
676 end 619 ## end
677 @frames.shift 620 ## @frames.shift
678 end 621 ## end
679 622
680 when 'class' 623 when 'class'
681 @frames.unshift [binding_, file, line, id] 624 @frames.unshift [binding_, file, line, id]
682 625
683 when 'return', 'end' 626 when 'return', 'end'
684 if @frames.size == @finish_pos 627 if @frames.size == @finish_pos
685 @stop_next = 1 628 @stop_next = 1
686 @finish_pos = 0 629 @finish_pos = 0
687 end 630 end
688 @frames.shift
689
690 when 'end'
691 @frames.shift 631 @frames.shift
692 632
693 when 'raise' 633 when 'raise'
694 @no_step = nil 634 @no_step = nil
695 @stop_next = 0 # break here before leaving... 635 @stop_next = 0 # break here before leaving...
841 781
842 def suspend 782 def suspend
843 =begin edoc 783 =begin edoc
844 Method to suspend the program being debugged. 784 Method to suspend the program being debugged.
845 =end 785 =end
846 Thread.critical = true 786 MUTEX.synchronize do
847 make_thread_list 787 make_thread_list
848 for th, in @thread_list 788 for th, in @thread_list
849 next if th == Thread.current 789 next if th == Thread.current
850 context(th).set_suspend 790 context(th).set_suspend
851 end 791 end
852 Thread.critical = false 792 end
853 # Schedule other threads to suspend as soon as possible. 793 # Schedule other threads to suspend as soon as possible.
854 Thread.pass 794 Thread.pass
855 end 795 end
856 796
857 def resume 797 def resume
858 =begin edoc 798 =begin edoc
859 Method to resume the program being debugged. 799 Method to resume the program being debugged.
860 =end 800 =end
861 Thread.critical = true 801 MUTEX.synchronize do
862 make_thread_list 802 make_thread_list
863 for th, in @thread_list 803 for th, in @thread_list
864 next if th == Thread.current 804 next if th == Thread.current
865 context(th).clear_suspend 805 context(th).clear_suspend
866 end 806 end
867 waiting.each do |th| 807 waiting.each do |th|
868 th.run 808 th.run
869 end 809 end
870 waiting.clear 810 waiting.clear
871 Thread.critical = false 811 end
872 # Schedule other threads to restart as soon as possible. 812 # Schedule other threads to restart as soon as possible.
873 Thread.pass 813 Thread.pass
874 end 814 end
875 815
876 def context(thread=Thread.current) 816 def context(thread=Thread.current)
899 Method returning a thread by number. 839 Method returning a thread by number.
900 840
901 @param num thread number (int) 841 @param num thread number (int)
902 @return thread with the requested number 842 @return thread with the requested number
903 =end 843 =end
904 th = @thread_list.index(num) 844 th = @thread_list.key(num)
905 unless th 845 unless th
906 @stdout.print "No thread ##{num}\n" 846 @stdout.print "No thread ##{num}\n"
907 throw :debug_error 847 throw :debug_error
908 end 848 end
909 th 849 th

eric ide

mercurial