* parse.y (yycompile): disable trace while creating ruby_debug_lines.
[ruby-talk:253586] * thread.c (ruby_suppress_tracing): new function to call a function with suppressing trace. * lib/debug.rb, lib/tracer.rb: for YARV. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12569 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
31345380ac
commit
942a54302d
10
ChangeLog
10
ChangeLog
@ -1,3 +1,13 @@
|
|||||||
|
Mon Jun 18 16:57:24 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
|
* parse.y (yycompile): disable trace while creating ruby_debug_lines.
|
||||||
|
[ruby-talk:253586]
|
||||||
|
|
||||||
|
* thread.c (ruby_suppress_tracing): new function to call a function
|
||||||
|
with suppressing trace.
|
||||||
|
|
||||||
|
* lib/debug.rb, lib/tracer.rb: for YARV.
|
||||||
|
|
||||||
Mon Jun 18 13:54:36 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
Mon Jun 18 13:54:36 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
* eval.c (ruby_cleanup): return EXIT_FAILURE if any exceptions occured
|
* eval.c (ruby_cleanup): return EXIT_FAILURE if any exceptions occured
|
||||||
|
102
lib/debug.rb
102
lib/debug.rb
@ -19,45 +19,6 @@ end
|
|||||||
SCRIPT_LINES__ = {} unless defined? SCRIPT_LINES__
|
SCRIPT_LINES__ = {} unless defined? SCRIPT_LINES__
|
||||||
|
|
||||||
class DEBUGGER__
|
class DEBUGGER__
|
||||||
class Mutex
|
|
||||||
def initialize
|
|
||||||
@locker = nil
|
|
||||||
@waiting = []
|
|
||||||
@locked = false;
|
|
||||||
end
|
|
||||||
|
|
||||||
def locked?
|
|
||||||
@locked
|
|
||||||
end
|
|
||||||
|
|
||||||
def lock
|
|
||||||
return if Thread.critical
|
|
||||||
return if @locker == Thread.current
|
|
||||||
while (Thread.critical = true; @locked)
|
|
||||||
@waiting.push Thread.current
|
|
||||||
Thread.stop
|
|
||||||
end
|
|
||||||
@locked = true
|
|
||||||
@locker = Thread.current
|
|
||||||
Thread.critical = false
|
|
||||||
self
|
|
||||||
end
|
|
||||||
|
|
||||||
def unlock
|
|
||||||
return if Thread.critical
|
|
||||||
return unless @locked
|
|
||||||
unless @locker == Thread.current
|
|
||||||
raise RuntimeError, "unlocked by other"
|
|
||||||
end
|
|
||||||
Thread.critical = true
|
|
||||||
t = @waiting.shift
|
|
||||||
@locked = false
|
|
||||||
@locker = nil
|
|
||||||
Thread.critical = false
|
|
||||||
t.run if t
|
|
||||||
self
|
|
||||||
end
|
|
||||||
end
|
|
||||||
MUTEX = Mutex.new
|
MUTEX = Mutex.new
|
||||||
|
|
||||||
class Context
|
class Context
|
||||||
@ -118,13 +79,14 @@ class Context
|
|||||||
end
|
end
|
||||||
|
|
||||||
def check_suspend
|
def check_suspend
|
||||||
return if Thread.critical
|
while MUTEX.synchronize {
|
||||||
while (Thread.critical = true; @suspend_next)
|
if @suspend_next
|
||||||
DEBUGGER__.waiting.push Thread.current
|
DEBUGGER__.waiting.push Thread.current
|
||||||
@suspend_next = false
|
@suspend_next = false
|
||||||
Thread.stop
|
true
|
||||||
|
end
|
||||||
|
}
|
||||||
end
|
end
|
||||||
Thread.critical = false
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def trace?
|
def trace?
|
||||||
@ -790,13 +752,12 @@ class << DEBUGGER__
|
|||||||
end
|
end
|
||||||
|
|
||||||
def set_trace( arg )
|
def set_trace( arg )
|
||||||
saved_crit = Thread.critical
|
MUTEX.synchronize do
|
||||||
Thread.critical = true
|
make_thread_list
|
||||||
make_thread_list
|
for th, in @thread_list
|
||||||
for th, in @thread_list
|
context(th).set_trace arg
|
||||||
context(th).set_trace arg
|
end
|
||||||
end
|
end
|
||||||
Thread.critical = saved_crit
|
|
||||||
arg
|
arg
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -805,31 +766,29 @@ class << DEBUGGER__
|
|||||||
end
|
end
|
||||||
|
|
||||||
def suspend
|
def suspend
|
||||||
saved_crit = Thread.critical
|
MUTEX.synchronize do
|
||||||
Thread.critical = true
|
make_thread_list
|
||||||
make_thread_list
|
for th, in @thread_list
|
||||||
for th, in @thread_list
|
next if th == Thread.current
|
||||||
next if th == Thread.current
|
context(th).set_suspend
|
||||||
context(th).set_suspend
|
end
|
||||||
end
|
end
|
||||||
Thread.critical = saved_crit
|
|
||||||
# Schedule other threads to suspend as soon as possible.
|
# Schedule other threads to suspend as soon as possible.
|
||||||
Thread.pass unless Thread.critical
|
Thread.pass
|
||||||
end
|
end
|
||||||
|
|
||||||
def resume
|
def resume
|
||||||
saved_crit = Thread.critical
|
MUTEX.synchronize do
|
||||||
Thread.critical = true
|
make_thread_list
|
||||||
make_thread_list
|
for th, in @thread_list
|
||||||
for th, in @thread_list
|
next if th == Thread.current
|
||||||
next if th == Thread.current
|
context(th).clear_suspend
|
||||||
context(th).clear_suspend
|
end
|
||||||
|
waiting.each do |th|
|
||||||
|
th.run
|
||||||
|
end
|
||||||
|
waiting.clear
|
||||||
end
|
end
|
||||||
waiting.each do |th|
|
|
||||||
th.run
|
|
||||||
end
|
|
||||||
waiting.clear
|
|
||||||
Thread.critical = saved_crit
|
|
||||||
# Schedule other threads to restart as soon as possible.
|
# Schedule other threads to restart as soon as possible.
|
||||||
Thread.pass
|
Thread.pass
|
||||||
end
|
end
|
||||||
@ -944,4 +903,7 @@ stdout.printf "Emacs support available.\n\n"
|
|||||||
set_trace_func proc { |event, file, line, id, binding, klass, *rest|
|
set_trace_func proc { |event, file, line, id, binding, klass, *rest|
|
||||||
DEBUGGER__.context.trace_func event, file, line, id, binding, klass
|
DEBUGGER__.context.trace_func event, file, line, id, binding, klass
|
||||||
}
|
}
|
||||||
|
VM::InstructionSequence.compile_option = {
|
||||||
|
trace_instruction: true
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
@ -118,8 +118,8 @@ class Tracer
|
|||||||
return unless p.call event, file, line, id, binding, klass
|
return unless p.call event, file, line, id, binding, klass
|
||||||
end
|
end
|
||||||
|
|
||||||
saved_crit = Thread.critical
|
# saved_crit = Thread.critical
|
||||||
Thread.critical = true
|
# Thread.critical = true
|
||||||
stdout.printf("#%d:%s:%d:%s:%s: %s",
|
stdout.printf("#%d:%s:%d:%s:%s: %s",
|
||||||
get_thread_no,
|
get_thread_no,
|
||||||
file,
|
file,
|
||||||
@ -127,7 +127,7 @@ class Tracer
|
|||||||
klass || '',
|
klass || '',
|
||||||
EVENT_SYMBOL[event],
|
EVENT_SYMBOL[event],
|
||||||
get_line(file, line))
|
get_line(file, line))
|
||||||
Thread.critical = saved_crit
|
# Thread.critical = saved_crit
|
||||||
end
|
end
|
||||||
|
|
||||||
Single = new
|
Single = new
|
||||||
|
37
parse.y
37
parse.y
@ -4584,26 +4584,35 @@ parser_yyerror(struct parser_params *parser, const char *msg)
|
|||||||
static void parser_prepare(struct parser_params *parser);
|
static void parser_prepare(struct parser_params *parser);
|
||||||
|
|
||||||
#ifndef RIPPER
|
#ifndef RIPPER
|
||||||
|
VALUE ruby_suppress_tracing(VALUE (*func)(ANYARGS), VALUE arg);
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
debug_lines(VALUE f)
|
||||||
|
{
|
||||||
|
if (rb_const_defined_at(rb_cObject, rb_intern("SCRIPT_LINES__"))) {
|
||||||
|
VALUE hash = rb_const_get_at(rb_cObject, rb_intern("SCRIPT_LINES__"));
|
||||||
|
if (TYPE(hash) == T_HASH) {
|
||||||
|
VALUE fname = rb_str_new2((const char *)f);
|
||||||
|
VALUE lines = rb_hash_aref(hash, fname);
|
||||||
|
if (NIL_P(lines)) {
|
||||||
|
lines = rb_ary_new();
|
||||||
|
rb_hash_aset(hash, fname, lines);
|
||||||
|
}
|
||||||
|
return lines;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static NODE*
|
static NODE*
|
||||||
yycompile(struct parser_params *parser, const char *f, int line)
|
yycompile(struct parser_params *parser, const char *f, int line)
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
const char *kcode_save;
|
const char *kcode_save;
|
||||||
|
|
||||||
if (!compile_for_eval && rb_safe_level() == 0 &&
|
if (!compile_for_eval && rb_safe_level() == 0) {
|
||||||
rb_const_defined(rb_cObject, rb_intern("SCRIPT_LINES__"))) {
|
ruby_debug_lines = ruby_suppress_tracing(debug_lines, (VALUE)f);
|
||||||
VALUE hash, fname;
|
if (ruby_debug_lines && line > 1) {
|
||||||
|
|
||||||
hash = rb_const_get(rb_cObject, rb_intern("SCRIPT_LINES__"));
|
|
||||||
if (TYPE(hash) == T_HASH) {
|
|
||||||
fname = rb_str_new2(f);
|
|
||||||
ruby_debug_lines = rb_hash_aref(hash, fname);
|
|
||||||
if (NIL_P(ruby_debug_lines)) {
|
|
||||||
ruby_debug_lines = rb_ary_new();
|
|
||||||
rb_hash_aset(hash, fname, ruby_debug_lines);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (line > 1) {
|
|
||||||
VALUE str = rb_str_new(0,0);
|
VALUE str = rb_str_new(0,0);
|
||||||
n = line - 1;
|
n = line - 1;
|
||||||
do {
|
do {
|
||||||
|
50
thread.c
50
thread.c
@ -2789,17 +2789,47 @@ get_event_name(rb_event_flag_t event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
VALUE ruby_suppress_tracing(VALUE (*func)(ANYARGS), VALUE arg);
|
||||||
call_trace_func(rb_event_flag_t event, VALUE proc, VALUE self, ID id, VALUE klass)
|
|
||||||
|
struct call_trace_func_args {
|
||||||
|
rb_event_flag_t event;
|
||||||
|
VALUE proc;
|
||||||
|
VALUE self;
|
||||||
|
ID id;
|
||||||
|
VALUE klass;
|
||||||
|
};
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
call_trace_proc(VALUE args)
|
||||||
{
|
{
|
||||||
rb_thread_t *th = GET_THREAD();
|
struct call_trace_func_args *p = (struct call_trace_func_args *)args;
|
||||||
int state, raised;
|
VALUE eventname = rb_str_new2(get_event_name(p->event));
|
||||||
VALUE eventname = rb_str_new2(get_event_name(event));
|
|
||||||
VALUE filename = rb_str_new2(rb_sourcefile());
|
VALUE filename = rb_str_new2(rb_sourcefile());
|
||||||
int line = rb_sourceline();
|
int line = rb_sourceline();
|
||||||
|
|
||||||
|
return rb_proc_call(p->proc, rb_ary_new3(6,
|
||||||
|
eventname, filename, INT2FIX(line),
|
||||||
|
p->id ? ID2SYM(p->id) : Qnil,
|
||||||
|
p->self ? rb_binding_new() : Qnil,
|
||||||
|
p->klass ? p->klass : Qnil));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
call_trace_func(rb_event_flag_t event, VALUE proc, VALUE self, ID id, VALUE klass)
|
||||||
|
{
|
||||||
|
struct call_trace_func_args args = {event, proc, self, id, klass};
|
||||||
|
ruby_suppress_tracing(call_trace_proc, (VALUE)&args);
|
||||||
|
}
|
||||||
|
|
||||||
|
VALUE
|
||||||
|
ruby_suppress_tracing(VALUE (*func)(ANYARGS), VALUE arg)
|
||||||
|
{
|
||||||
|
rb_thread_t *th = GET_THREAD();
|
||||||
|
int state, raised;
|
||||||
|
VALUE result = Qnil;
|
||||||
|
|
||||||
if (th->tracing) {
|
if (th->tracing) {
|
||||||
return;
|
return Qnil;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
th->tracing = 1;
|
th->tracing = 1;
|
||||||
@ -2809,11 +2839,7 @@ call_trace_func(rb_event_flag_t event, VALUE proc, VALUE self, ID id, VALUE klas
|
|||||||
|
|
||||||
PUSH_TAG();
|
PUSH_TAG();
|
||||||
if ((state = EXEC_TAG()) == 0) {
|
if ((state = EXEC_TAG()) == 0) {
|
||||||
proc_invoke(proc, rb_ary_new3(6,
|
result = (*func)(arg);
|
||||||
eventname, filename, INT2FIX(line),
|
|
||||||
id ? ID2SYM(id) : Qnil,
|
|
||||||
self ? rb_binding_new() : Qnil,
|
|
||||||
klass ? klass : Qnil), Qundef, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (raised) {
|
if (raised) {
|
||||||
@ -2825,6 +2851,8 @@ call_trace_func(rb_event_flag_t event, VALUE proc, VALUE self, ID id, VALUE klas
|
|||||||
if (state) {
|
if (state) {
|
||||||
JUMP_TAG(state);
|
JUMP_TAG(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user