调试线程化ruby应用程序
我正在开发一个使用线程的ruby应用程序。我调试它有困难。主要的问题是我想一步一步地完成一个特定的线程。我设置断点并运行,但在使用类似调试线程化ruby应用程序,ruby,multithreading,debugging,Ruby,Multithreading,Debugging,我正在开发一个使用线程的ruby应用程序。我调试它有困难。主要的问题是我想一步一步地完成一个特定的线程。我设置断点并运行,但在使用类似thrsw2的东西之前,不会发生任何事情。但随后的输入是FUBAR'd。我试过pry,但pry在处理线程方面似乎没有更好的表现 解决方案?解决办法 编辑1: 仅供参考:Pry版本0.10.1在Ruby 2.0.0上使用byebug 下面是我对Pry的体验。尝试1:我使用break 让程序运行 断点被触发 Pry正确地向我显示了断点和周围的代码 现在什么都没有了。我
thrsw2
的东西之前,不会发生任何事情。但随后的输入是FUBAR'd。我试过pry,但pry在处理线程方面似乎没有更好的表现
解决方案?解决办法
编辑1:
仅供参考:Pry版本0.10.1在Ruby 2.0.0上使用byebug
下面是我对Pry的体验。尝试1:我使用break
让程序运行李>
断点被触发
Pry正确地向我显示了断点和周围的代码
现在什么都没有了。我没有提示。控制C不起作用。事实上,我必须从外部杀死-9进程李>
尝试2:使用上面的“binding.pry”方法
同样的
同样的
一样李>
我得到一个窥探提示!我能表达李>
我试图使用“步骤”或“下一步”,突然我进入了“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
可以很好地处理螺纹。您的代码中可能有小故障
让我们尝试检查以下线程切换器(示例):
注释掉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
=> #<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
...
帧编号:0/2
From:/tmp/a.rb@第12行SeqExec::Seqs#synch#u previor:
6:def同步之前的mx,cv
7:Thread.new{
8:mx.synchronize{
9:@init[:prior]=真
10:loop do
11:cv.wait mx
=>12:binding.pry
13:如果给定块,产量?
14:cv广播
15:完
16: }
17: }
18:完
▶ mx
=> #
▶ 出口
-1-|1|
帧编号:0/2
From:/tmp/a.rb@第12行SeqExec::Seqs#synch#u previor:
6:def同步之前的mx,cv
7:Thread.new{
8:mx.synchronize{
9:@init[:prior]=真
10:loop do
11:cv.wait mx
=>12:binding.pry
13:如果给定块,产量?
14:cv广播
15:完
16: }
17: }
18:完
▶ 出口
-2-|2|
帧编号:0/2
...
不用说,上述情况意味着线程将停止,直到恢复pry
为止。对我来说并不是这样。首先,您建议“代码中的小故障”会妨碍调试器正常工作。你知道这听起来有多荒谬吗?我正在编辑我的原始问题,以说明Pry和threads的问题。这听起来一点也不荒谬。例如,死锁将破坏任何调试器尝试(我知道这不是您的情况,只是一个示例。)我猜您应该尝试删除byebug
依赖项,并测试安装了pry的dry gemset上发生的情况。虽然我有一些线程调试的经验,但我从未遇到过您描述的行为(将步骤窥探到它自己的上下文中)。这就是为什么我建议您的代码/环境中存在一些小故障。当然,也存在一些小故障。这就是调试器的作用:P没有byebug
,我如何逐步
通过代码?好吧,你和我争辩过,调试器不应该屈服于小故障,但没有人是完美的:)不管怎样,你把我搞糊涂了。我担心,step
是pry自己的特性,因为ruby2。我已经试过了我用ebug提供的代码,它可以像一个符咒一样工作。我认为,上面的工作示例和您的开发代码之间的主要区别在于,设备设计通常没有中断,其他线程仍在运行,可能会结束,这将pry头脑中的东西混在一起。我建议您在每个线程中设置断点,以防止调试环境中出现竞态条件。令人沮丧的是,我必须从头开始测试线程。谢谢我会跟进。我无法获得标记格式来正确地将ruby输出显示为代码。我不知道为什么。
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
...