调试线程ruby应用程序
我正在开发一个使用线程的ruby应用程序。 我无法调试它。 主要问题是我想逐步完成一个特定的线程。 我设置断点并运行,但在使用thr sw 2
类的东西之前没有任何反应。 但后来的输入是FUBAR。 我试过撬,但撬似乎没有更好的处理线程。
解决方案? 变通?
编辑1:
仅供参考:使用byebug
Pry version 0.10.1 on Ruby 2.0.0
上byebug
Pry version 0.10.1 on Ruby 2.0.0
所以这就是我对Pry的体验。 尝试1:我使用break
设置特定于线程的断点
- 让程序运行。
- 断点被触发。
- 撬正确地向我显示了断点和周围的代码。
- 什么都没有。 我没有提示 。 Control-C不起作用。 事实上,我必须从外面杀死-9这个过程。
尝试2:使用上面的“binding.pry”方法。
- 相同
- 相同
- 相同!
- 我得到了一个Pry提示! 我可以表达。
- 我尝试使用“步骤”或“下一步”,突然我在“Pry :: history #load”中。 所以现在调试器已跳转到正在处理输入本身的线程。 这不起作用。
撬输出:
[2] pry(#)> step From: /usr/local/rvm/gems/ruby-2.0.0-p598/gems/pry-0.10.1/lib/pry/history.rb @ line 37 Pry::History#load: 35: def load 36: @loader.call do |line| => 37: @pusher.call(line.chomp) 38: @history << line.chomp 39: @original_lines += 1 40: end 41: end [2] pry(#)>
- 我尝试“退出”,现在我在“撬(主)”没有任何其他工作。
撬输出:
[1] pry(main)> continue Error: Cannot find local context. Did you use `binding.pry`?
pry
可以很好地处理线程。 您的代码中可能存在故障。
让我们尝试检查以下线程切换器(示例在这里采取):
require 'pry' module SeqExec class Seqs attr_reader :init def synch_prior mx, cv Thread.new { mx.synchronize { @init[:prior] = true loop do cv.wait mx # binding.pry yield if block_given? cv.broadcast end } } end def synch_posterior mx, cv Thread.new { mx.synchronize { @init[:posterior] = true loop do cv.wait mx yield if block_given? cv.broadcast end } } end def synch λ1, λ2 @init = {} mx = Mutex.new cv = ConditionVariable.new synch_prior(mx, cv, &λ1) # prior function Thread.pass until {:prior=>true} == @init synch_posterior(mx, cv, &λ2) # posterior function Thread.pass until {:prior=>true,:posterior=>true} == @init cv.signal # we are ready to start end end end module SeqExec Thread.abort_on_exception = true def pre &cb @prior = cb end def post &cb @posterior = cb end def run λ1 = nil, λ2 = nil pre &λ1 if λ1 post &λ2 if λ2 raise ArgumentError.new "Cannot run sequential execution, lambdas are not set" \ unless (@prior && @posterior) Seqs.new.synch @prior, @posterior end end include SeqExec @i=0 @stack = [] pre { sleep 0.3; print "-#{@i += 1}-"; @stack.push(@i) } post { print "|#{@stack.pop}|" } run 10.times { sleep 0.1 } sleep 30000
随着binding.pry
注释掉,它打印出来:
#⇒ -1-|1|-2-|2|-3-|3|-4-|4|-5-|5|-6-|6|-7-........
使用binding.pry
取消注释,我们产生:
Frame number: 0/2 From: /tmp/a.rb @ line 12 SeqExec::Seqs#synch_prior: 6: def synch_prior mx, cv 7: Thread.new { 8: mx.synchronize { 9: @init[:prior] = true 10: loop do 11: cv.wait mx => 12: binding.pry 13: yield if block_given? 14: cv.broadcast 15: end 16: } 17: } 18: end ▶ mx => # ▶ exit -1-|1| Frame number: 0/2 From: /tmp/a.rb @ line 12 SeqExec::Seqs#synch_prior: 6: def synch_prior mx, cv 7: Thread.new { 8: mx.synchronize { 9: @init[:prior] = true 10: loop do 11: cv.wait mx => 12: binding.pry 13: yield if block_given? 14: cv.broadcast 15: end 16: } 17: } 18: end ▶ exit -2-|2| Frame number: 0/2 ...
不用说,上述意味着线程停止直到pry
恢复。