зеркало из https://github.com/github/ruby.git
cvs.netlab.co.jp last commit
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1078 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
Родитель
4c8f968c40
Коммит
c101164b02
188
lib/debug.rb
188
lib/debug.rb
|
@ -91,22 +91,54 @@ class DEBUGGER__
|
||||||
@finish_pos = 0
|
@finish_pos = 0
|
||||||
@trace = false
|
@trace = false
|
||||||
@catch = "StandardError"
|
@catch = "StandardError"
|
||||||
|
@suspend_next = false
|
||||||
end
|
end
|
||||||
|
|
||||||
def stop_next(n=1)
|
def stop_next(n=1)
|
||||||
@stop_next = n
|
@stop_next = n
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def suspend
|
||||||
|
@suspend_next = true
|
||||||
|
end
|
||||||
|
|
||||||
|
def check_suspend
|
||||||
|
while (Thread.critical = true; @suspend_next)
|
||||||
|
waiting.push Thread.current
|
||||||
|
@suspend_next = false
|
||||||
|
Thread.stop
|
||||||
|
end
|
||||||
|
Thread.critical = false
|
||||||
|
end
|
||||||
|
|
||||||
|
def trace?
|
||||||
|
@trace
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_trace(arg)
|
||||||
|
@trace = arg
|
||||||
|
end
|
||||||
|
|
||||||
def stdout
|
def stdout
|
||||||
DEBUGGER__.stdout
|
DEBUGGER__.stdout
|
||||||
end
|
end
|
||||||
|
|
||||||
def break_points
|
def break_points
|
||||||
DEBUGGER__.break_points
|
DEBUGGER__.break_points
|
||||||
end
|
end
|
||||||
|
|
||||||
def display
|
def display
|
||||||
DEBUGGER__.display
|
DEBUGGER__.display
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def waiting
|
||||||
|
DEBUGGER__.waiting
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_trace_all(arg)
|
||||||
|
DEBUGGER__.set_trace(arg)
|
||||||
|
end
|
||||||
|
|
||||||
def debug_eval(str, binding)
|
def debug_eval(str, binding)
|
||||||
begin
|
begin
|
||||||
val = eval(str, binding)
|
val = eval(str, binding)
|
||||||
|
@ -218,7 +250,8 @@ class DEBUGGER__
|
||||||
end
|
end
|
||||||
@frames[0] = [binding, file, line, id]
|
@frames[0] = [binding, file, line, id]
|
||||||
display_expressions(binding)
|
display_expressions(binding)
|
||||||
while input = readline("(rdb:%d) "%thnum(), true)
|
prompt = true
|
||||||
|
while prompt and input = readline("(rdb:%d) "%thnum(), true)
|
||||||
catch(:debug_error) do
|
catch(:debug_error) do
|
||||||
if input == ""
|
if input == ""
|
||||||
input = DEBUG_LAST_CMD[0]
|
input = DEBUG_LAST_CMD[0]
|
||||||
|
@ -228,18 +261,24 @@ class DEBUGGER__
|
||||||
end
|
end
|
||||||
|
|
||||||
case input
|
case input
|
||||||
when /^\s*tr(?:ace)?(?:\s+(on|off))?$/
|
when /^\s*tr(?:ace)?(?:\s+(on|off))?(?:\s+(all))?$/
|
||||||
if defined?( $1 )
|
if defined?( $2 )
|
||||||
if $1 == 'on'
|
if $1 == 'on'
|
||||||
@trace = true
|
set_trace_all true
|
||||||
else
|
else
|
||||||
@trace = false
|
set_trace_all false
|
||||||
|
end
|
||||||
|
elsif defined?( $1 )
|
||||||
|
if $1 == 'on'
|
||||||
|
set_trace true
|
||||||
|
else
|
||||||
|
set_trace false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if @trace
|
if trace?
|
||||||
stdout.print "Trace on\n"
|
stdout.print "Trace on.\n"
|
||||||
else
|
else
|
||||||
stdout.print "Trace off\n"
|
stdout.print "Trace off.\n"
|
||||||
end
|
end
|
||||||
|
|
||||||
when /^\s*b(?:reak)?\s+((?:.*?+:)?.+)$/
|
when /^\s*b(?:reak)?\s+((?:.*?+:)?.+)$/
|
||||||
|
@ -336,8 +375,7 @@ class DEBUGGER__
|
||||||
end
|
end
|
||||||
|
|
||||||
when /^\s*c(?:ont)?$/
|
when /^\s*c(?:ont)?$/
|
||||||
MUTEX.unlock
|
prompt = false
|
||||||
return
|
|
||||||
|
|
||||||
when /^\s*s(?:tep)?(?:\s+(\d+))?$/
|
when /^\s*s(?:tep)?(?:\s+(\d+))?$/
|
||||||
if $1
|
if $1
|
||||||
|
@ -346,7 +384,7 @@ class DEBUGGER__
|
||||||
lev = 1
|
lev = 1
|
||||||
end
|
end
|
||||||
@stop_next = lev
|
@stop_next = lev
|
||||||
return
|
prompt = false
|
||||||
|
|
||||||
when /^\s*n(?:ext)?(?:\s+(\d+))?$/
|
when /^\s*n(?:ext)?(?:\s+(\d+))?$/
|
||||||
if $1
|
if $1
|
||||||
|
@ -356,7 +394,7 @@ class DEBUGGER__
|
||||||
end
|
end
|
||||||
@stop_next = lev
|
@stop_next = lev
|
||||||
@no_step = @frames.size - frame_pos
|
@no_step = @frames.size - frame_pos
|
||||||
return
|
prompt = false
|
||||||
|
|
||||||
when /^\s*w(?:here)?$/, /^\s*f(?:rame)?$/
|
when /^\s*w(?:here)?$/, /^\s*f(?:rame)?$/
|
||||||
display_frames(frame_pos)
|
display_frames(frame_pos)
|
||||||
|
@ -417,8 +455,7 @@ class DEBUGGER__
|
||||||
else
|
else
|
||||||
@finish_pos = @frames.size - frame_pos
|
@finish_pos = @frames.size - frame_pos
|
||||||
frame_pos = 0
|
frame_pos = 0
|
||||||
MUTEX.unlock
|
prompt = false
|
||||||
return
|
|
||||||
end
|
end
|
||||||
|
|
||||||
when /^\s*cat(?:ch)?(?:\s+(.+))?$/
|
when /^\s*cat(?:ch)?(?:\s+(.+))?$/
|
||||||
|
@ -440,8 +477,10 @@ class DEBUGGER__
|
||||||
end
|
end
|
||||||
|
|
||||||
when /^\s*q(?:uit)?$/
|
when /^\s*q(?:uit)?$/
|
||||||
input = readline("really quit? (y/n) ", false)
|
input = readline("Really quit? (y/n) ", false)
|
||||||
exit if input == "y"
|
if input == "y"
|
||||||
|
exit! # exit -> exit!: No graceful way to stop threads...
|
||||||
|
end
|
||||||
|
|
||||||
when /^\s*v(?:ar)?\s+/
|
when /^\s*v(?:ar)?\s+/
|
||||||
debug_variable_info($', binding)
|
debug_variable_info($', binding)
|
||||||
|
@ -451,8 +490,7 @@ class DEBUGGER__
|
||||||
|
|
||||||
when /^\s*th(?:read)?\s+/
|
when /^\s*th(?:read)?\s+/
|
||||||
if DEBUGGER__.debug_thread_info($', binding) == :cont
|
if DEBUGGER__.debug_thread_info($', binding) == :cont
|
||||||
MUTEX.unlock
|
prompt = false
|
||||||
return
|
|
||||||
end
|
end
|
||||||
|
|
||||||
when /^\s*p\s+/
|
when /^\s*p\s+/
|
||||||
|
@ -467,6 +505,8 @@ class DEBUGGER__
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
MUTEX.unlock
|
||||||
|
DEBUGGER__.resume_all_thread
|
||||||
end
|
end
|
||||||
|
|
||||||
def debug_print_help
|
def debug_print_help
|
||||||
|
@ -492,7 +532,8 @@ Commands
|
||||||
up[ nn] move to higher frame
|
up[ nn] move to higher frame
|
||||||
down[ nn] move to lower frame
|
down[ nn] move to lower frame
|
||||||
fin[ish] return to outer frame
|
fin[ish] return to outer frame
|
||||||
tr[ace][ (on|off)] set trace mode
|
tr[ace] (on|off) set trace mode of current thread
|
||||||
|
tr[ace] (on|off) all set trace mode of all threads
|
||||||
q[uit] exit from debugger
|
q[uit] exit from debugger
|
||||||
v[ar] g[lobal] show global variables
|
v[ar] g[lobal] show global variables
|
||||||
v[ar] l[ocal] show local variables
|
v[ar] l[ocal] show local variables
|
||||||
|
@ -501,11 +542,10 @@ Commands
|
||||||
m[ethod] i[nstance] <obj> show methods of object
|
m[ethod] i[nstance] <obj> show methods of object
|
||||||
m[ethod] <class|module> show instance methods of class or module
|
m[ethod] <class|module> show instance methods of class or module
|
||||||
th[read] l[ist] list all threads
|
th[read] l[ist] list all threads
|
||||||
th[read] c[ur[rent]] show current threads
|
th[read] c[ur[rent]] show current thread
|
||||||
th[read] <nnn> stop thread nnn
|
th[read] [sw[itch]] <nnn> switch thread context to nnn
|
||||||
th[read] stop <nnn> alias for th[read] <nnn>
|
th[read] stop <nnn> stop thread nnn
|
||||||
th[read] c[ur[rent]] <nnn> alias for th[read] <nnn>
|
th[read] resume <nnn> resume thread nnn
|
||||||
th[read] resume <nnn> run thread nnn
|
|
||||||
p expression evaluate expression and print its value
|
p expression evaluate expression and print its value
|
||||||
h[elp] print this help
|
h[elp] print this help
|
||||||
<everything else> evaluate
|
<everything else> evaluate
|
||||||
|
@ -587,7 +627,7 @@ EOHELP
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_break_points(file, pos, binding, id)
|
def check_break_points(file, pos, binding, id)
|
||||||
MUTEX.lock # Stop all threads before 'line' and 'call'.
|
return false if break_points.empty?
|
||||||
file = File.basename(file)
|
file = File.basename(file)
|
||||||
n = 1
|
n = 1
|
||||||
for b in break_points
|
for b in break_points
|
||||||
|
@ -604,7 +644,6 @@ EOHELP
|
||||||
end
|
end
|
||||||
n += 1
|
n += 1
|
||||||
end
|
end
|
||||||
MUTEX.unlock
|
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -616,7 +655,6 @@ EOHELP
|
||||||
end
|
end
|
||||||
|
|
||||||
if @catch and ($!.type.ancestors.find { |e| e.to_s == @catch })
|
if @catch and ($!.type.ancestors.find { |e| e.to_s == @catch })
|
||||||
MUTEX.lock
|
|
||||||
fs = @frames.size
|
fs = @frames.size
|
||||||
tb = caller(0)[-fs..-1]
|
tb = caller(0)[-fs..-1]
|
||||||
if tb
|
if tb
|
||||||
|
@ -624,12 +662,14 @@ EOHELP
|
||||||
stdout.printf "\tfrom %s\n", i
|
stdout.printf "\tfrom %s\n", i
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
DEBUGGER__.suspend_all_thread
|
||||||
debug_command(file, line, id, binding)
|
debug_command(file, line, id, binding)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def trace_func(event, file, line, id, binding, klass)
|
def trace_func(event, file, line, id, binding, klass)
|
||||||
Tracer.trace_func(event, file, line, id, binding) if @trace
|
Tracer.trace_func(event, file, line, id, binding, klass) if trace?
|
||||||
|
DEBUGGER__.context(Thread.current).check_suspend
|
||||||
@file = file
|
@file = file
|
||||||
@line = line
|
@line = line
|
||||||
case event
|
case event
|
||||||
|
@ -647,6 +687,7 @@ EOHELP
|
||||||
@stop_next = 1
|
@stop_next = 1
|
||||||
else
|
else
|
||||||
@no_step = nil
|
@no_step = nil
|
||||||
|
DEBUGGER__.suspend_all_thread
|
||||||
debug_command(file, line, id, binding)
|
debug_command(file, line, id, binding)
|
||||||
@last = [file, line]
|
@last = [file, line]
|
||||||
end
|
end
|
||||||
|
@ -656,6 +697,7 @@ EOHELP
|
||||||
@frames.unshift [binding, file, line, id]
|
@frames.unshift [binding, file, line, id]
|
||||||
if check_break_points(file, id.id2name, binding, id) or
|
if check_break_points(file, id.id2name, binding, id) or
|
||||||
check_break_points(klass.to_s, id.id2name, binding, id)
|
check_break_points(klass.to_s, id.id2name, binding, id)
|
||||||
|
DEBUGGER__.suspend_all_thread
|
||||||
debug_command(file, line, id, binding)
|
debug_command(file, line, id, binding)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -682,19 +724,20 @@ EOHELP
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
trap("INT") { DEBUGGER__.interrupt }
|
trap("INT") { DEBUGGER__.interrupt }
|
||||||
# $DEBUG = true
|
|
||||||
@last_thread = Thread::main
|
@last_thread = Thread::main
|
||||||
@max_thread = 1
|
@max_thread = 1
|
||||||
@thread_list = {Thread::main => 1}
|
@thread_list = {Thread::main => 1}
|
||||||
@break_points = []
|
@break_points = []
|
||||||
@display = []
|
@display = []
|
||||||
|
@waiting = []
|
||||||
@stdout = STDOUT
|
@stdout = STDOUT
|
||||||
|
|
||||||
class <<DEBUGGER__
|
class <<DEBUGGER__
|
||||||
def stdout
|
def stdout
|
||||||
@stdout
|
@stdout
|
||||||
end
|
end
|
||||||
|
|
||||||
def stdout=(s)
|
def stdout=(s)
|
||||||
@stdout = s
|
@stdout = s
|
||||||
end
|
end
|
||||||
|
@ -707,10 +750,46 @@ EOHELP
|
||||||
@break_points
|
@break_points
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def waiting
|
||||||
|
@waiting
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_trace( arg )
|
||||||
|
Thread.critical = true
|
||||||
|
make_thread_list
|
||||||
|
for th in @thread_list
|
||||||
|
context(th[0]).set_trace arg
|
||||||
|
end
|
||||||
|
Thread.critical = false
|
||||||
|
end
|
||||||
|
|
||||||
def set_last_thread(th)
|
def set_last_thread(th)
|
||||||
@last_thread = th
|
@last_thread = th
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def suspend_all_thread
|
||||||
|
Thread.critical = true
|
||||||
|
make_thread_list
|
||||||
|
for th in @thread_list
|
||||||
|
next if th[0] == Thread.current
|
||||||
|
context(th[0]).suspend
|
||||||
|
end
|
||||||
|
Thread.critical = false
|
||||||
|
# Schedule other threads to suspend as soon as possible.
|
||||||
|
Thread.pass
|
||||||
|
end
|
||||||
|
|
||||||
|
def resume_all_thread
|
||||||
|
Thread.critical = true
|
||||||
|
waiting.each do |th|
|
||||||
|
th.run
|
||||||
|
end
|
||||||
|
waiting.clear
|
||||||
|
Thread.critical = false
|
||||||
|
# Schedule other threads to restart as soon as possible.
|
||||||
|
Thread.pass
|
||||||
|
end
|
||||||
|
|
||||||
def context(thread=Thread.current)
|
def context(thread=Thread.current)
|
||||||
c = thread[:__debugger_data__]
|
c = thread[:__debugger_data__]
|
||||||
unless c
|
unless c
|
||||||
|
@ -726,7 +805,7 @@ EOHELP
|
||||||
def get_thread(num)
|
def get_thread(num)
|
||||||
th = @thread_list.index(num)
|
th = @thread_list.index(num)
|
||||||
unless th
|
unless th
|
||||||
@stdout.print "no thread no.", num, "\n"
|
@stdout.print "No thread ##{num}\n"
|
||||||
throw :debug_error
|
throw :debug_error
|
||||||
end
|
end
|
||||||
th
|
th
|
||||||
|
@ -773,31 +852,52 @@ EOHELP
|
||||||
make_thread_list
|
make_thread_list
|
||||||
thread_list_all
|
thread_list_all
|
||||||
|
|
||||||
when /^c(?:ur(?:rent)?)?\s+(\d+)/, /^stop\s+(\d+)/, /^(\d+)/
|
|
||||||
make_thread_list
|
|
||||||
th = get_thread($1.to_i)
|
|
||||||
thread_list(@thread_list[th])
|
|
||||||
context(th).stop_next
|
|
||||||
th.run
|
|
||||||
return :cont
|
|
||||||
|
|
||||||
when /^c(?:ur(?:rent)?)?$/
|
when /^c(?:ur(?:rent)?)?$/
|
||||||
make_thread_list
|
make_thread_list
|
||||||
thread_list(@thread_list[Thread.current])
|
thread_list(@thread_list[Thread.current])
|
||||||
|
|
||||||
|
when /^(?:sw(?:itch)?\s+)?(\d+)/
|
||||||
|
make_thread_list
|
||||||
|
th = get_thread($1.to_i)
|
||||||
|
if th == Thread.current
|
||||||
|
@stdout.print "It's the current thread.\n"
|
||||||
|
else
|
||||||
|
thread_list(@thread_list[th])
|
||||||
|
context(th).stop_next
|
||||||
|
th.run
|
||||||
|
return :cont
|
||||||
|
end
|
||||||
|
|
||||||
|
when /^stop\s+(\d+)/
|
||||||
|
make_thread_list
|
||||||
|
th = get_thread($1.to_i)
|
||||||
|
if th == Thread.current
|
||||||
|
@stdout.print "It's the current thread.\n"
|
||||||
|
elsif th.stop?
|
||||||
|
@stdout.print "Already stopped.\n"
|
||||||
|
else
|
||||||
|
thread_list(@thread_list[th])
|
||||||
|
context(th).suspend
|
||||||
|
end
|
||||||
|
|
||||||
when /^resume\s+(\d+)/
|
when /^resume\s+(\d+)/
|
||||||
make_thread_list
|
make_thread_list
|
||||||
th = get_thread($1.to_i)
|
th = get_thread($1.to_i)
|
||||||
thread_list(@thread_list[th])
|
if th == Thread.current
|
||||||
th.run
|
@stdout.print "It's the current thread.\n"
|
||||||
return :cont
|
elsif !th.stop?
|
||||||
|
@stdout.print "Already running."
|
||||||
|
else
|
||||||
|
thread_list(@thread_list[th])
|
||||||
|
th.run
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
stdout.printf "Debug.rb\n"
|
stdout.printf "Debug.rb\n"
|
||||||
stdout.printf "Emacs support available.\n\n"
|
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
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
Загрузка…
Ссылка в новой задаче