* 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>
|
||||
|
||||
* 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__
|
||||
|
||||
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
|
||||
|
||||
class Context
|
||||
@ -118,13 +79,14 @@ class Context
|
||||
end
|
||||
|
||||
def check_suspend
|
||||
return if Thread.critical
|
||||
while (Thread.critical = true; @suspend_next)
|
||||
DEBUGGER__.waiting.push Thread.current
|
||||
@suspend_next = false
|
||||
Thread.stop
|
||||
while MUTEX.synchronize {
|
||||
if @suspend_next
|
||||
DEBUGGER__.waiting.push Thread.current
|
||||
@suspend_next = false
|
||||
true
|
||||
end
|
||||
}
|
||||
end
|
||||
Thread.critical = false
|
||||
end
|
||||
|
||||
def trace?
|
||||
@ -790,13 +752,12 @@ class << DEBUGGER__
|
||||
end
|
||||
|
||||
def set_trace( arg )
|
||||
saved_crit = Thread.critical
|
||||
Thread.critical = true
|
||||
make_thread_list
|
||||
for th, in @thread_list
|
||||
context(th).set_trace arg
|
||||
MUTEX.synchronize do
|
||||
make_thread_list
|
||||
for th, in @thread_list
|
||||
context(th).set_trace arg
|
||||
end
|
||||
end
|
||||
Thread.critical = saved_crit
|
||||
arg
|
||||
end
|
||||
|
||||
@ -805,31 +766,29 @@ class << DEBUGGER__
|
||||
end
|
||||
|
||||
def suspend
|
||||
saved_crit = Thread.critical
|
||||
Thread.critical = true
|
||||
make_thread_list
|
||||
for th, in @thread_list
|
||||
next if th == Thread.current
|
||||
context(th).set_suspend
|
||||
MUTEX.synchronize do
|
||||
make_thread_list
|
||||
for th, in @thread_list
|
||||
next if th == Thread.current
|
||||
context(th).set_suspend
|
||||
end
|
||||
end
|
||||
Thread.critical = saved_crit
|
||||
# Schedule other threads to suspend as soon as possible.
|
||||
Thread.pass unless Thread.critical
|
||||
Thread.pass
|
||||
end
|
||||
|
||||
def resume
|
||||
saved_crit = Thread.critical
|
||||
Thread.critical = true
|
||||
make_thread_list
|
||||
for th, in @thread_list
|
||||
next if th == Thread.current
|
||||
context(th).clear_suspend
|
||||
MUTEX.synchronize do
|
||||
make_thread_list
|
||||
for th, in @thread_list
|
||||
next if th == Thread.current
|
||||
context(th).clear_suspend
|
||||
end
|
||||
waiting.each do |th|
|
||||
th.run
|
||||
end
|
||||
waiting.clear
|
||||
end
|
||||
waiting.each do |th|
|
||||
th.run
|
||||
end
|
||||
waiting.clear
|
||||
Thread.critical = saved_crit
|
||||
# Schedule other threads to restart as soon as possible.
|
||||
Thread.pass
|
||||
end
|
||||
@ -944,4 +903,7 @@ stdout.printf "Emacs support available.\n\n"
|
||||
set_trace_func proc { |event, file, line, id, binding, klass, *rest|
|
||||
DEBUGGER__.context.trace_func event, file, line, id, binding, klass
|
||||
}
|
||||
VM::InstructionSequence.compile_option = {
|
||||
trace_instruction: true
|
||||
}
|
||||
end
|
||||
|
@ -118,8 +118,8 @@ class Tracer
|
||||
return unless p.call event, file, line, id, binding, klass
|
||||
end
|
||||
|
||||
saved_crit = Thread.critical
|
||||
Thread.critical = true
|
||||
# saved_crit = Thread.critical
|
||||
# Thread.critical = true
|
||||
stdout.printf("#%d:%s:%d:%s:%s: %s",
|
||||
get_thread_no,
|
||||
file,
|
||||
@ -127,7 +127,7 @@ class Tracer
|
||||
klass || '',
|
||||
EVENT_SYMBOL[event],
|
||||
get_line(file, line))
|
||||
Thread.critical = saved_crit
|
||||
# Thread.critical = saved_crit
|
||||
end
|
||||
|
||||
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);
|
||||
|
||||
#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*
|
||||
yycompile(struct parser_params *parser, const char *f, int line)
|
||||
{
|
||||
int n;
|
||||
const char *kcode_save;
|
||||
|
||||
if (!compile_for_eval && rb_safe_level() == 0 &&
|
||||
rb_const_defined(rb_cObject, rb_intern("SCRIPT_LINES__"))) {
|
||||
VALUE hash, fname;
|
||||
|
||||
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) {
|
||||
if (!compile_for_eval && rb_safe_level() == 0) {
|
||||
ruby_debug_lines = ruby_suppress_tracing(debug_lines, (VALUE)f);
|
||||
if (ruby_debug_lines && line > 1) {
|
||||
VALUE str = rb_str_new(0,0);
|
||||
n = line - 1;
|
||||
do {
|
||||
|
50
thread.c
50
thread.c
@ -2789,17 +2789,47 @@ get_event_name(rb_event_flag_t event)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
call_trace_func(rb_event_flag_t event, VALUE proc, VALUE self, ID id, VALUE klass)
|
||||
VALUE ruby_suppress_tracing(VALUE (*func)(ANYARGS), VALUE arg);
|
||||
|
||||
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();
|
||||
int state, raised;
|
||||
VALUE eventname = rb_str_new2(get_event_name(event));
|
||||
struct call_trace_func_args *p = (struct call_trace_func_args *)args;
|
||||
VALUE eventname = rb_str_new2(get_event_name(p->event));
|
||||
VALUE filename = rb_str_new2(rb_sourcefile());
|
||||
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) {
|
||||
return;
|
||||
return Qnil;
|
||||
}
|
||||
else {
|
||||
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();
|
||||
if ((state = EXEC_TAG()) == 0) {
|
||||
proc_invoke(proc, rb_ary_new3(6,
|
||||
eventname, filename, INT2FIX(line),
|
||||
id ? ID2SYM(id) : Qnil,
|
||||
self ? rb_binding_new() : Qnil,
|
||||
klass ? klass : Qnil), Qundef, 0);
|
||||
result = (*func)(arg);
|
||||
}
|
||||
|
||||
if (raised) {
|
||||
@ -2825,6 +2851,8 @@ call_trace_func(rb_event_flag_t event, VALUE proc, VALUE self, ID id, VALUE klas
|
||||
if (state) {
|
||||
JUMP_TAG(state);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
x
Reference in New Issue
Block a user