ruby-debug 0.4.2 → 0.4.3

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES CHANGED
@@ -1,3 +1,7 @@
1
+ 0.4.3
2
+ - Added Debugger.skip method which allows escaping a block from the debugger reach.
3
+ - Bugfixes.
4
+
1
5
  0.4.2
2
6
  - Module#deubg_method added.
3
7
  - Added rdoc.
data/Rakefile CHANGED
@@ -5,7 +5,7 @@ require 'rake/rdoctask'
5
5
  SO_NAME = "ruby_debug.so"
6
6
 
7
7
  # ------- Default Package ----------
8
- RUBY_DEBUG_VERSION = "0.4.2"
8
+ RUBY_DEBUG_VERSION = "0.4.3"
9
9
 
10
10
  FILES = FileList[
11
11
  'Rakefile',
data/bin/rdebug CHANGED
@@ -70,14 +70,16 @@ else
70
70
  trap('INT') { Debugger.interrupt_last }
71
71
  Debugger.stop_on_connect = !options.nostop
72
72
  Debugger.wait_connection = options.wait
73
+ load "#{ENV["HOME"]}/.rdebugrc" if File.exists?("#{ENV["HOME"]}/.rdebugrc")
73
74
  if options.server
74
75
  Debugger.start_remote(options.host, [options.port, options.cport])
76
+ Debugger.debug_load ARGV.shift
75
77
  else
76
78
  Debugger.start
77
79
  if options.script
78
80
  Debugger.run_script(options.script)
79
81
  end
80
82
  debugger 2
83
+ Debugger.debug_load ARGV.shift
81
84
  end
82
- load ARGV.shift
83
85
  end
data/ext/ruby_debug.c CHANGED
@@ -4,7 +4,7 @@
4
4
  #include <rubysig.h>
5
5
  #include <st.h>
6
6
 
7
- #define DEBUG_VERSION "0.4.2"
7
+ #define DEBUG_VERSION "0.4.3"
8
8
 
9
9
  typedef struct {
10
10
  int thnum;
@@ -39,6 +39,7 @@ static VALUE breakpoints = Qnil;
39
39
  static VALUE catchpoint = Qnil;
40
40
  static VALUE waiting = Qnil;
41
41
  static VALUE tracing = Qfalse;
42
+ static VALUE locker = Qnil;
42
43
 
43
44
  static VALUE mDebugger;
44
45
  static VALUE cContext;
@@ -67,6 +68,64 @@ static VALUE debug_suspend(VALUE);
67
68
  static VALUE create_binding(VALUE);
68
69
  static VALUE debug_stop(VALUE);
69
70
 
71
+ typedef struct locked_thread_t {
72
+ VALUE thread;
73
+ struct locked_thread_t *next;
74
+ } locked_thread_t;
75
+
76
+ static locked_thread_t *locked_head = NULL;
77
+ static locked_thread_t *locked_tail = NULL;
78
+
79
+ static int
80
+ is_in_locked(VALUE thread)
81
+ {
82
+ locked_thread_t *node;
83
+
84
+ if(!locked_head)
85
+ return 0;
86
+
87
+ for(node = locked_head; node != locked_tail; node = node->next)
88
+ {
89
+ if(node->thread == thread) return 1;
90
+ }
91
+ return 0;
92
+ }
93
+
94
+ static void
95
+ add_to_locked(VALUE thread)
96
+ {
97
+ locked_thread_t *node;
98
+
99
+ if(is_in_locked(thread))
100
+ return;
101
+
102
+ node = ALLOC(locked_thread_t);
103
+ node->thread = thread;
104
+ node->next = NULL;
105
+ if(locked_tail)
106
+ locked_tail->next = node;
107
+ locked_tail = node;
108
+ if(!locked_head)
109
+ locked_head = node;
110
+ }
111
+
112
+ static VALUE
113
+ remove_from_locked()
114
+ {
115
+ VALUE thread;
116
+ locked_thread_t *node;
117
+
118
+ if(locked_head == NULL)
119
+ return Qnil;
120
+ node = locked_head;
121
+ locked_head = locked_head->next;
122
+ if(locked_tail == node)
123
+ locked_tail = NULL;
124
+ thread = node->thread;
125
+ xfree(node);
126
+ return thread;
127
+ }
128
+
70
129
  #define IS_STARTED (threads_tbl != Qnil)
71
130
 
72
131
  /*
@@ -359,15 +418,20 @@ debug_event_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass)
359
418
  VALUE file = Qnil, line = Qnil;
360
419
  int breakpoint_index = -1;
361
420
 
362
- static int debugging = 0;
363
-
364
421
  if (mid == ID_ALLOCATOR) return;
365
- if(debugging) return;
366
422
  if(!node) return;
423
+
424
+ thread = rb_thread_current();
425
+ while(locker != Qnil && locker != thread)
426
+ {
427
+ add_to_locked(thread);
428
+ rb_thread_stop();
429
+ }
430
+
431
+ if(locker != Qnil) return;
367
432
 
368
- debugging++;
433
+ locker = rb_thread_current();
369
434
 
370
- thread = rb_thread_current();
371
435
  context = thread_context_lookup(thread);
372
436
  Data_Get_Struct(context, debug_context_t, debug_context);
373
437
  check_suspend(debug_context);
@@ -420,7 +484,9 @@ debug_event_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass)
420
484
  {
421
485
  breakpoint = get_breakpoint_at(breakpoint_index);
422
486
  if(check_breakpoint_expression(breakpoint, binding))
487
+ {
423
488
  rb_funcall(context, idAtBreakpoint, 1, breakpoint);
489
+ }
424
490
  else
425
491
  break;
426
492
  }
@@ -508,7 +574,10 @@ debug_event_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass)
508
574
  }
509
575
  }
510
576
 
511
- debugging--;
577
+ locker = Qnil;
578
+ thread = remove_from_locked();
579
+ if(thread != Qnil)
580
+ rb_thread_run(thread);
512
581
  }
513
582
 
514
583
  static VALUE
@@ -543,15 +612,12 @@ debug_start(VALUE self)
543
612
  threads_tbl = rb_hash_new();
544
613
  breakpoints = rb_ary_new();
545
614
  waiting = rb_ary_new();
615
+ locker = Qnil;
546
616
 
547
- rb_add_event_hook(debug_event_hook,
548
- RUBY_EVENT_LINE | RUBY_EVENT_C_CALL | RUBY_EVENT_C_RETURN |
549
- RUBY_EVENT_CALL | RUBY_EVENT_RETURN | RUBY_EVENT_CLASS |
550
- RUBY_EVENT_END | RUBY_EVENT_RAISE
551
- );
617
+ rb_add_event_hook(debug_event_hook, RUBY_EVENT_ALL);
552
618
 
553
619
  if(rb_block_given_p())
554
- return rb_ensure(rb_yield, Qnil, debug_stop_i, Qnil);
620
+ return rb_ensure(rb_yield, Qnil, debug_stop_i, self);
555
621
 
556
622
  return Qtrue;
557
623
  }
@@ -578,6 +644,7 @@ debug_stop(VALUE self)
578
644
  rb_remove_event_hook(debug_event_hook);
579
645
 
580
646
  waiting = Qnil;
647
+ locker = Qnil;
581
648
  breakpoints = Qnil;
582
649
  threads_tbl = Qnil;
583
650
 
@@ -799,7 +866,7 @@ debug_suspend(VALUE self)
799
866
  rb_thread_critical = saved_crit;
800
867
 
801
868
  if(rb_thread_critical == Qfalse)
802
- rb_thread_schedule();
869
+ rb_thread_schedule();
803
870
 
804
871
  return self;
805
872
  }
@@ -837,8 +904,8 @@ debug_resume(VALUE self)
837
904
  }
838
905
  for(i = 0; i < RARRAY(waiting)->len; i++)
839
906
  {
840
- thread = rb_ary_entry(waiting, i);
841
- rb_thread_run(thread);
907
+ thread = rb_ary_entry(waiting, i);
908
+ rb_thread_run(thread);
842
909
  }
843
910
  rb_ary_clear(waiting);
844
911
  rb_thread_critical = saved_crit;
@@ -873,6 +940,94 @@ debug_set_tracing(VALUE self, VALUE value)
873
940
  return value;
874
941
  }
875
942
 
943
+ /*
944
+ * call-seq:
945
+ * Debugger.debug_load(file) -> nil
946
+ *
947
+ * Same as Kernel#load but resets current context's frames.
948
+ * FOR INTERNAL USE ONLY.
949
+ */
950
+ static VALUE
951
+ debug_debug_load(VALUE self, VALUE file)
952
+ {
953
+ VALUE context;
954
+ debug_context_t *debug_context;
955
+
956
+ debug_start(self);
957
+
958
+ context = debug_current_context(self);
959
+ Data_Get_Struct(context, debug_context_t, debug_context);
960
+ rb_ary_clear(debug_context->frames);
961
+ rb_load(file, 0);
962
+
963
+ debug_stop(self);
964
+ return Qnil;
965
+ }
966
+
967
+ static VALUE
968
+ debug_skip_i(VALUE value)
969
+ {
970
+ rb_add_event_hook(debug_event_hook, RUBY_EVENT_ALL);
971
+ return Qnil;
972
+ }
973
+
974
+ /*
975
+ * call-seq:
976
+ * Debugger.skip { block } -> obj or nil
977
+ *
978
+ * The code inside of the block is escaped from the debugger.
979
+ */
980
+ static VALUE
981
+ debug_skip(VALUE self)
982
+ {
983
+ if (!rb_block_given_p()) {
984
+ rb_raise(rb_eArgError, "called without a block");
985
+ }
986
+ if(!IS_STARTED)
987
+ return rb_yield(Qnil);
988
+ rb_remove_event_hook(debug_event_hook);
989
+ return rb_ensure(rb_yield, Qnil, debug_skip_i, Qnil);
990
+ }
991
+
992
+ static VALUE
993
+ debug_at_exit_c(VALUE proc)
994
+ {
995
+ return rb_funcall(proc, rb_intern("call"), 0);
996
+ }
997
+
998
+ static void
999
+ debug_at_exit_i(VALUE proc)
1000
+ {
1001
+ if(!IS_STARTED)
1002
+ {
1003
+ debug_at_exit_c(proc);
1004
+ }
1005
+ else
1006
+ {
1007
+ rb_remove_event_hook(debug_event_hook);
1008
+ rb_ensure(debug_at_exit_c, proc, debug_skip_i, Qnil);
1009
+ }
1010
+ }
1011
+
1012
+ /*
1013
+ * call-seq:
1014
+ * Debugger.debug_at_exit { block } -> proc
1015
+ *
1016
+ * Register <tt>at_exit</tt> hook which is escaped from the debugger.
1017
+ * FOR INTERNAL USE ONLY.
1018
+ */
1019
+ static VALUE
1020
+ debug_at_exit(VALUE self)
1021
+ {
1022
+ VALUE proc;
1023
+ if (!rb_block_given_p()) {
1024
+ rb_raise(rb_eArgError, "called without a block");
1025
+ }
1026
+ proc = rb_block_proc();
1027
+ rb_set_end_proc(debug_at_exit_i, proc);
1028
+ return proc;
1029
+ }
1030
+
876
1031
  /*
877
1032
  * call-seq:
878
1033
  * context.stop_next = steps
@@ -1259,6 +1414,9 @@ Init_ruby_debug()
1259
1414
  rb_define_module_function(mDebugger, "resume", debug_resume, 0);
1260
1415
  rb_define_module_function(mDebugger, "tracing", debug_tracing, 0);
1261
1416
  rb_define_module_function(mDebugger, "tracing=", debug_set_tracing, 1);
1417
+ rb_define_module_function(mDebugger, "debug_load", debug_debug_load, 1);
1418
+ rb_define_module_function(mDebugger, "skip", debug_skip, 0);
1419
+ rb_define_module_function(mDebugger, "debug_at_exit", debug_at_exit, 0);
1262
1420
 
1263
1421
  Init_context();
1264
1422
  Init_frame();
@@ -1282,6 +1440,7 @@ Init_ruby_debug()
1282
1440
  rb_global_variable(&breakpoints);
1283
1441
  rb_global_variable(&catchpoint);
1284
1442
  rb_global_variable(&waiting);
1443
+ rb_global_variable(&locker);
1285
1444
  rb_global_variable(&file_separator);
1286
1445
  rb_global_variable(&alt_file_separator);
1287
1446
  }
data/lib/ruby-debug.rb CHANGED
@@ -156,7 +156,6 @@ module Debugger
156
156
  end
157
157
  end
158
158
  socket.close
159
- puts
160
159
  end
161
160
 
162
161
  def stop_main_thread # :nodoc:
@@ -19,25 +19,26 @@ module Debugger
19
19
 
20
20
  begin
21
21
  require 'readline'
22
- FILE_HISTORY = ".rdebug_hist"
23
-
24
- save_file = File.join(Dir.getwd, FILE_HISTORY)
25
- open(save_file, 'r') do |file|
26
- file.each do |line|
27
- line.chomp!
28
- Readline::HISTORY << line
29
- end
30
- end if File.exists?(save_file)
31
-
32
- class << Debugger; self end.send('define_method', 'save_history') do
33
- open(save_file, 'w') do |file|
34
- Readline::HISTORY.each do |line|
35
- file.puts line unless line.strip.empty?
22
+ class << Debugger
23
+ FILE_HISTORY = ".rdebug_hist"
24
+ save_file = File.join(ENV["HOME"]||ENV["HOMEPATH"], FILE_HISTORY)
25
+ open(save_file, 'r') do |file|
26
+ file.each do |line|
27
+ line.chomp!
28
+ Readline::HISTORY << line
29
+ end
30
+ end if File.exists?(save_file)
31
+
32
+ define_method(:save_history) do
33
+ open(save_file, 'w') do |file|
34
+ Readline::HISTORY.to_a.last(500).each do |line|
35
+ file.puts line unless line.strip.empty?
36
+ end
36
37
  end
37
38
  end
39
+ public :save_history
38
40
  end
39
- class << Debugger; public :save_history end
40
- at_exit { Debugger.save_history }
41
+ Debugger.debug_at_exit { Debugger.save_history }
41
42
 
42
43
  def readline(prompt, hist)
43
44
  Readline::readline(prompt, hist)
@@ -51,7 +52,6 @@ module Debugger
51
52
  line.chomp!
52
53
  line
53
54
  end
54
- USE_READLINE = false
55
55
  end
56
56
  end
57
57
 
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.0
3
3
  specification_version: 1
4
4
  name: ruby-debug
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.4.2
7
- date: 2006-09-15 02:05:10 -04:00
6
+ version: 0.4.3
7
+ date: 2006-10-09 17:56:47 -04:00
8
8
  summary: Fast Ruby debugger
9
9
  require_paths:
10
10
  - lib