本文介绍了调试线程红宝石应用程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发使用线程的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.0byebug

这就是我对Pry的经验.尝试1:我使用break

So here is what I experience with Pry. Try 1:I set the thread-specific breakpoint using break

  1. 让程序运行.
  2. 断点被触发.
  3. 撬开正确地显示断点和周围的代码.
  4. 现在什么都没有. 我没有提示. Control-C不起作用.实际上,我必须从外部杀死-9进程.
  1. Let program run.
  2. Breakpoint is triggered.
  3. Pry correctly shows me the breakpoint and surrounding code.
  4. 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.

  1. 相同
  2. 相同
  3. 一样!
  4. 我收到撬动提示!我可以产生表达式.
  5. 我尝试使用"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. 我尝试退出",现在我处于撬(主)"状态,没有其他任何作用.

撬出输出:

[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.

这篇关于调试线程红宝石应用程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-26 00:58