ruby-debug 0.7.1-mswin32 → 0.7.2-mswin32
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +8 -0
- data/ext/ruby_debug.c +69 -12
- data/lib/ruby-debug.rb +2 -0
- data/lib/ruby-debug/processor.rb +17 -1
- data/lib/ruby_debug.so +0 -0
- metadata +2 -2
data/CHANGES
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
0.7.2
|
2
|
+
- Fixed a case when a frame is not popped up properly (ruby's bug!).
|
3
|
+
- Fixed Context#resume (a thread should be waked up only when it was running when it wsa suspened).
|
4
|
+
- When handling post-mortem exception, all threads must be suspended.
|
5
|
+
|
6
|
+
0.7.1
|
7
|
+
- Fixed 'delete' command
|
8
|
+
|
1
9
|
0.7
|
2
10
|
- Eliminated explicit Frame object. Use Context.frame_[binding,file,line] instead.
|
3
11
|
- Fixed help command.
|
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.7.
|
7
|
+
#define DEBUG_VERSION "0.7.2"
|
8
8
|
|
9
9
|
#ifdef _WIN32
|
10
10
|
struct FRAME {
|
@@ -48,6 +48,7 @@ RUBY_EXTERN struct RVarmap *ruby_dyna_vars;
|
|
48
48
|
#define CTX_FL_SKIPPED (1<<4)
|
49
49
|
#define CTX_FL_IGNORE (1<<5)
|
50
50
|
#define CTX_FL_DEAD (1<<6)
|
51
|
+
#define CTX_FL_WAS_RUNNING (1<<7)
|
51
52
|
|
52
53
|
#define CTX_FL_TEST(c,f) ((c)->flags & (f))
|
53
54
|
#define CTX_FL_SET(c,f) do { (c)->flags |= (f); } while (0)
|
@@ -156,6 +157,8 @@ static VALUE create_binding(VALUE);
|
|
156
157
|
static VALUE debug_stop(VALUE);
|
157
158
|
static void save_current_position(debug_context_t *);
|
158
159
|
static VALUE context_copy_locals(debug_frame_t *);
|
160
|
+
static void context_suspend_0(debug_context_t *);
|
161
|
+
static void context_resume_0(debug_context_t *);
|
159
162
|
|
160
163
|
typedef struct locked_thread_t {
|
161
164
|
VALUE thread_id;
|
@@ -521,6 +524,7 @@ save_call_frame(VALUE self, char *file, int line, ID mid, debug_context_t *debug
|
|
521
524
|
debug_frame->self = self;
|
522
525
|
debug_frame->info.runtime.frame = ruby_frame;
|
523
526
|
debug_frame->info.runtime.scope = ruby_scope;
|
527
|
+
|
524
528
|
debug_frame->info.runtime.dyna_vars = ruby_dyna_vars;
|
525
529
|
}
|
526
530
|
|
@@ -711,6 +715,32 @@ save_current_position(debug_context_t *debug_context)
|
|
711
715
|
CTX_FL_UNSET(debug_context, CTX_FL_MOVED);
|
712
716
|
}
|
713
717
|
|
718
|
+
static char *
|
719
|
+
get_event_name(rb_event_t event)
|
720
|
+
{
|
721
|
+
switch (event) {
|
722
|
+
case RUBY_EVENT_LINE:
|
723
|
+
return "line";
|
724
|
+
case RUBY_EVENT_CLASS:
|
725
|
+
return "class";
|
726
|
+
case RUBY_EVENT_END:
|
727
|
+
return "end";
|
728
|
+
case RUBY_EVENT_CALL:
|
729
|
+
return "call";
|
730
|
+
case RUBY_EVENT_RETURN:
|
731
|
+
return "return";
|
732
|
+
case RUBY_EVENT_C_CALL:
|
733
|
+
return "c-call";
|
734
|
+
case RUBY_EVENT_C_RETURN:
|
735
|
+
return "c-return";
|
736
|
+
case RUBY_EVENT_RAISE:
|
737
|
+
return "raise";
|
738
|
+
default:
|
739
|
+
return "unknown";
|
740
|
+
}
|
741
|
+
}
|
742
|
+
|
743
|
+
|
714
744
|
static void
|
715
745
|
debug_event_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass)
|
716
746
|
{
|
@@ -725,7 +755,7 @@ debug_event_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass)
|
|
725
755
|
|
726
756
|
if (mid == ID_ALLOCATOR) return;
|
727
757
|
if(!node) return;
|
728
|
-
|
758
|
+
|
729
759
|
thread = rb_thread_current();
|
730
760
|
thread_context_lookup(thread, &context, &debug_context);
|
731
761
|
|
@@ -853,8 +883,15 @@ debug_event_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass)
|
|
853
883
|
debug_context->stop_next = 1;
|
854
884
|
debug_context->stop_frame = 0;
|
855
885
|
}
|
856
|
-
|
886
|
+
// frame's method id must be checked to avoid a nasty Ruby's bug where
|
887
|
+
// [call] event is received without corresponding [return] event.
|
888
|
+
// For example, it happens when singleton methods are called.
|
889
|
+
while(debug_context->stack_size > 0)
|
890
|
+
{
|
857
891
|
debug_context->stack_size--;
|
892
|
+
if(debug_context->frames[debug_context->stack_size].id == mid)
|
893
|
+
break;
|
894
|
+
}
|
858
895
|
break;
|
859
896
|
}
|
860
897
|
case RUBY_EVENT_CLASS:
|
@@ -1266,7 +1303,7 @@ debug_suspend(VALUE self)
|
|
1266
1303
|
if(current == context)
|
1267
1304
|
continue;
|
1268
1305
|
Data_Get_Struct(context, debug_context_t, debug_context);
|
1269
|
-
|
1306
|
+
context_suspend_0(debug_context);
|
1270
1307
|
}
|
1271
1308
|
rb_thread_critical = saved_crit;
|
1272
1309
|
|
@@ -1304,11 +1341,7 @@ debug_resume(VALUE self)
|
|
1304
1341
|
if(current == context)
|
1305
1342
|
continue;
|
1306
1343
|
Data_Get_Struct(context, debug_context_t, debug_context);
|
1307
|
-
|
1308
|
-
{
|
1309
|
-
CTX_FL_UNSET(debug_context, CTX_FL_SUSPEND);
|
1310
|
-
rb_thread_run(context_thread_0(debug_context));
|
1311
|
-
}
|
1344
|
+
context_resume_0(debug_context);
|
1312
1345
|
}
|
1313
1346
|
rb_thread_critical = saved_crit;
|
1314
1347
|
|
@@ -1765,6 +1798,31 @@ context_thnum(VALUE self)
|
|
1765
1798
|
return INT2FIX(debug_context->thnum);
|
1766
1799
|
}
|
1767
1800
|
|
1801
|
+
static void
|
1802
|
+
context_suspend_0(debug_context_t *debug_context)
|
1803
|
+
{
|
1804
|
+
VALUE status;
|
1805
|
+
|
1806
|
+
status = rb_funcall(context_thread_0(debug_context), rb_intern("status"), 0);
|
1807
|
+
if(rb_str_cmp(status, rb_str_new2("run")) == 0)
|
1808
|
+
CTX_FL_SET(debug_context, CTX_FL_WAS_RUNNING);
|
1809
|
+
else if(rb_str_cmp(status, rb_str_new2("sleep")) == 0)
|
1810
|
+
CTX_FL_UNSET(debug_context, CTX_FL_WAS_RUNNING);
|
1811
|
+
else
|
1812
|
+
return;
|
1813
|
+
CTX_FL_SET(debug_context, CTX_FL_SUSPEND);
|
1814
|
+
}
|
1815
|
+
|
1816
|
+
static void
|
1817
|
+
context_resume_0(debug_context_t *debug_context)
|
1818
|
+
{
|
1819
|
+
if(!CTX_FL_TEST(debug_context, CTX_FL_SUSPEND))
|
1820
|
+
return;
|
1821
|
+
CTX_FL_UNSET(debug_context, CTX_FL_SUSPEND);
|
1822
|
+
if(CTX_FL_TEST(debug_context, CTX_FL_WAS_RUNNING))
|
1823
|
+
rb_thread_wakeup(context_thread_0(debug_context));
|
1824
|
+
}
|
1825
|
+
|
1768
1826
|
/*
|
1769
1827
|
* call-seq:
|
1770
1828
|
* context.suspend -> nil
|
@@ -1781,7 +1839,7 @@ context_suspend(VALUE self)
|
|
1781
1839
|
Data_Get_Struct(self, debug_context_t, debug_context);
|
1782
1840
|
if(CTX_FL_TEST(debug_context, CTX_FL_SUSPEND))
|
1783
1841
|
rb_raise(rb_eRuntimeError, "Already suspended.");
|
1784
|
-
|
1842
|
+
context_suspend_0(debug_context);
|
1785
1843
|
return Qnil;
|
1786
1844
|
}
|
1787
1845
|
|
@@ -1818,8 +1876,7 @@ context_resume(VALUE self)
|
|
1818
1876
|
Data_Get_Struct(self, debug_context_t, debug_context);
|
1819
1877
|
if(!CTX_FL_TEST(debug_context, CTX_FL_SUSPEND))
|
1820
1878
|
rb_raise(rb_eRuntimeError, "Thread is not suspended.");
|
1821
|
-
|
1822
|
-
rb_thread_run(context_thread_0(debug_context));
|
1879
|
+
context_resume_0(debug_context);
|
1823
1880
|
return Qnil;
|
1824
1881
|
}
|
1825
1882
|
|
data/lib/ruby-debug.rb
CHANGED
@@ -260,11 +260,13 @@ module Debugger
|
|
260
260
|
|
261
261
|
def handle_post_mortem(exp)
|
262
262
|
return if exp.__debug_context.stack_size == 0
|
263
|
+
Debugger.suspend
|
263
264
|
orig_tracing = Debugger.tracing, Debugger.current_context.tracing
|
264
265
|
Debugger.tracing = Debugger.current_context.tracing = false
|
265
266
|
processor.at_line(exp.__debug_context, exp.__debug_file, exp.__debug_line)
|
266
267
|
ensure
|
267
268
|
Debugger.tracing, Debugger.current_context.tracing = orig_tracing
|
269
|
+
Debugger.resume
|
268
270
|
end
|
269
271
|
private :handle_post_mortem
|
270
272
|
end
|
data/lib/ruby-debug/processor.rb
CHANGED
@@ -94,6 +94,22 @@ module Debugger
|
|
94
94
|
end
|
95
95
|
commands = event_cmds.map{|cmd| cmd.new(state) }
|
96
96
|
commands.select{|cmd| cmd.class.always_run }.each{|cmd| cmd.execute }
|
97
|
+
|
98
|
+
splitter = lambda do |str|
|
99
|
+
str.split(/;/).inject([]) do |m, v|
|
100
|
+
if m.empty?
|
101
|
+
m << v
|
102
|
+
else
|
103
|
+
if m.last[-1] == ?\\
|
104
|
+
m.last[-1,1] = ''
|
105
|
+
m.last << ';' << v
|
106
|
+
else
|
107
|
+
m << v
|
108
|
+
end
|
109
|
+
end
|
110
|
+
m
|
111
|
+
end
|
112
|
+
end
|
97
113
|
|
98
114
|
while !state.proceed? and input = @interface.read_command(prompt(context))
|
99
115
|
catch(:debug_error) do
|
@@ -105,7 +121,7 @@ module Debugger
|
|
105
121
|
@last_cmd = input
|
106
122
|
end
|
107
123
|
|
108
|
-
input.
|
124
|
+
splitter[input].each do |input|
|
109
125
|
if cmd = commands.find{ |c| c.match(input) }
|
110
126
|
if context.dead? && cmd.class.need_context
|
111
127
|
print "Command is unavailable\n"
|
data/lib/ruby_debug.so
CHANGED
Binary file
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.1
|
|
3
3
|
specification_version: 1
|
4
4
|
name: ruby-debug
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.7.
|
7
|
-
date: 2007-02-
|
6
|
+
version: 0.7.2
|
7
|
+
date: 2007-02-03 15:35:35 -05:00
|
8
8
|
summary: Fast Ruby debugger
|
9
9
|
require_paths:
|
10
10
|
- lib
|