ruby-debug 0.4.2-mswin32 → 0.4.3-mswin32
Sign up to get free protection for your applications and to get access to all the features.
- 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
|