调试线程化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正确地向我显示了断点和周围的代码 现在什么都没有了。我

我正在开发一个使用线程的ruby应用程序。我调试它有困难。主要的问题是我想一步一步地完成一个特定的线程。我设置断点并运行,但在使用类似
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
    ...