ruby-debug 0.4.3 → 0.4.4

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES CHANGED
@@ -1,3 +1,8 @@
1
+ 0.4.4
2
+ - Renamed Context#set_suspend and Context#clear_suspend methods to Context#suspend and Context#resume respectively.
3
+ - Context#resume method not only clears suspend flag, but also resumes the thread execution.
4
+ - Bugfixes.
5
+
1
6
  0.4.3
2
7
  - Added Debugger.skip method which allows escaping a block from the debugger reach.
3
8
  - Bugfixes.
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.3"
8
+ RUBY_DEBUG_VERSION = open("ext/ruby_debug.c"){|f| f.grep(/^#define DEBUG_VERSION/).first[/"(.+)"/,1]}
9
9
 
10
10
  FILES = FileList[
11
11
  'Rakefile',
data/bin/rdebug CHANGED
@@ -29,6 +29,9 @@ EOB
29
29
  opts.on("-c", "--client", "Connect to remote debugger") {options.client = true}
30
30
  opts.on("-h", "--host HOST", "Host name used for remote debugging") {|options.host|}
31
31
  opts.on("-p", "--port PORT", Integer, "Port used for remote debugging") {|options.port|}
32
+ opts.on("-I", "--include PATH", String, "Add PATH to $LOAD_PATH") do |path|
33
+ $LOAD_PATH.unshift(path)
34
+ end
32
35
  opts.on("--script FILE", String, "Name of the script file to run") do |options.script|
33
36
  unless File.exists?(options.script)
34
37
  puts "Script file '#{options.script}' is not found"
data/ext/ruby_debug.c CHANGED
@@ -4,21 +4,35 @@
4
4
  #include <rubysig.h>
5
5
  #include <st.h>
6
6
 
7
- #define DEBUG_VERSION "0.4.3"
7
+ #define DEBUG_VERSION "0.4.4"
8
+
9
+ #define CTX_FL_MOVED (1<<1)
10
+ #define CTX_FL_SUSPEND (1<<2)
11
+ #define CTX_FL_TRACING (1<<3)
12
+ #define CTX_FL_SKIPPED (1<<4)
13
+ #define CTX_FL_IGNORE (1<<5)
14
+
15
+ #define CTX_FL_TEST(c,f) ((c)->flags & (f))
16
+ #define CTX_FL_SET(c,f) do { (c)->flags |= (f); } while (0)
17
+ #define CTX_FL_UNSET(c,f) do { (c)->flags &= ~(f); } while (0)
18
+
19
+ #define DID_MOVED (debug_context->last_line != line || \
20
+ debug_context->last_file == Qnil || \
21
+ rb_str_cmp(debug_context->last_file, file) != 0)
22
+
23
+ #define IS_STARTED (threads_tbl != Qnil)
8
24
 
9
25
  typedef struct {
10
26
  int thnum;
11
- VALUE last_file;
12
- VALUE last_line;
13
- int moved;
27
+ int flags;
14
28
  int stop_next;
15
29
  int dest_frame;
16
30
  int stop_line;
17
31
  int stop_frame;
18
- int suspend;
19
- int tracing;
20
32
  VALUE frames;
21
33
  VALUE thread;
34
+ VALUE last_file;
35
+ VALUE last_line;
22
36
  } debug_context_t;
23
37
 
24
38
  typedef struct {
@@ -34,14 +48,18 @@ typedef struct {
34
48
  VALUE expr;
35
49
  } debug_breakpoint_t;
36
50
 
51
+ typedef struct {
52
+ st_table *tbl;
53
+ } threads_table_t;
54
+
37
55
  static VALUE threads_tbl = Qnil;
38
56
  static VALUE breakpoints = Qnil;
39
57
  static VALUE catchpoint = Qnil;
40
- static VALUE waiting = Qnil;
41
58
  static VALUE tracing = Qfalse;
42
59
  static VALUE locker = Qnil;
43
60
 
44
61
  static VALUE mDebugger;
62
+ static VALUE cThreadsTable;
45
63
  static VALUE cContext;
46
64
  static VALUE cFrame;
47
65
  static VALUE cBreakpoint;
@@ -64,7 +82,6 @@ static int start_count = 0;
64
82
  static int thnum_max = 0;
65
83
  static int last_debugged_thnum = -1;
66
84
 
67
- static VALUE debug_suspend(VALUE);
68
85
  static VALUE create_binding(VALUE);
69
86
  static VALUE debug_stop(VALUE);
70
87
 
@@ -126,7 +143,72 @@ remove_from_locked()
126
143
  return thread;
127
144
  }
128
145
 
129
- #define IS_STARTED (threads_tbl != Qnil)
146
+ static int
147
+ thread_hash(VALUE thread)
148
+ {
149
+ return (int)FIX2LONG(rb_obj_id(thread));
150
+ }
151
+
152
+ static int
153
+ thread_cmp(VALUE a, VALUE b)
154
+ {
155
+ if(a == b) return 0;
156
+ if(a < b) return -1;
157
+ return 1;
158
+ }
159
+
160
+ static struct st_hash_type st_thread_hash = {
161
+ thread_cmp,
162
+ thread_hash
163
+ };
164
+
165
+ static int
166
+ threads_table_mark_keyvalue(VALUE key, VALUE value, int dummy)
167
+ {
168
+ rb_gc_mark(key);
169
+ rb_gc_mark(value);
170
+ return ST_CONTINUE;
171
+ }
172
+
173
+ static void
174
+ threads_table_mark(void* data)
175
+ {
176
+ threads_table_t *threads_table = (threads_table_t*)data;
177
+ st_foreach(threads_table->tbl, threads_table_mark_keyvalue, 0);
178
+ }
179
+
180
+ static void
181
+ threads_table_free(void* data)
182
+ {
183
+ threads_table_t *threads_table = (threads_table_t*)data;
184
+ st_free_table(threads_table->tbl);
185
+ xfree(threads_table);
186
+ }
187
+
188
+ static VALUE
189
+ threads_table_create()
190
+ {
191
+ threads_table_t *threads_table;
192
+
193
+ threads_table = ALLOC(threads_table_t);
194
+ threads_table->tbl = st_init_table(&st_thread_hash);
195
+ return Data_Wrap_Struct(cThreadsTable, threads_table_mark, threads_table_free, threads_table);
196
+ }
197
+
198
+ static int
199
+ threads_table_clear_i(VALUE key, VALUE value, VALUE dummy)
200
+ {
201
+ return ST_DELETE;
202
+ }
203
+
204
+ static void
205
+ threads_table_clear(VALUE table)
206
+ {
207
+ threads_table_t *threads_table;
208
+
209
+ Data_Get_Struct(table, threads_table_t, threads_table);
210
+ st_foreach(threads_table->tbl, threads_table_clear_i, 0);
211
+ }
130
212
 
131
213
  /*
132
214
  * call-seq:
@@ -170,14 +252,12 @@ debug_context_create(VALUE thread)
170
252
 
171
253
  debug_context->last_file = Qnil;
172
254
  debug_context->last_line = Qnil;
173
- debug_context->moved = 0;
255
+ debug_context->flags = 0;
174
256
 
175
257
  debug_context->stop_next = -1;
176
258
  debug_context->dest_frame = -1;
177
259
  debug_context->stop_line = -1;
178
260
  debug_context->stop_frame = -1;
179
- debug_context->suspend = 0;
180
- debug_context->tracing = 0;
181
261
  debug_context->frames = rb_ary_new();
182
262
  debug_context->thread = thread;
183
263
  result = Data_Wrap_Struct(cContext, debug_context_mark, xfree, debug_context);
@@ -188,14 +268,15 @@ static VALUE
188
268
  thread_context_lookup(VALUE thread)
189
269
  {
190
270
  VALUE context;
271
+ threads_table_t *threads_table;
191
272
 
192
273
  debug_check_started();
193
274
 
194
- context = rb_hash_aref(threads_tbl, thread);
195
- if(context == Qnil)
275
+ Data_Get_Struct(threads_tbl, threads_table_t, threads_table);
276
+ if(!st_lookup(threads_table->tbl, thread, &context))
196
277
  {
197
- context = debug_context_create(thread);
198
- rb_hash_aset(threads_tbl, thread, context);
278
+ context = debug_context_create(thread);
279
+ st_insert(threads_table->tbl, thread, context);
199
280
  }
200
281
  return context;
201
282
  }
@@ -241,13 +322,9 @@ save_current_position(VALUE context)
241
322
 
242
323
  debug_context->last_file = debug_frame->file;
243
324
  debug_context->last_line = debug_frame->line;
244
- debug_context->moved = 0;
325
+ CTX_FL_UNSET(debug_context, CTX_FL_MOVED);
245
326
  }
246
327
 
247
- #define did_moved() (debug_context->last_line != line || \
248
- debug_context->last_file == Qnil || \
249
- rb_str_cmp(debug_context->last_file, file) != 0)
250
-
251
328
  static VALUE
252
329
  call_at_line_unprotected(VALUE args)
253
330
  {
@@ -263,7 +340,6 @@ call_at_line(VALUE context, int thnum, VALUE binding, VALUE file, VALUE line)
263
340
 
264
341
  last_debugged_thnum = thnum;
265
342
  save_current_position(context);
266
- debug_suspend(mDebugger);
267
343
 
268
344
  args = rb_ary_new3(4, context, file, line, binding);
269
345
  return rb_protect(call_at_line_unprotected, args, 0);
@@ -330,7 +406,7 @@ check_breakpoints(debug_context_t *debug_context, VALUE file, VALUE klass, VALUE
330
406
 
331
407
  if(RARRAY(breakpoints)->len == 0)
332
408
  return -1;
333
- if(!debug_context->moved)
409
+ if(!CTX_FL_TEST(debug_context, CTX_FL_MOVED))
334
410
  return -1;
335
411
 
336
412
  for(i = 0; i < RARRAY(breakpoints)->len; i++)
@@ -366,23 +442,6 @@ create_binding(VALUE self)
366
442
  return f_binding(self);
367
443
  }
368
444
 
369
- static void
370
- check_suspend(debug_context_t *debug_context)
371
- {
372
- if(rb_thread_critical == Qtrue)
373
- return;
374
- while(1)
375
- {
376
- rb_thread_critical = Qtrue;
377
- if(!debug_context->suspend)
378
- break;
379
- rb_ary_push(waiting, rb_thread_current());
380
- debug_context->suspend = 0;
381
- rb_thread_stop();
382
- }
383
- rb_thread_critical = Qfalse;
384
- }
385
-
386
445
  static VALUE
387
446
  get_breakpoint_at(int index)
388
447
  {
@@ -422,25 +481,45 @@ debug_event_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass)
422
481
  if(!node) return;
423
482
 
424
483
  thread = rb_thread_current();
425
- while(locker != Qnil && locker != thread)
484
+ context = thread_context_lookup(thread);
485
+ Data_Get_Struct(context, debug_context_t, debug_context);
486
+
487
+ /* return if thread is marked as 'ignored'.
488
+ debugger's threads are marked this way
489
+ */
490
+ if(CTX_FL_TEST(debug_context, CTX_FL_IGNORE)) return;
491
+
492
+ while(1)
426
493
  {
427
- add_to_locked(thread);
428
- rb_thread_stop();
494
+ /* halt execution of the current thread if the debugger
495
+ is activated in another
496
+ */
497
+ while(locker != Qnil && locker != thread)
498
+ {
499
+ add_to_locked(thread);
500
+ rb_thread_stop();
501
+ }
502
+
503
+ /* stop the current thread if it's marked as suspended */
504
+ if(CTX_FL_TEST(debug_context, CTX_FL_SUSPEND))
505
+ rb_thread_stop();
506
+ else break;
429
507
  }
430
508
 
509
+ /* return if the current thread is the locker */
431
510
  if(locker != Qnil) return;
511
+
512
+ /* only the current thread can proceed */
513
+ locker = thread;
432
514
 
433
- locker = rb_thread_current();
434
-
435
- context = thread_context_lookup(thread);
436
- Data_Get_Struct(context, debug_context_t, debug_context);
437
- check_suspend(debug_context);
515
+ /* ignore a skipped section of code */
516
+ if(CTX_FL_TEST(debug_context, CTX_FL_SKIPPED)) goto cleanup;
438
517
 
439
518
  file = rb_str_new2(node->nd_file);
440
519
  line = INT2FIX(nd_line(node));
441
520
 
442
- if(did_moved())
443
- debug_context->moved = 1;
521
+ if(DID_MOVED)
522
+ CTX_FL_SET(debug_context, CTX_FL_MOVED);
444
523
 
445
524
  switch(event)
446
525
  {
@@ -448,7 +527,7 @@ debug_event_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass)
448
527
  {
449
528
  set_frame_source(debug_context, file, line);
450
529
 
451
- if(RTEST(tracing) || debug_context->tracing )
530
+ if(RTEST(tracing) || CTX_FL_TEST(debug_context, CTX_FL_TRACING))
452
531
  {
453
532
  rb_funcall(context, idAtTracing, 2, file, line);
454
533
  }
@@ -460,7 +539,7 @@ debug_event_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass)
460
539
  if(debug_context->stop_next < 0)
461
540
  debug_context->stop_next = -1;
462
541
  /* we check that we actualy moved to another line */
463
- if(did_moved())
542
+ if(DID_MOVED)
464
543
  {
465
544
  debug_context->stop_line--;
466
545
  }
@@ -574,17 +653,21 @@ debug_event_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass)
574
653
  }
575
654
  }
576
655
 
656
+ cleanup:
657
+
658
+ /* release a lock */
577
659
  locker = Qnil;
660
+ /* let the next thread to run */
578
661
  thread = remove_from_locked();
579
662
  if(thread != Qnil)
580
663
  rb_thread_run(thread);
581
664
  }
582
665
 
583
666
  static VALUE
584
- debug_stop_i(VALUE value)
667
+ debug_stop_i(VALUE self)
585
668
  {
586
669
  if(IS_STARTED)
587
- debug_stop(value);
670
+ debug_stop(self);
588
671
  return Qnil;
589
672
  }
590
673
 
@@ -595,8 +678,8 @@ debug_stop_i(VALUE value)
595
678
  *
596
679
  * This method activates the debugger.
597
680
  * If it's called without a block it returns +true+, unless debugger was already started.
598
- * If a block is given, it starts debugger and yields to block. At the end of stops the debugger
599
- * with Debugger.stop method.
681
+ * If a block is given, it starts debugger and yields to block. When the block is finished
682
+ * executing it stops the debugger with Debugger.stop method.
600
683
  *
601
684
  * <i>Note that if you want to stop debugger, you must call Debugger.stop as many time as you
602
685
  * called Debugger.start method.</i>
@@ -604,22 +687,24 @@ debug_stop_i(VALUE value)
604
687
  static VALUE
605
688
  debug_start(VALUE self)
606
689
  {
690
+ VALUE result;
607
691
  start_count++;
608
692
 
609
693
  if(IS_STARTED)
610
- return Qfalse;
611
-
612
- threads_tbl = rb_hash_new();
613
- breakpoints = rb_ary_new();
614
- waiting = rb_ary_new();
615
- locker = Qnil;
694
+ result = Qfalse;
695
+ else
696
+ {
697
+ breakpoints = rb_ary_new();
698
+ locker = Qnil;
699
+ threads_tbl = threads_table_create();
616
700
 
617
- rb_add_event_hook(debug_event_hook, RUBY_EVENT_ALL);
701
+ rb_add_event_hook(debug_event_hook, RUBY_EVENT_ALL);
702
+ result = Qtrue;
703
+ }
618
704
 
619
705
  if(rb_block_given_p())
620
706
  return rb_ensure(rb_yield, Qnil, debug_stop_i, self);
621
-
622
- return Qtrue;
707
+ return result;
623
708
  }
624
709
 
625
710
  /*
@@ -643,7 +728,6 @@ debug_stop(VALUE self)
643
728
 
644
729
  rb_remove_event_hook(debug_event_hook);
645
730
 
646
- waiting = Qnil;
647
731
  locker = Qnil;
648
732
  breakpoints = Qnil;
649
733
  threads_tbl = Qnil;
@@ -767,10 +851,13 @@ static VALUE
767
851
  debug_last_interrupted(VALUE self)
768
852
  {
769
853
  VALUE result = Qnil;
854
+ threads_table_t *threads_table;
770
855
 
771
856
  debug_check_started();
772
857
 
773
- rb_hash_foreach(threads_tbl, find_last_context_func, (st_data_t)&result);
858
+ Data_Get_Struct(threads_tbl, threads_table_t, threads_table);
859
+
860
+ st_foreach(threads_table->tbl, find_last_context_func, (st_data_t)&result);
774
861
  return result;
775
862
  }
776
863
 
@@ -806,6 +893,7 @@ debug_contexts(VALUE self)
806
893
  volatile VALUE list;
807
894
  volatile VALUE new_list;
808
895
  VALUE thread, context;
896
+ threads_table_t *threads_table;
809
897
  debug_context_t *debug_context;
810
898
  int i;
811
899
 
@@ -819,15 +907,13 @@ debug_contexts(VALUE self)
819
907
  context = thread_context_lookup(thread);
820
908
  rb_ary_push(new_list, context);
821
909
  }
822
- /*
823
- * I wonder why rb_hash_clear is declared static?
824
- */
825
- rb_funcall(threads_tbl, idClear, 0);
910
+ threads_table_clear(threads_tbl);
911
+ Data_Get_Struct(threads_tbl, threads_table_t, threads_table);
826
912
  for(i = 0; i < RARRAY(new_list)->len; i++)
827
913
  {
828
914
  context = rb_ary_entry(new_list, i);
829
915
  Data_Get_Struct(context, debug_context_t, debug_context);
830
- rb_hash_aset(threads_tbl, debug_context->thread, context);
916
+ st_insert(threads_table->tbl, debug_context->thread, context);
831
917
  }
832
918
 
833
919
  return new_list;
@@ -861,7 +947,7 @@ debug_suspend(VALUE self)
861
947
  if(current == context)
862
948
  continue;
863
949
  Data_Get_Struct(context, debug_context_t, debug_context);
864
- debug_context->suspend = 1;
950
+ CTX_FL_SET(debug_context, CTX_FL_SUSPEND);
865
951
  }
866
952
  rb_thread_critical = saved_crit;
867
953
 
@@ -882,7 +968,6 @@ debug_resume(VALUE self)
882
968
  {
883
969
  VALUE current, context;
884
970
  VALUE saved_crit;
885
- VALUE thread;
886
971
  VALUE context_list;
887
972
  debug_context_t *debug_context;
888
973
  int i;
@@ -900,14 +985,12 @@ debug_resume(VALUE self)
900
985
  if(current == context)
901
986
  continue;
902
987
  Data_Get_Struct(context, debug_context_t, debug_context);
903
- debug_context->suspend = 0;
904
- }
905
- for(i = 0; i < RARRAY(waiting)->len; i++)
906
- {
907
- thread = rb_ary_entry(waiting, i);
908
- rb_thread_run(thread);
988
+ if(CTX_FL_TEST(debug_context, CTX_FL_SUSPEND))
989
+ {
990
+ CTX_FL_UNSET(debug_context, CTX_FL_SUSPEND);
991
+ rb_thread_run(debug_context->thread);
992
+ }
909
993
  }
910
- rb_ary_clear(waiting);
911
994
  rb_thread_critical = saved_crit;
912
995
 
913
996
  rb_thread_schedule();
@@ -965,9 +1048,17 @@ debug_debug_load(VALUE self, VALUE file)
965
1048
  }
966
1049
 
967
1050
  static VALUE
968
- debug_skip_i(VALUE value)
1051
+ set_current_skipped_status(VALUE status)
969
1052
  {
970
- rb_add_event_hook(debug_event_hook, RUBY_EVENT_ALL);
1053
+ VALUE context;
1054
+ debug_context_t *debug_context;
1055
+
1056
+ context = debug_current_context(Qnil);
1057
+ Data_Get_Struct(context, debug_context_t, debug_context);
1058
+ if(status)
1059
+ CTX_FL_SET(debug_context, CTX_FL_SKIPPED);
1060
+ else
1061
+ CTX_FL_UNSET(debug_context, CTX_FL_SKIPPED);
971
1062
  return Qnil;
972
1063
  }
973
1064
 
@@ -985,8 +1076,8 @@ debug_skip(VALUE self)
985
1076
  }
986
1077
  if(!IS_STARTED)
987
1078
  return rb_yield(Qnil);
988
- rb_remove_event_hook(debug_event_hook);
989
- return rb_ensure(rb_yield, Qnil, debug_skip_i, Qnil);
1079
+ set_current_skipped_status(Qtrue);
1080
+ return rb_ensure(rb_yield, Qnil, set_current_skipped_status, Qfalse);
990
1081
  }
991
1082
 
992
1083
  static VALUE
@@ -1004,8 +1095,8 @@ debug_at_exit_i(VALUE proc)
1004
1095
  }
1005
1096
  else
1006
1097
  {
1007
- rb_remove_event_hook(debug_event_hook);
1008
- rb_ensure(debug_at_exit_c, proc, debug_skip_i, Qnil);
1098
+ set_current_skipped_status(Qtrue);
1099
+ rb_ensure(debug_at_exit_c, proc, set_current_skipped_status, Qfalse);
1009
1100
  }
1010
1101
  }
1011
1102
 
@@ -1151,37 +1242,42 @@ context_thnum(VALUE self)
1151
1242
 
1152
1243
  /*
1153
1244
  * call-seq:
1154
- * context.set_suspend -> nil
1245
+ * context.suspend -> nil
1155
1246
  *
1156
1247
  * Suspends the thread when it is running.
1157
1248
  */
1158
1249
  static VALUE
1159
- context_set_suspend(VALUE self)
1250
+ context_suspend(VALUE self)
1160
1251
  {
1161
1252
  debug_context_t *debug_context;
1162
1253
 
1163
1254
  debug_check_started();
1164
1255
 
1165
1256
  Data_Get_Struct(self, debug_context_t, debug_context);
1166
- debug_context->suspend = 1;
1257
+ if(CTX_FL_TEST(debug_context, CTX_FL_SUSPEND))
1258
+ rb_raise(rb_eRuntimeError, "Already suspended.");
1259
+ CTX_FL_SET(debug_context, CTX_FL_SUSPEND);
1167
1260
  return Qnil;
1168
1261
  }
1169
1262
 
1170
1263
  /*
1171
1264
  * call-seq:
1172
- * context.clear_suspend -> nil
1265
+ * context.resume -> nil
1173
1266
  *
1174
- * Clears a suspend flag.
1267
+ * Resumes the thread from the suspended mode.
1175
1268
  */
1176
1269
  static VALUE
1177
- context_clear_suspend(VALUE self)
1270
+ context_resume(VALUE self)
1178
1271
  {
1179
1272
  debug_context_t *debug_context;
1180
1273
 
1181
1274
  debug_check_started();
1182
1275
 
1183
1276
  Data_Get_Struct(self, debug_context_t, debug_context);
1184
- debug_context->suspend = 0;
1277
+ if(!CTX_FL_TEST(debug_context, CTX_FL_SUSPEND))
1278
+ rb_raise(rb_eRuntimeError, "Thread is not suspended.");
1279
+ CTX_FL_UNSET(debug_context, CTX_FL_SUSPEND);
1280
+ rb_thread_run(debug_context->thread);
1185
1281
  return Qnil;
1186
1282
  }
1187
1283
 
@@ -1199,7 +1295,7 @@ context_tracing(VALUE self)
1199
1295
  debug_check_started();
1200
1296
 
1201
1297
  Data_Get_Struct(self, debug_context_t, debug_context);
1202
- return debug_context->tracing ? Qtrue : Qfalse;
1298
+ return CTX_FL_TEST(debug_context, CTX_FL_TRACING) ? Qtrue : Qfalse;
1203
1299
  }
1204
1300
 
1205
1301
  /*
@@ -1216,7 +1312,48 @@ context_set_tracing(VALUE self, VALUE value)
1216
1312
  debug_check_started();
1217
1313
 
1218
1314
  Data_Get_Struct(self, debug_context_t, debug_context);
1219
- debug_context->tracing = RTEST(value) ? 1 : 0;
1315
+ if(RTEST(value))
1316
+ CTX_FL_SET(debug_context, CTX_FL_TRACING);
1317
+ else
1318
+ CTX_FL_UNSET(debug_context, CTX_FL_TRACING);
1319
+ return value;
1320
+ }
1321
+
1322
+ /*
1323
+ * call-seq:
1324
+ * context.ignore -> bool
1325
+ *
1326
+ * Returns the ignore flag for the current context.
1327
+ */
1328
+ static VALUE
1329
+ context_ignore(VALUE self)
1330
+ {
1331
+ debug_context_t *debug_context;
1332
+
1333
+ debug_check_started();
1334
+
1335
+ Data_Get_Struct(self, debug_context_t, debug_context);
1336
+ return CTX_FL_TEST(debug_context, CTX_FL_IGNORE) ? Qtrue : Qfalse;
1337
+ }
1338
+
1339
+ /*
1340
+ * call-seq:
1341
+ * context.tracking = bool
1342
+ *
1343
+ * Controls the ignore flag for this context.
1344
+ */
1345
+ static VALUE
1346
+ context_set_ignore(VALUE self, VALUE value)
1347
+ {
1348
+ debug_context_t *debug_context;
1349
+
1350
+ debug_check_started();
1351
+
1352
+ Data_Get_Struct(self, debug_context_t, debug_context);
1353
+ if(RTEST(value))
1354
+ CTX_FL_SET(debug_context, CTX_FL_IGNORE);
1355
+ else
1356
+ CTX_FL_UNSET(debug_context, CTX_FL_IGNORE);
1220
1357
  return value;
1221
1358
  }
1222
1359
 
@@ -1344,10 +1481,12 @@ Init_context()
1344
1481
  rb_define_method(cContext, "frames", context_frames, 0);
1345
1482
  rb_define_method(cContext, "thread", context_thread, 0);
1346
1483
  rb_define_method(cContext, "thnum", context_thnum, 0);
1347
- rb_define_method(cContext, "set_suspend", context_set_suspend, 0);
1348
- rb_define_method(cContext, "clear_suspend", context_clear_suspend, 0);
1484
+ rb_define_method(cContext, "suspend", context_suspend, 0);
1485
+ rb_define_method(cContext, "resume", context_resume, 0);
1349
1486
  rb_define_method(cContext, "tracing", context_tracing, 0);
1350
1487
  rb_define_method(cContext, "tracing=", context_set_tracing, 1);
1488
+ rb_define_method(cContext, "ignore", context_ignore, 0);
1489
+ rb_define_method(cContext, "ignore=", context_set_ignore, 1);
1351
1490
  }
1352
1491
 
1353
1492
  /*
@@ -1418,6 +1557,8 @@ Init_ruby_debug()
1418
1557
  rb_define_module_function(mDebugger, "skip", debug_skip, 0);
1419
1558
  rb_define_module_function(mDebugger, "debug_at_exit", debug_at_exit, 0);
1420
1559
 
1560
+ cThreadsTable = rb_define_class_under(mDebugger, "ThreadsTable", rb_cObject);
1561
+
1421
1562
  Init_context();
1422
1563
  Init_frame();
1423
1564
  Init_breakpoint();
@@ -1439,7 +1580,6 @@ Init_ruby_debug()
1439
1580
  rb_global_variable(&threads_tbl);
1440
1581
  rb_global_variable(&breakpoints);
1441
1582
  rb_global_variable(&catchpoint);
1442
- rb_global_variable(&waiting);
1443
1583
  rb_global_variable(&locker);
1444
1584
  rb_global_variable(&file_separator);
1445
1585
  rb_global_variable(&alt_file_separator);
data/lib/ruby-debug.rb CHANGED
@@ -2,13 +2,11 @@ require 'pp'
2
2
  require 'stringio'
3
3
  require 'thread'
4
4
  require 'ruby_debug.so'
5
- require 'ruby-debug/lock'
6
5
  require 'ruby-debug/processor'
7
6
 
8
7
  SCRIPT_LINES__ = {} unless defined? SCRIPT_LINES__
9
8
 
10
9
  module Debugger
11
- MUTEX = Lock.new
12
10
  PORT = 8989
13
11
 
14
12
  @processor = CommandProcessor.new
@@ -37,10 +35,7 @@ module Debugger
37
35
  end
38
36
 
39
37
  def at_line(file, line, binding)
40
- MUTEX.lock
41
38
  processor.at_line(self, file, line, binding)
42
- MUTEX.unlock
43
- Debugger.resume
44
39
  end
45
40
  end
46
41
 
@@ -97,6 +92,7 @@ module Debugger
97
92
  end
98
93
 
99
94
  @control_thread = Thread.start do
95
+ current_context.ignore = true
100
96
  server = TCPServer.new(host, ctrl_port)
101
97
  while (session = server.accept)
102
98
  interface = RemoteInterface.new(session)
@@ -109,6 +105,7 @@ module Debugger
109
105
  proceed = ConditionVariable.new
110
106
 
111
107
  @thread = Thread.start do
108
+ current_context.ignore = true
112
109
  server = TCPServer.new(host, cmd_port)
113
110
  while (session = server.accept)
114
111
  self.interface = RemoteInterface.new(session)
@@ -36,10 +36,6 @@ module Debugger
36
36
  self.always_run = true
37
37
  include DisplayFunctions
38
38
 
39
- def initialize(state)
40
- super
41
- end
42
-
43
39
  def regexp
44
40
  /^\s*disp(?:lay)?$/
45
41
  end
@@ -100,7 +100,7 @@ module Debugger
100
100
  print "Already stopped.\n"
101
101
  else
102
102
  display_context(c)
103
- c.set_suspend
103
+ c.suspend
104
104
  end
105
105
  end
106
106
 
@@ -160,7 +160,7 @@ module Debugger
160
160
  print "Already running."
161
161
  else
162
162
  display_context(c)
163
- c.thread.run
163
+ c.resume
164
164
  end
165
165
  end
166
166
 
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.3
7
- date: 2006-10-09 17:56:47 -04:00
6
+ version: 0.4.4
7
+ date: 2006-10-15 18:26:58 -04:00
8
8
  summary: Fast Ruby debugger
9
9
  require_paths:
10
10
  - lib
@@ -38,7 +38,6 @@ files:
38
38
  - lib/ruby-debug/command.rb
39
39
  - lib/ruby-debug/commands
40
40
  - lib/ruby-debug/interface.rb
41
- - lib/ruby-debug/lock.rb
42
41
  - lib/ruby-debug/processor.rb
43
42
  - lib/ruby-debug/commands/breakpoints.rb
44
43
  - lib/ruby-debug/commands/catchpoint.rb
@@ -1,41 +0,0 @@
1
- module Debugger
2
- class Lock # :nodoc:
3
- def initialize
4
- @locker = nil
5
- @waiting = []
6
- @locked = false;
7
- end
8
-
9
- def locked?
10
- @locked
11
- end
12
-
13
- def lock
14
- return if Thread.critical
15
- return if @locker == Thread.current
16
- while (Thread.critical = true; @locked)
17
- @waiting.push Thread.current
18
- Thread.stop
19
- end
20
- @locked = true
21
- @locker = Thread.current
22
- Thread.critical = false
23
- self
24
- end
25
-
26
- def unlock
27
- return if Thread.critical
28
- return unless @locked
29
- unless @locker == Thread.current
30
- raise RuntimeError, "unlocked by other"
31
- end
32
- Thread.critical = true
33
- t = @waiting.shift
34
- @locked = false
35
- @locker = nil
36
- Thread.critical = false
37
- t.run if t
38
- self
39
- end
40
- end
41
- end