问题描述
我正在开发使用线程的ruby应用程序.我在调试它时遇到困难.主要问题是我想逐步浏览特定线程.我设置了断点并运行,但是直到使用thr sw 2
之类的东西之前,什么都没有发生.但是随后的输入是FUBAR'd.我尝试过撬,但是撬似乎在处理线程方面并不更好.
I am developing a ruby application which uses threads. I am having difficulty debugging it. The main problem is that I want to step through a particular thread. I set the breakpoint and run, but nothing happens until I use something like thr sw 2
. But then subsequent input is FUBAR'd. I have tried pry, but pry seems no better at dealing with threads.
解决方案?解决方法?
仅供参考:Pry version 0.10.1 on Ruby 2.0.0
和byebug
这就是我对Pry的经验.尝试1:我使用break
So here is what I experience with Pry. Try 1:I set the thread-specific breakpoint using break
- 让程序运行.
- 断点被触发.
- 撬开正确地显示断点和周围的代码.
- 现在什么都没有. 我没有提示. Control-C不起作用.实际上,我必须从外部杀死-9进程.
- Let program run.
- Breakpoint is triggered.
- Pry correctly shows me the breakpoint and surrounding code.
- Now nothing. I have no prompt. Control-C doesn't work. In fact, I have to kill -9 the process from outside.
尝试2:使用上面的"binding.pry"方法.
Try 2: Using the "binding.pry" method above.
- 相同
- 相同
- 一样!
- 我收到撬动提示!我可以产生表达式.
- 我尝试使用"step"或"next",然后突然进入"Pry :: history#load".因此,现在调试器已跳至正在处理输入本身的线程.这不起作用.
撬出输出:
[2] pry(#<QDS::Node::Primary>)> 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(#<Pry::History>)>
- 我尝试退出",现在我处于撬(主)"状态,没有其他任何作用.
撬出输出:
[1] pry(main)> continue
Error: Cannot find local context. Did you use `binding.pry`?
推荐答案
pry
可以很好地与线程配合使用.您的代码中可能存在故障.
pry
is just fine working with threads. There are probably glitches in your code.
让我们尝试检查以下线程切换器(示例已此处):
Let’s try to examine the following thread switcher (example was taken here):
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
的情况下,我们得出:
With binding.pry
uncommented, we yield:
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
=> #<Mutex:0xb21f204>
▶ 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
.
Needless to say, the above means that threads stopped until pry
is resumed.
这篇关于调试线程红宝石应用程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!