ruby-debug-base 0.10.0 → 0.10.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,11 +1,13 @@
1
+ #include "ruby_debug.h"
2
+
1
3
  #include <stdio.h>
2
- #include <ruby.h>
3
4
  #include <node.h>
4
5
  #include <rubysig.h>
5
6
  #include <st.h>
6
7
  #include <version.h>
7
8
 
8
- #define DEBUG_VERSION "0.10.0"
9
+ #define DEBUG_VERSION "0.10.1"
10
+
9
11
 
10
12
  #ifdef _WIN32
11
13
  struct FRAME {
@@ -43,21 +45,6 @@ RUBY_EXTERN struct RVarmap *ruby_dyna_vars;
43
45
  #include <env.h>
44
46
  #endif
45
47
 
46
- #define CTX_FL_SUSPEND (1<<1)
47
- #define CTX_FL_TRACING (1<<2)
48
- #define CTX_FL_SKIPPED (1<<3)
49
- #define CTX_FL_IGNORE (1<<4)
50
- #define CTX_FL_DEAD (1<<5)
51
- #define CTX_FL_WAS_RUNNING (1<<6)
52
- #define CTX_FL_ENABLE_BKPT (1<<7)
53
- #define CTX_FL_STEPPED (1<<8)
54
- #define CTX_FL_FORCE_MOVE (1<<9)
55
-
56
- #define CTX_FL_TEST(c,f) ((c)->flags & (f))
57
- #define CTX_FL_SET(c,f) do { (c)->flags |= (f); } while (0)
58
- #define CTX_FL_UNSET(c,f) do { (c)->flags &= ~(f); } while (0)
59
-
60
- #define IS_STARTED (threads_tbl != Qnil)
61
48
  #define FRAME_N(n) (&debug_context->frames[debug_context->stack_size-(n)-1])
62
49
  #define GET_FRAME (FRAME_N(check_frame_number(debug_context, frame)))
63
50
 
@@ -67,75 +54,10 @@ RUBY_EXTERN struct RVarmap *ruby_dyna_vars;
67
54
 
68
55
  #define STACK_SIZE_INCREMENT 128
69
56
 
70
- typedef struct {
71
- int argc; /* Number of arguments a frame should have. */
72
- VALUE binding;
73
- ID id;
74
- ID orig_id;
75
- int line;
76
- const char * file;
77
- short dead;
78
- VALUE self;
79
- VALUE arg_ary;
80
- union {
81
- struct {
82
- struct FRAME *frame;
83
- struct SCOPE *scope;
84
- struct RVarmap *dyna_vars;
85
- } runtime;
86
- struct {
87
- VALUE args;
88
- VALUE locals;
89
- VALUE arg_ary;
90
- } copy;
91
- } info;
92
- } debug_frame_t;
93
-
94
- enum ctx_stop_reason {CTX_STOP_NONE, CTX_STOP_STEP, CTX_STOP_BREAKPOINT, CTX_STOP_CATCHPOINT};
95
-
96
- typedef struct {
97
- VALUE thread_id;
98
- int thnum;
99
- int flags;
100
- enum ctx_stop_reason stop_reason;
101
- int stop_next;
102
- int dest_frame;
103
- int stop_line;
104
- int stop_frame;
105
- int stack_size;
106
- int stack_len;
107
- debug_frame_t *frames;
108
- const char * last_file;
109
- int last_line;
110
- VALUE breakpoint;
111
- } debug_context_t;
112
-
113
- enum bp_type {BP_POS_TYPE, BP_METHOD_TYPE};
114
- enum hit_condition {HIT_COND_NONE, HIT_COND_GE, HIT_COND_EQ, HIT_COND_MOD};
115
-
116
- typedef struct {
117
- int id;
118
- enum bp_type type;
119
- VALUE source;
120
- union
121
- {
122
- int line;
123
- ID mid;
124
- } pos;
125
- VALUE expr;
126
- VALUE enabled;
127
- int hit_count;
128
- int hit_value;
129
- enum hit_condition hit_condition;
130
- } debug_breakpoint_t;
131
-
132
57
  typedef struct {
133
58
  st_table *tbl;
134
59
  } threads_table_t;
135
60
 
136
- static VALUE threads_tbl = Qnil;
137
- static VALUE breakpoints = Qnil;
138
- static VALUE catchpoint = Qnil;
139
61
  static VALUE tracing = Qfalse;
140
62
  static VALUE locker = Qnil;
141
63
  static VALUE post_mortem = Qfalse;
@@ -147,20 +69,21 @@ static VALUE last_context = Qnil;
147
69
  static VALUE last_thread = Qnil;
148
70
  static debug_context_t *last_debug_context = NULL;
149
71
 
150
- static VALUE mDebugger;
72
+ VALUE rdebug_threads_tbl = Qnil; /* Context for each of the threads */
73
+ VALUE mDebugger; /* Ruby Debugger Module object */
74
+
151
75
  static VALUE cThreadsTable;
152
76
  static VALUE cContext;
153
- static VALUE cBreakpoint;
154
77
  static VALUE cDebugThread;
155
78
 
156
79
  static VALUE rb_mObjectSpace;
157
80
 
158
- static ID idAtLine;
159
81
  static ID idAtBreakpoint;
160
82
  static ID idAtCatchpoint;
83
+ static ID idAtLine;
84
+ static ID idAtReturn;
161
85
  static ID idAtTracing;
162
86
  static ID idList;
163
- static ID idEval;
164
87
 
165
88
  static int start_count = 0;
166
89
  static int thnum_max = 0;
@@ -186,6 +109,17 @@ typedef struct locked_thread_t {
186
109
  static locked_thread_t *locked_head = NULL;
187
110
  static locked_thread_t *locked_tail = NULL;
188
111
 
112
+ /* "Step", "Next" and "Finish" do their work by saving information
113
+ about where to stop next. reset_stopping_points removes/resets this
114
+ information. */
115
+ inline static void
116
+ reset_stepping_stop_points(debug_context_t *debug_context)
117
+ {
118
+ debug_context->dest_frame = -1;
119
+ debug_context->stop_line = -1;
120
+ debug_context->stop_next = -1;
121
+ }
122
+
189
123
  inline static VALUE
190
124
  real_class(VALUE klass)
191
125
  {
@@ -379,7 +313,7 @@ check_thread_contexts()
379
313
  {
380
314
  threads_table_t *threads_table;
381
315
 
382
- Data_Get_Struct(threads_tbl, threads_table_t, threads_table);
316
+ Data_Get_Struct(rdebug_threads_tbl, threads_table_t, threads_table);
383
317
  st_foreach(threads_table->tbl, threads_table_check_i, 0);
384
318
  }
385
319
 
@@ -395,15 +329,6 @@ debug_is_started(VALUE self)
395
329
  return IS_STARTED ? Qtrue : Qfalse;
396
330
  }
397
331
 
398
- static void
399
- debug_check_started()
400
- {
401
- if(!IS_STARTED)
402
- {
403
- rb_raise(rb_eRuntimeError, "Debugger.start is not called yet.");
404
- }
405
- }
406
-
407
332
  static void
408
333
  debug_context_mark(void *data)
409
334
  {
@@ -505,7 +430,7 @@ thread_context_lookup(VALUE thread, VALUE *context, debug_context_t **debug_cont
505
430
  return;
506
431
  }
507
432
  thread_id = ref2id(thread);
508
- Data_Get_Struct(threads_tbl, threads_table_t, threads_table);
433
+ Data_Get_Struct(rdebug_threads_tbl, threads_table_t, threads_table);
509
434
  if(!st_lookup(threads_table->tbl, thread_id, context))
510
435
  {
511
436
  *context = debug_context_create(thread);
@@ -541,6 +466,26 @@ call_at_line(VALUE context, debug_context_t *debug_context, VALUE file, VALUE li
541
466
  return rb_protect(call_at_line_unprotected, args, 0);
542
467
  }
543
468
 
469
+ static VALUE
470
+ call_at_return_unprotected(VALUE args)
471
+ {
472
+ VALUE context;
473
+ context = *RARRAY(args)->ptr;
474
+ return rb_funcall2(context, idAtReturn, RARRAY(args)->len - 1, RARRAY(args)->ptr + 1);
475
+ }
476
+
477
+ static VALUE
478
+ call_at_return(VALUE context, debug_context_t *debug_context, VALUE file, VALUE line)
479
+ {
480
+ VALUE args;
481
+
482
+ last_debugged_thnum = debug_context->thnum;
483
+ save_current_position(debug_context);
484
+
485
+ args = rb_ary_new3(3, context, file, line);
486
+ return rb_protect(call_at_return_unprotected, args, 0);
487
+ }
488
+
544
489
  static void
545
490
  save_call_frame(rb_event_t event, VALUE self, char *file, int line, ID mid, debug_context_t *debug_context)
546
491
  {
@@ -579,7 +524,7 @@ save_call_frame(rb_event_t event, VALUE self, char *file, int line, ID mid, debu
579
524
  #define isdirsep(x) ((x) == '/')
580
525
  #endif
581
526
 
582
- static int
527
+ int
583
528
  filename_cmp(VALUE source, char *file)
584
529
  {
585
530
  char *source_ptr, *file_ptr;
@@ -606,133 +551,6 @@ filename_cmp(VALUE source, char *file)
606
551
  return 1;
607
552
  }
608
553
 
609
- inline static int
610
- classname_cmp(VALUE name, VALUE klass)
611
- {
612
- VALUE class_name = (Qnil == name) ? rb_str_new2("main") : name;
613
- return (klass != Qnil
614
- && rb_str_cmp(class_name, rb_mod_name(klass)) == 0);
615
- }
616
-
617
- static int
618
- check_breakpoint_hit_condition(VALUE breakpoint)
619
- {
620
- debug_breakpoint_t *debug_breakpoint;
621
-
622
- if(breakpoint == Qnil)
623
- return 0;
624
- Data_Get_Struct(breakpoint, debug_breakpoint_t, debug_breakpoint);
625
-
626
- debug_breakpoint->hit_count++;
627
- if (!Qtrue == debug_breakpoint->enabled) return 0;
628
- switch(debug_breakpoint->hit_condition)
629
- {
630
- case HIT_COND_NONE:
631
- return 1;
632
- case HIT_COND_GE:
633
- {
634
- if(debug_breakpoint->hit_count >= debug_breakpoint->hit_value)
635
- return 1;
636
- break;
637
- }
638
- case HIT_COND_EQ:
639
- {
640
- if(debug_breakpoint->hit_count == debug_breakpoint->hit_value)
641
- return 1;
642
- break;
643
- }
644
- case HIT_COND_MOD:
645
- {
646
- if(debug_breakpoint->hit_count % debug_breakpoint->hit_value == 0)
647
- return 1;
648
- break;
649
- }
650
- }
651
- return 0;
652
- }
653
-
654
- static int
655
- check_breakpoint_by_pos(VALUE breakpoint, char *file, int line)
656
- {
657
- debug_breakpoint_t *debug_breakpoint;
658
-
659
- if(breakpoint == Qnil)
660
- return 0;
661
- Data_Get_Struct(breakpoint, debug_breakpoint_t, debug_breakpoint);
662
- if (!Qtrue == debug_breakpoint->enabled) return 0;
663
- if(debug_breakpoint->type != BP_POS_TYPE)
664
- return 0;
665
- if(debug_breakpoint->pos.line != line)
666
- return 0;
667
- if(filename_cmp(debug_breakpoint->source, file))
668
- return 1;
669
- return 0;
670
- }
671
-
672
- static int
673
- check_breakpoint_by_method(VALUE breakpoint, VALUE klass, ID mid)
674
- {
675
- debug_breakpoint_t *debug_breakpoint;
676
-
677
- if(breakpoint == Qnil)
678
- return 0;
679
- Data_Get_Struct(breakpoint, debug_breakpoint_t, debug_breakpoint);
680
- if (!Qtrue == debug_breakpoint->enabled) return 0;
681
- if(debug_breakpoint->type != BP_METHOD_TYPE)
682
- return 0;
683
- if(debug_breakpoint->pos.mid != mid)
684
- return 0;
685
- if(classname_cmp(debug_breakpoint->source, klass))
686
- return 1;
687
- return 0;
688
- }
689
-
690
- static VALUE
691
- check_breakpoints_by_pos(debug_context_t *debug_context, char *file, int line)
692
- {
693
- VALUE breakpoint;
694
- int i;
695
-
696
- if(!CTX_FL_TEST(debug_context, CTX_FL_ENABLE_BKPT))
697
- return Qnil;
698
-
699
- if(check_breakpoint_by_pos(debug_context->breakpoint, file, line))
700
- return debug_context->breakpoint;
701
-
702
- if(RARRAY(breakpoints)->len == 0)
703
- return Qnil;
704
- for(i = 0; i < RARRAY(breakpoints)->len; i++)
705
- {
706
- breakpoint = rb_ary_entry(breakpoints, i);
707
- if(check_breakpoint_by_pos(breakpoint, file, line))
708
- return breakpoint;
709
- }
710
- return Qnil;
711
- }
712
-
713
- static VALUE
714
- check_breakpoints_by_method(debug_context_t *debug_context, VALUE klass, ID mid)
715
- {
716
- VALUE breakpoint;
717
- int i;
718
-
719
- if(!CTX_FL_TEST(debug_context, CTX_FL_ENABLE_BKPT))
720
- return Qnil;
721
-
722
- if(check_breakpoint_by_method(debug_context->breakpoint, klass, mid))
723
- return debug_context->breakpoint;
724
-
725
- if(RARRAY(breakpoints)->len == 0)
726
- return Qnil;
727
- for(i = 0; i < RARRAY(breakpoints)->len; i++)
728
- {
729
- breakpoint = rb_ary_entry(breakpoints, i);
730
- if(check_breakpoint_by_method(breakpoint, klass, mid))
731
- return breakpoint;
732
- }
733
- return Qnil;
734
- }
735
-
736
554
  /*
737
555
  * This is a NASTY HACK. For some reasons rb_f_binding is declared
738
556
  * static in eval.c. So we create a cons up call to binding in C.
@@ -750,27 +568,6 @@ create_binding(VALUE self)
750
568
  return f_binding(self);
751
569
  }
752
570
 
753
- static VALUE
754
- eval_expression(VALUE args)
755
- {
756
- return rb_funcall2(rb_mKernel, idEval, 2, RARRAY(args)->ptr);
757
- }
758
-
759
- inline static int
760
- check_breakpoint_expression(VALUE breakpoint, VALUE binding)
761
- {
762
- debug_breakpoint_t *debug_breakpoint;
763
- VALUE args, expr_result;
764
-
765
- Data_Get_Struct(breakpoint, debug_breakpoint_t, debug_breakpoint);
766
- if(NIL_P(debug_breakpoint->expr))
767
- return 1;
768
-
769
- args = rb_ary_new3(2, debug_breakpoint->expr, binding);
770
- expr_result = rb_protect(eval_expression, args, 0);
771
- return RTEST(expr_result);
772
- }
773
-
774
571
  inline static debug_frame_t *
775
572
  get_top_frame(debug_context_t *debug_context)
776
573
  {
@@ -999,12 +796,9 @@ debug_event_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass)
999
796
  debug_context->breakpoint = Qnil;
1000
797
  }
1001
798
 
1002
- /* reset all pointers */
1003
- debug_context->dest_frame = -1;
1004
- debug_context->stop_line = -1;
1005
- debug_context->stop_next = -1;
1006
-
1007
- call_at_line(context, debug_context, rb_str_new2(file), INT2FIX(line));
799
+ reset_stepping_stop_points(debug_context);
800
+ call_at_line(context, debug_context, rb_str_new2(file),
801
+ INT2FIX(line));
1008
802
  }
1009
803
  break;
1010
804
  }
@@ -1056,8 +850,15 @@ debug_event_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass)
1056
850
  {
1057
851
  if(debug_context->stack_size == debug_context->stop_frame)
1058
852
  {
1059
- debug_context->stop_next = 1;
1060
- debug_context->stop_frame = 0;
853
+ if(debug_context->stack_size == 0)
854
+ save_call_frame(event, self, file, line, mid, debug_context);
855
+ else
856
+ set_frame_source(event, debug_context, self, file, line, mid);
857
+ binding = self? create_binding(self) : Qnil;
858
+ save_top_binding(debug_context, binding);
859
+ call_at_return(context, debug_context, rb_str_new2(file),
860
+ INT2FIX(line));
861
+ debug_context->dest_frame = -1;
1061
862
  }
1062
863
  while(debug_context->stack_size > 0)
1063
864
  {
@@ -1065,7 +866,6 @@ debug_event_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass)
1065
866
  if(debug_context->frames[debug_context->stack_size].orig_id == mid)
1066
867
  break;
1067
868
  }
1068
- CTX_FL_SET(debug_context, CTX_FL_ENABLE_BKPT);
1069
869
  break;
1070
870
  }
1071
871
  case RUBY_EVENT_CLASS:
@@ -1092,21 +892,43 @@ debug_event_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass)
1092
892
  }
1093
893
 
1094
894
  expn_class = rb_obj_class(ruby_errinfo);
895
+
896
+ /* This code goes back to the earliest days of ruby-debug. It
897
+ tends to disallow catching an exception via the
898
+ "catchpoint" command. To address this one possiblilty is to
899
+ move this after testing for catchponts. Kent however thinks
900
+ there may be a misfeature in Ruby's eval.c: the problem was
901
+ in the fact that Ruby doesn't reset exception flag on the
902
+ current thread before it calls a notification handler.
903
+
904
+ See also the #ifdef'd code below as well.
905
+ */
906
+ #ifdef NORMAL_CODE
1095
907
  if( !NIL_P(rb_class_inherited_p(expn_class, rb_eSystemExit)) )
1096
908
  {
1097
909
  debug_stop(mDebugger);
1098
910
  break;
1099
911
  }
912
+ #endif
1100
913
 
1101
- if(catchpoint == Qnil)
914
+ if (rdebug_catchpoints == Qnil ||
915
+ RHASH(rdebug_catchpoints)->tbl->num_entries == 0)
1102
916
  break;
1103
917
 
1104
918
  ancestors = rb_mod_ancestors(expn_class);
1105
919
  for(i = 0; i < RARRAY(ancestors)->len; i++)
1106
920
  {
1107
- aclass = rb_ary_entry(ancestors, i);
1108
- if(rb_str_cmp(rb_mod_name(aclass), catchpoint) == 0)
921
+ VALUE mod_name;
922
+ VALUE hit_count;
923
+
924
+ aclass = rb_ary_entry(ancestors, i);
925
+ mod_name = rb_mod_name(aclass);
926
+ hit_count = rb_hash_aref(rdebug_catchpoints, mod_name);
927
+ if(hit_count != Qnil)
1109
928
  {
929
+ hit_count = INT2FIX(FIX2INT(rb_hash_aref(rdebug_catchpoints,
930
+ mod_name)+1));
931
+ rb_hash_aset(rdebug_catchpoints, mod_name, hit_count);
1110
932
  debug_context->stop_reason = CTX_STOP_CATCHPOINT;
1111
933
  rb_funcall(context, idAtCatchpoint, 1, ruby_errinfo);
1112
934
  if(self && binding == Qnil)
@@ -1117,6 +939,18 @@ debug_event_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass)
1117
939
  }
1118
940
  }
1119
941
 
942
+ /* If we stop the debugger, we may not be able to trace into
943
+ code that has an exception handler wrapped around it. So
944
+ the alternative is to force the user to do his own
945
+ Debugger.stop. */
946
+ #ifdef NORMAL_CODE_MOVING_AFTER_
947
+ if( !NIL_P(rb_class_inherited_p(expn_class, rb_eSystemExit)) )
948
+ {
949
+ debug_stop(mDebugger);
950
+ break;
951
+ }
952
+ #endif
953
+
1120
954
  break;
1121
955
  }
1122
956
  }
@@ -1150,16 +984,20 @@ debug_stop_i(VALUE self)
1150
984
 
1151
985
  /*
1152
986
  * call-seq:
1153
- * Debugger.start -> bool
1154
- * Debugger.start { ... } -> obj
987
+ * Debugger.start_ -> bool
988
+ * Debugger.start_ { ... } -> obj
989
+ *
990
+ * This method is internal and activates the debugger. Use
991
+ * Debugger.start (from ruby-debug-base.rb) instead.
1155
992
  *
1156
- * This method activates the debugger.
1157
- * If it's called without a block it returns +true+, unless debugger was already started.
1158
- * If a block is given, it starts debugger and yields to block. When the block is finished
1159
- * executing it stops the debugger with Debugger.stop method.
993
+ * If it's called without a block it returns +true+, unless debugger
994
+ * was already started. If a block is given, it starts debugger and
995
+ * yields to block. When the block is finished executing it stops
996
+ * the debugger with Debugger.stop method.
1160
997
  *
1161
- * <i>Note that if you want to stop debugger, you must call Debugger.stop as many time as you
1162
- * called Debugger.start method.</i>
998
+ * <i>Note that if you want to stop debugger, you must call
999
+ * Debugger.stop as many time as you called Debugger.start
1000
+ * method.</i>
1163
1001
  */
1164
1002
  static VALUE
1165
1003
  debug_start(VALUE self)
@@ -1171,9 +1009,10 @@ debug_start(VALUE self)
1171
1009
  result = Qfalse;
1172
1010
  else
1173
1011
  {
1174
- breakpoints = rb_ary_new();
1175
- locker = Qnil;
1176
- threads_tbl = threads_table_create();
1012
+ locker = Qnil;
1013
+ rdebug_breakpoints = rb_ary_new();
1014
+ rdebug_catchpoints = rb_hash_new();
1015
+ rdebug_threads_tbl = threads_table_create();
1177
1016
 
1178
1017
  rb_add_event_hook(debug_event_hook, RUBY_EVENT_ALL);
1179
1018
  result = Qtrue;
@@ -1206,156 +1045,13 @@ debug_stop(VALUE self)
1206
1045
 
1207
1046
  rb_remove_event_hook(debug_event_hook);
1208
1047
 
1209
- locker = Qnil;
1210
- breakpoints = Qnil;
1211
- threads_tbl = Qnil;
1048
+ locker = Qnil;
1049
+ rdebug_breakpoints = Qnil;
1050
+ rdebug_threads_tbl = Qnil;
1212
1051
 
1213
1052
  return Qtrue;
1214
1053
  }
1215
1054
 
1216
- static void
1217
- breakpoint_mark(void *data)
1218
- {
1219
- debug_breakpoint_t *breakpoint;
1220
- breakpoint = (debug_breakpoint_t *)data;
1221
- rb_gc_mark(breakpoint->source);
1222
- rb_gc_mark(breakpoint->expr);
1223
- }
1224
-
1225
- static VALUE
1226
- create_breakpoint_from_args(int argc, VALUE *argv, int id)
1227
- {
1228
- VALUE source, pos, expr;
1229
- debug_breakpoint_t *breakpoint;
1230
- int type;
1231
-
1232
- if(rb_scan_args(argc, argv, "21", &source, &pos, &expr) == 2)
1233
- {
1234
- expr = Qnil;
1235
- }
1236
- type = FIXNUM_P(pos) ? BP_POS_TYPE : BP_METHOD_TYPE;
1237
- if(type == BP_POS_TYPE)
1238
- source = StringValue(source);
1239
- else
1240
- pos = StringValue(pos);
1241
- breakpoint = ALLOC(debug_breakpoint_t);
1242
- breakpoint->id = id;
1243
- breakpoint->source = source;
1244
- breakpoint->type = type;
1245
- if(type == BP_POS_TYPE)
1246
- breakpoint->pos.line = FIX2INT(pos);
1247
- else
1248
- breakpoint->pos.mid = rb_intern(RSTRING(pos)->ptr);
1249
- breakpoint->enabled = Qtrue;
1250
- breakpoint->expr = NIL_P(expr) ? expr: StringValue(expr);
1251
- breakpoint->hit_count = 0;
1252
- breakpoint->hit_value = 0;
1253
- breakpoint->hit_condition = HIT_COND_NONE;
1254
- return Data_Wrap_Struct(cBreakpoint, breakpoint_mark, xfree, breakpoint);
1255
- }
1256
-
1257
- /*
1258
- * call-seq:
1259
- * Debugger.add_breakpoint(source, pos, condition = nil) -> breakpoint
1260
- *
1261
- * Adds a new breakpoint.
1262
- * <i>source</i> is a name of a file or a class.
1263
- * <i>pos</i> is a line number or a method name if <i>source</i> is a class name.
1264
- * <i>condition</i> is a string which is evaluated to +true+ when this breakpoint
1265
- * is activated.
1266
- */
1267
- static VALUE
1268
- debug_add_breakpoint(int argc, VALUE *argv, VALUE self)
1269
- {
1270
- VALUE result;
1271
-
1272
- debug_check_started();
1273
-
1274
- result = create_breakpoint_from_args(argc, argv, ++bkp_count);
1275
- rb_ary_push(breakpoints, result);
1276
- return result;
1277
- }
1278
-
1279
- /*
1280
- * call-seq:
1281
- * Debugger.remove_breakpoint(id) -> breakpoint
1282
- *
1283
- * Removes breakpoint by its id.
1284
- * <i>id</i> is an identificator of a breakpoint.
1285
- */
1286
- static VALUE
1287
- debug_remove_breakpoint(VALUE self, VALUE id_value)
1288
- {
1289
- int i;
1290
- int id;
1291
- VALUE breakpoint;
1292
- debug_breakpoint_t *debug_breakpoint;
1293
-
1294
- id = FIX2INT(id_value);
1295
-
1296
- for( i = 0; i < RARRAY(breakpoints)->len; i += 1 )
1297
- {
1298
- breakpoint = rb_ary_entry(breakpoints, i);
1299
- Data_Get_Struct(breakpoint, debug_breakpoint_t, debug_breakpoint);
1300
- if(debug_breakpoint->id == id)
1301
- {
1302
- rb_ary_delete_at(breakpoints, i);
1303
- return breakpoint;
1304
- }
1305
- }
1306
- return Qnil;
1307
- }
1308
-
1309
- /*
1310
- * call-seq:
1311
- * Debugger.breakpoints -> array
1312
- *
1313
- * Returns an array of breakpoints.
1314
- */
1315
- static VALUE
1316
- debug_breakpoints(VALUE self)
1317
- {
1318
- debug_check_started();
1319
-
1320
- return breakpoints;
1321
- }
1322
-
1323
- /*
1324
- * call-seq:
1325
- * Debugger.checkpoint -> string
1326
- *
1327
- * Returns a current checkpoint, which is a name of exception that will
1328
- * trigger a debugger when raised.
1329
- */
1330
- static VALUE
1331
- debug_catchpoint(VALUE self)
1332
- {
1333
- debug_check_started();
1334
-
1335
- return catchpoint;
1336
- }
1337
-
1338
- /*
1339
- * call-seq:
1340
- * Debugger.checkpoint = string -> string
1341
- *
1342
- * Sets checkpoint.
1343
- */
1344
- static VALUE
1345
- debug_set_catchpoint(VALUE self, VALUE value)
1346
- {
1347
- debug_check_started();
1348
-
1349
- if (!NIL_P(value) && TYPE(value) != T_STRING) {
1350
- rb_raise(rb_eTypeError, "value of checkpoint must be String");
1351
- }
1352
- if(NIL_P(value))
1353
- catchpoint = Qnil;
1354
- else
1355
- catchpoint = rb_str_dup(value);
1356
- return value;
1357
- }
1358
-
1359
1055
  static int
1360
1056
  find_last_context_func(VALUE key, VALUE value, VALUE *result)
1361
1057
  {
@@ -1383,7 +1079,7 @@ debug_last_interrupted(VALUE self)
1383
1079
 
1384
1080
  debug_check_started();
1385
1081
 
1386
- Data_Get_Struct(threads_tbl, threads_table_t, threads_table);
1082
+ Data_Get_Struct(rdebug_threads_tbl, threads_table_t, threads_table);
1387
1083
 
1388
1084
  st_foreach(threads_table->tbl, find_last_context_func, (st_data_t)&result);
1389
1085
  return result;
@@ -1451,8 +1147,8 @@ debug_contexts(VALUE self)
1451
1147
  thread_context_lookup(thread, &context, NULL);
1452
1148
  rb_ary_push(new_list, context);
1453
1149
  }
1454
- threads_table_clear(threads_tbl);
1455
- Data_Get_Struct(threads_tbl, threads_table_t, threads_table);
1150
+ threads_table_clear(rdebug_threads_tbl);
1151
+ Data_Get_Struct(rdebug_threads_tbl, threads_table_t, threads_table);
1456
1152
  for(i = 0; i < RARRAY(new_list)->len; i++)
1457
1153
  {
1458
1154
  context = rb_ary_entry(new_list, i);
@@ -1676,7 +1372,8 @@ debug_debug_load(int argc, VALUE *argv, VALUE self)
1676
1372
  {
1677
1373
  VALUE file, stop, context;
1678
1374
  debug_context_t *debug_context;
1679
-
1375
+ int state = 0;
1376
+
1680
1377
  if(rb_scan_args(argc, argv, "11", &file, &stop) == 1)
1681
1378
  stop = Qfalse;
1682
1379
 
@@ -1686,8 +1383,14 @@ debug_debug_load(int argc, VALUE *argv, VALUE self)
1686
1383
  debug_context->stack_size = 0;
1687
1384
  if(RTEST(stop))
1688
1385
  debug_context->stop_next = 1;
1689
- rb_load(file, 0);
1690
-
1386
+ rb_load_protect(file, 0, &state);
1387
+ if (0 != state) {
1388
+ VALUE errinfo = ruby_errinfo;
1389
+ debug_suspend(self);
1390
+ reset_stepping_stop_points(debug_context);
1391
+ ruby_errinfo = Qnil;
1392
+ return errinfo;
1393
+ }
1691
1394
  debug_stop(self);
1692
1395
  return Qnil;
1693
1396
  }
@@ -1836,7 +1539,7 @@ context_step_over(int argc, VALUE *argv, VALUE self)
1836
1539
  * call-seq:
1837
1540
  * context.stop_frame(frame)
1838
1541
  *
1839
- * Stops when a frame with number +frame+ is activated. Implements +up+ and +down+ commands.
1542
+ * Stops when a frame with number +frame+ is activated. Implements +finish+ and +next+ commands.
1840
1543
  */
1841
1544
  static VALUE
1842
1545
  context_stop_frame(VALUE self, VALUE frame)
@@ -2395,50 +2098,6 @@ context_dead(VALUE self)
2395
2098
  return CTX_FL_TEST(debug_context, CTX_FL_DEAD) ? Qtrue : Qfalse;
2396
2099
  }
2397
2100
 
2398
- /*
2399
- * call-seq:
2400
- * context.breakpoint -> breakpoint
2401
- *
2402
- * Returns a context-specific temporary Breakpoint object.
2403
- */
2404
- static VALUE
2405
- context_breakpoint(VALUE self)
2406
- {
2407
- debug_context_t *debug_context;
2408
-
2409
- debug_check_started();
2410
-
2411
- Data_Get_Struct(self, debug_context_t, debug_context);
2412
- return debug_context->breakpoint;
2413
- }
2414
-
2415
- /*
2416
- * call-seq:
2417
- * context.set_breakpoint(source, pos, condition = nil) -> breakpoint
2418
- *
2419
- * Sets a context-specific temporary breakpoint, which can be used to implement
2420
- * 'Run to Cursor' debugger function. When this breakpoint is reached, it will be
2421
- * cleared out.
2422
- *
2423
- * <i>source</i> is a name of a file or a class.
2424
- * <i>pos</i> is a line number or a method name if <i>source</i> is a class name.
2425
- * <i>condition</i> is a string which is evaluated to +true+ when this breakpoint
2426
- * is activated.
2427
- */
2428
- static VALUE
2429
- context_set_breakpoint(int argc, VALUE *argv, VALUE self)
2430
- {
2431
- VALUE result;
2432
- debug_context_t *debug_context;
2433
-
2434
- debug_check_started();
2435
-
2436
- Data_Get_Struct(self, debug_context_t, debug_context);
2437
- result = create_breakpoint_from_args(argc, argv, 0);
2438
- debug_context->breakpoint = result;
2439
- return result;
2440
- }
2441
-
2442
2101
  /*
2443
2102
  * call-seq:
2444
2103
  * context.stop_reason -> sym
@@ -2478,256 +2137,6 @@ context_stop_reason(VALUE self)
2478
2137
  }
2479
2138
 
2480
2139
 
2481
- /*
2482
- * call-seq:
2483
- * breakpoint.enabled?
2484
- *
2485
- * Returns whether breakpoint is enabled or not.
2486
- */
2487
- static VALUE
2488
- breakpoint_enabled(VALUE self)
2489
- {
2490
- debug_breakpoint_t *breakpoint;
2491
-
2492
- Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
2493
- return breakpoint->enabled;
2494
- }
2495
-
2496
- /*
2497
- * call-seq:
2498
- * breakpoint.enabled = bool
2499
- *
2500
- * Enables or disables breakpoint.
2501
- */
2502
- static VALUE
2503
- breakpoint_set_enabled(VALUE self, VALUE bool)
2504
- {
2505
- debug_breakpoint_t *breakpoint;
2506
-
2507
- Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
2508
- return breakpoint->enabled = bool;
2509
- }
2510
-
2511
- /*
2512
- * call-seq:
2513
- * breakpoint.source -> string
2514
- *
2515
- * Returns a source of the breakpoint.
2516
- */
2517
- static VALUE
2518
- breakpoint_source(VALUE self)
2519
- {
2520
- debug_breakpoint_t *breakpoint;
2521
-
2522
- Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
2523
- return breakpoint->source;
2524
- }
2525
-
2526
- /*
2527
- * call-seq:
2528
- * breakpoint.source = string
2529
- *
2530
- * Sets the source of the breakpoint.
2531
- */
2532
- static VALUE
2533
- breakpoint_set_source(VALUE self, VALUE value)
2534
- {
2535
- debug_breakpoint_t *breakpoint;
2536
-
2537
- Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
2538
- breakpoint->source = StringValue(value);
2539
- return value;
2540
- }
2541
-
2542
- /*
2543
- * call-seq:
2544
- * breakpoint.pos -> string or int
2545
- *
2546
- * Returns a position of this breakpoint.
2547
- */
2548
- static VALUE
2549
- breakpoint_pos(VALUE self)
2550
- {
2551
- debug_breakpoint_t *breakpoint;
2552
-
2553
- Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
2554
- if(breakpoint->type == BP_METHOD_TYPE)
2555
- return rb_str_new2(rb_id2name(breakpoint->pos.mid));
2556
- else
2557
- return INT2FIX(breakpoint->pos.line);
2558
- }
2559
-
2560
- /*
2561
- * call-seq:
2562
- * breakpoint.pos = string or int
2563
- *
2564
- * Sets the position of this breakpoint.
2565
- */
2566
- static VALUE
2567
- breakpoint_set_pos(VALUE self, VALUE value)
2568
- {
2569
- debug_breakpoint_t *breakpoint;
2570
-
2571
- Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
2572
- if(breakpoint->type == BP_METHOD_TYPE)
2573
- {
2574
- breakpoint->pos.mid = rb_to_id(StringValue(value));
2575
- }
2576
- else
2577
- breakpoint->pos.line = FIX2INT(value);
2578
- return value;
2579
- }
2580
-
2581
- /*
2582
- * call-seq:
2583
- * breakpoint.expr -> string
2584
- *
2585
- * Returns a codition expression when this breakpoint should be activated.
2586
- */
2587
- static VALUE
2588
- breakpoint_expr(VALUE self)
2589
- {
2590
- debug_breakpoint_t *breakpoint;
2591
-
2592
- Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
2593
- return breakpoint->expr;
2594
- }
2595
-
2596
- /*
2597
- * call-seq:
2598
- * breakpoint.expr = string
2599
- *
2600
- * Sets the codition expression when this breakpoint should be activated.
2601
- */
2602
- static VALUE
2603
- breakpoint_set_expr(VALUE self, VALUE value)
2604
- {
2605
- debug_breakpoint_t *breakpoint;
2606
-
2607
- Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
2608
- breakpoint->expr = StringValue(value);
2609
- return value;
2610
- }
2611
-
2612
- /*
2613
- * call-seq:
2614
- * breakpoint.id -> int
2615
- *
2616
- * Returns id of the breakpoint.
2617
- */
2618
- static VALUE
2619
- breakpoint_id(VALUE self)
2620
- {
2621
- debug_breakpoint_t *breakpoint;
2622
-
2623
- Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
2624
- return INT2FIX(breakpoint->id);
2625
- }
2626
-
2627
- /*
2628
- * call-seq:
2629
- * breakpoint.hit_count -> int
2630
- *
2631
- * Returns the hit count of the breakpoint.
2632
- */
2633
- static VALUE
2634
- breakpoint_hit_count(VALUE self)
2635
- {
2636
- debug_breakpoint_t *breakpoint;
2637
-
2638
- Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
2639
- return INT2FIX(breakpoint->hit_count);
2640
- }
2641
-
2642
- /*
2643
- * call-seq:
2644
- * breakpoint.hit_value -> int
2645
- *
2646
- * Returns the hit value of the breakpoint.
2647
- */
2648
- static VALUE
2649
- breakpoint_hit_value(VALUE self)
2650
- {
2651
- debug_breakpoint_t *breakpoint;
2652
-
2653
- Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
2654
- return INT2FIX(breakpoint->hit_value);
2655
- }
2656
-
2657
- /*
2658
- * call-seq:
2659
- * breakpoint.hit_value = int
2660
- *
2661
- * Sets the hit value of the breakpoint.
2662
- */
2663
- static VALUE
2664
- breakpoint_set_hit_value(VALUE self, VALUE value)
2665
- {
2666
- debug_breakpoint_t *breakpoint;
2667
-
2668
- Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
2669
- breakpoint->hit_value = FIX2INT(value);
2670
- return value;
2671
- }
2672
-
2673
- /*
2674
- * call-seq:
2675
- * breakpoint.hit_condition -> symbol
2676
- *
2677
- * Returns the hit condition of the breakpoint:
2678
- *
2679
- * +nil+ if it is an unconditional breakpoint, or
2680
- * :greater_or_equal, :equal, :modulo
2681
- */
2682
- static VALUE
2683
- breakpoint_hit_condition(VALUE self)
2684
- {
2685
- debug_breakpoint_t *breakpoint;
2686
-
2687
- Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
2688
- switch(breakpoint->hit_condition)
2689
- {
2690
- case HIT_COND_GE:
2691
- return ID2SYM(rb_intern("greater_or_equal"));
2692
- case HIT_COND_EQ:
2693
- return ID2SYM(rb_intern("equal"));
2694
- case HIT_COND_MOD:
2695
- return ID2SYM(rb_intern("modulo"));
2696
- case HIT_COND_NONE:
2697
- default:
2698
- return Qnil;
2699
- }
2700
- }
2701
-
2702
- /*
2703
- * call-seq:
2704
- * breakpoint.hit_condition = symbol
2705
- *
2706
- * Sets the hit condition of the breakpoint which must be one of the following values:
2707
- *
2708
- * +nil+ if it is an unconditional breakpoint, or
2709
- * :greater_or_equal(:ge), :equal(:eq), :modulo(:mod)
2710
- */
2711
- static VALUE
2712
- breakpoint_set_hit_condition(VALUE self, VALUE value)
2713
- {
2714
- debug_breakpoint_t *breakpoint;
2715
- ID id_value;
2716
-
2717
- Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
2718
- id_value = rb_to_id(value);
2719
-
2720
- if(rb_intern("greater_or_equal") == id_value || rb_intern("ge") == id_value)
2721
- breakpoint->hit_condition = HIT_COND_GE;
2722
- else if(rb_intern("equal") == id_value || rb_intern("eq") == id_value)
2723
- breakpoint->hit_condition = HIT_COND_EQ;
2724
- else if(rb_intern("modulo") == id_value || rb_intern("mod") == id_value)
2725
- breakpoint->hit_condition = HIT_COND_MOD;
2726
- else
2727
- rb_raise(rb_eArgError, "Invalid condition parameter");
2728
- return value;
2729
- }
2730
-
2731
2140
  /*
2732
2141
  * Document-class: Context
2733
2142
  *
@@ -2764,38 +2173,47 @@ Init_context()
2764
2173
  rb_define_method(cContext, "frame_self", context_frame_self, -1);
2765
2174
  rb_define_method(cContext, "stack_size", context_stack_size, 0);
2766
2175
  rb_define_method(cContext, "dead?", context_dead, 0);
2767
- rb_define_method(cContext, "breakpoint", context_breakpoint, 0);
2768
- rb_define_method(cContext, "set_breakpoint", context_set_breakpoint, -1);
2176
+ rb_define_method(cContext, "breakpoint",
2177
+ context_breakpoint, 0); /* in breakpoint.c */
2178
+ rb_define_method(cContext, "set_breakpoint",
2179
+ context_set_breakpoint, -1); /* in breakpoint.c */
2769
2180
  }
2770
2181
 
2771
2182
  /*
2772
- * Document-class: Breakpoint
2773
- *
2774
- * == Summary
2183
+ * call-seq:
2184
+ * Debugger.breakpoints -> array
2775
2185
  *
2776
- * This class represents a breakpoint. It defines position of the breakpoint and
2777
- * condition when this breakpoint should be triggered.
2186
+ * Returns an array of breakpoints.
2778
2187
  */
2779
- static void
2780
- Init_breakpoint()
2781
- {
2782
- cBreakpoint = rb_define_class_under(mDebugger, "Breakpoint", rb_cObject);
2783
- rb_define_method(cBreakpoint, "id", breakpoint_id, 0);
2784
- rb_define_method(cBreakpoint, "source", breakpoint_source, 0);
2785
- rb_define_method(cBreakpoint, "source=", breakpoint_set_source, 1);
2786
- rb_define_method(cBreakpoint, "enabled?", breakpoint_enabled, 0);
2787
- rb_define_method(cBreakpoint, "enabled=", breakpoint_set_enabled, 1);
2788
- rb_define_method(cBreakpoint, "pos", breakpoint_pos, 0);
2789
- rb_define_method(cBreakpoint, "pos=", breakpoint_set_pos, 1);
2790
- rb_define_method(cBreakpoint, "expr", breakpoint_expr, 0);
2791
- rb_define_method(cBreakpoint, "expr=", breakpoint_set_expr, 1);
2792
- rb_define_method(cBreakpoint, "hit_count", breakpoint_hit_count, 0);
2793
- rb_define_method(cBreakpoint, "hit_value", breakpoint_hit_value, 0);
2794
- rb_define_method(cBreakpoint, "hit_value=", breakpoint_set_hit_value, 1);
2795
- rb_define_method(cBreakpoint, "hit_condition", breakpoint_hit_condition, 0);
2796
- rb_define_method(cBreakpoint, "hit_condition=", breakpoint_set_hit_condition, 1);
2188
+ static VALUE
2189
+ debug_breakpoints(VALUE self)
2190
+ {
2191
+ debug_check_started();
2192
+
2193
+ return rdebug_breakpoints;
2797
2194
  }
2798
2195
 
2196
+ /*
2197
+ * call-seq:
2198
+ * Debugger.add_breakpoint(source, pos, condition = nil) -> breakpoint
2199
+ *
2200
+ * Adds a new breakpoint.
2201
+ * <i>source</i> is a name of a file or a class.
2202
+ * <i>pos</i> is a line number or a method name if <i>source</i> is a class name.
2203
+ * <i>condition</i> is a string which is evaluated to +true+ when this breakpoint
2204
+ * is activated.
2205
+ */
2206
+ static VALUE
2207
+ debug_add_breakpoint(int argc, VALUE *argv, VALUE self)
2208
+ {
2209
+ VALUE result;
2210
+
2211
+ debug_check_started();
2212
+
2213
+ result = create_breakpoint_from_args(argc, argv, ++bkp_count);
2214
+ rb_ary_push(rdebug_breakpoints, result);
2215
+ return result;
2216
+ }
2799
2217
 
2800
2218
  /*
2801
2219
  * Document-class: Debugger
@@ -2813,15 +2231,18 @@ Init_ruby_debug()
2813
2231
  {
2814
2232
  mDebugger = rb_define_module("Debugger");
2815
2233
  rb_define_const(mDebugger, "VERSION", rb_str_new2(DEBUG_VERSION));
2816
- rb_define_module_function(mDebugger, "start", debug_start, 0);
2234
+ rb_define_module_function(mDebugger, "start_", debug_start, 0);
2817
2235
  rb_define_module_function(mDebugger, "stop", debug_stop, 0);
2818
2236
  rb_define_module_function(mDebugger, "started?", debug_is_started, 0);
2819
2237
  rb_define_module_function(mDebugger, "breakpoints", debug_breakpoints, 0);
2820
2238
  rb_define_module_function(mDebugger, "add_breakpoint", debug_add_breakpoint, -1);
2821
2239
  rb_define_module_function(mDebugger, "remove_breakpoint",
2822
- debug_remove_breakpoint, 1);
2823
- rb_define_module_function(mDebugger, "catchpoint", debug_catchpoint, 0);
2824
- rb_define_module_function(mDebugger, "catchpoint=", debug_set_catchpoint, 1);
2240
+ rdebug_remove_breakpoint,
2241
+ 1); /* in breakpoint.c */
2242
+ rb_define_module_function(mDebugger, "add_catchpoint",
2243
+ rdebug_add_catchpoint, 1); /* in breakpoint.c */
2244
+ rb_define_module_function(mDebugger, "catchpoints",
2245
+ debug_catchpoints, 0); /* in breakpoint.c */
2825
2246
  rb_define_module_function(mDebugger, "last_context", debug_last_interrupted, 0);
2826
2247
  rb_define_module_function(mDebugger, "contexts", debug_contexts, 0);
2827
2248
  rb_define_module_function(mDebugger, "current_context", debug_current_context, 0);
@@ -2835,8 +2256,10 @@ Init_ruby_debug()
2835
2256
  rb_define_module_function(mDebugger, "debug_at_exit", debug_at_exit, 0);
2836
2257
  rb_define_module_function(mDebugger, "post_mortem?", debug_post_mortem, 0);
2837
2258
  rb_define_module_function(mDebugger, "post_mortem=", debug_set_post_mortem, 1);
2838
- rb_define_module_function(mDebugger, "keep_frame_binding?", debug_keep_frame_binding, 0);
2839
- rb_define_module_function(mDebugger, "keep_frame_binding=", debug_set_keep_frame_binding, 1);
2259
+ rb_define_module_function(mDebugger, "keep_frame_binding?",
2260
+ debug_keep_frame_binding, 0);
2261
+ rb_define_module_function(mDebugger, "keep_frame_binding=",
2262
+ debug_set_keep_frame_binding, 1);
2840
2263
  rb_define_module_function(mDebugger, "track_frame_args?",
2841
2264
  debug_track_frame_args, 0);
2842
2265
  rb_define_module_function(mDebugger, "track_frame_args=",
@@ -2847,24 +2270,25 @@ Init_ruby_debug()
2847
2270
  cThreadsTable = rb_define_class_under(mDebugger, "ThreadsTable", rb_cObject);
2848
2271
 
2849
2272
  cDebugThread = rb_define_class_under(mDebugger, "DebugThread", rb_cThread);
2850
- rb_define_singleton_method(cDebugThread, "inherited", debug_thread_inherited, 1);
2273
+ rb_define_singleton_method(cDebugThread, "inherited",
2274
+ debug_thread_inherited, 1);
2851
2275
 
2852
2276
  Init_context();
2853
2277
  Init_breakpoint();
2854
2278
 
2855
- idAtLine = rb_intern("at_line");
2856
2279
  idAtBreakpoint = rb_intern("at_breakpoint");
2857
2280
  idAtCatchpoint = rb_intern("at_catchpoint");
2281
+ idAtLine = rb_intern("at_line");
2282
+ idAtReturn = rb_intern("at_return");
2858
2283
  idAtTracing = rb_intern("at_tracing");
2859
- idEval = rb_intern("eval");
2860
2284
  idList = rb_intern("list");
2861
2285
 
2862
2286
  rb_mObjectSpace = rb_const_get(rb_mKernel, rb_intern("ObjectSpace"));
2863
2287
 
2864
- rb_global_variable(&threads_tbl);
2865
- rb_global_variable(&breakpoints);
2866
- rb_global_variable(&catchpoint);
2867
- rb_global_variable(&locker);
2868
2288
  rb_global_variable(&last_context);
2869
2289
  rb_global_variable(&last_thread);
2290
+ rb_global_variable(&locker);
2291
+ rb_global_variable(&rdebug_breakpoints);
2292
+ rb_global_variable(&rdebug_catchpoints);
2293
+ rb_global_variable(&rdebug_threads_tbl);
2870
2294
  }