ruby-debug 0.4.2-mswin32 → 0.4.3-mswin32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGES +4 -0
- data/Rakefile +1 -1
- data/bin/rdebug +3 -1
- data/ext/ruby_debug.c +175 -16
- data/lib/ruby-debug.rb +0 -1
- data/lib/ruby-debug/interface.rb +17 -17
- data/lib/ruby_debug.so +0 -0
- metadata +2 -2
data/CHANGES
CHANGED
data/Rakefile
CHANGED
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.
|
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
|
-
|
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
|
-
|
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,
|
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
|
-
|
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
|
-
|
841
|
-
|
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
data/lib/ruby-debug/interface.rb
CHANGED
@@ -19,25 +19,26 @@ module Debugger
|
|
19
19
|
|
20
20
|
begin
|
21
21
|
require 'readline'
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
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
|
-
|
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
|
|
data/lib/ruby_debug.so
CHANGED
Binary file
|
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.
|
7
|
-
date: 2006-09
|
6
|
+
version: 0.4.3
|
7
|
+
date: 2006-10-09 18:04:00 -04:00
|
8
8
|
summary: Fast Ruby debugger
|
9
9
|
require_paths:
|
10
10
|
- lib
|