如何让ruby pry停止所有其他线程

如何让ruby pry停止所有其他线程,ruby,multithreading,pry,Ruby,Multithreading,Pry,我试图调试一个多线程ruby脚本,问题是当我调试时 binding.pry 其他线程继续向控制台发送输出。如何使它们在绑定时停止。撬起,然后在退出时重新启动?我想在.pryrc中有一种方法可以做到这一点。如果binding.pry产生不一致的结果,请尝试以下操作: 如果存在,请从GEM文件中删除pry-stack_explorer,然后 重新打包您的应用程序。这家创业板似乎与中国存在问题 用ebug撬 此外,不确定您是否已经尝试过此操作,但有几个服务器 重启不会有什么伤害;这为我们解决了类似这

我试图调试一个多线程ruby脚本,问题是当我调试时

binding.pry

其他线程继续向控制台发送输出。如何使它们在绑定时停止。撬起,然后在退出时重新启动?我想在.pryrc中有一种方法可以做到这一点。如果binding.pry产生不一致的结果,请尝试以下操作:

  • 如果存在,请从GEM文件中删除
    pry-stack_explorer
    ,然后 重新打包您的应用程序。这家创业板似乎与中国存在问题
    用ebug撬

  • 此外,不确定您是否已经尝试过此操作,但有几个服务器 重启不会有什么伤害;这为我们解决了类似这样的奇怪问题 我比我想承认的要多

  • 但是,您可能试图做一些绑定无法完成的事情。pry:

    关于
    binding.pry
    必须理解的一个基本点是,它的作用域仅包括当前线程,而不是您所描述的多线程应用程序中的每个线程

    假设,如果
    binding.pry
    确实影响了每个线程(同样,它不会),这将导致不可预测的行为,特别是当某些线程正在执行数据访问/检索/更新操作时

    要实现您的目标,您可能需要采取不同的方法:


    尽管根据应用程序中的线程数量,这可能会很繁琐,但您可能需要单独控制/停止每个线程。显然,这可以通过
    Thread.stop
    来完成。听起来您建议使用调用
    binding.pry
    来询问所有子线程,并将它们挂起,直到您结束pry会话。由于技术和实际原因,这是不可能的。
    绑定
    线程
    类不是这样工作的,Ruby中的多线程也不是这样工作的

    Ruby中的线程只能通过调用
    Kernel\sleep
    Thread.stop
    来挂起。(这些方法在功能上是等价的)至关重要的是,这些方法只能在当前线程上调用。(
    Thread.stop
    是类方法,不是实例方法)

    让我们看看binding.pry实际上做了什么:类的对象将执行上下文封装在代码中的某个特定位置,并保留该上下文以备将来使用。因此,当您将
    binding.pry
    放入代码中时,您告诉Ruby封装当前线程的执行上下文

    这意味着,当您在主线程中调用
    binding.pry
    时,绑定对象具有当前线程的上下文,可以告诉自己睡眠,但核心Ruby线程类不允许它告诉任何其他线程睡眠

    即使它真的支持它,它也会很奇怪,容易出错,而且会引起很多麻烦。假设您有这样的代码:

    # we are in the main thread
    Thread.new do
      # we are in the child thread
      foo = Foo.new(bar.fetch(:baz, {}))
      foo.save
    end
    
    # we are in the main thread
    binding.pry
    
    由于Ruby处理的方式,如果
    binding.pry
    告诉所有子线程停止,那么子线程可能会停止调用堆栈中的任何位置,包括
    Foo.new
    的代码中的任何位置。在执行代码的过程中,如果这些线程停顿和恢复,则会给您带来麻烦。例如,如果池中的ActiveRecord连接被签出并用于
    SELECT
    查询,但线程在返回到池的连接和得到响应之前进入睡眠状态,会发生什么情况?坏东西。很多坏东西

    听起来真正的解决方案是更改子线程的详细程度。如果您正在对聊天代码进行故障排除,而您的其他线程在尝试在单个线程中工作时发出噪音,那么请将其他线程设置为临时使用较低的日志记录级别。

    根据:

    线程不工作,怎么了? 有些系统(特别是Mac OS X)使用Editline而不是GNU Readline。Ruby Readline库当前在使用Editline库编译时存在一个问题,这使得它阻止所有线程,而不仅仅是调用Readline.Readline()的线程(它在保持全局VM锁的同时阻止其他线程获取它)。这可以通过安装来修复

    <> P>这听起来像是用EdgRead构建的Rube阻止了所有线程,正如PrY所预期的那样,PRY的开发者认为这是一个bug。我找不到任何方法可以使用Pry自动阻止对
    binding.Pry的一次调用中的所有线程

    建议在调用
    binding.pry
    之前使用互斥锁同步线程。显然,这需要对代码进行更改,并且您可能不希望仅仅为了调试而同步线程。另一方面,同步线程确实减少了不确定性,并且可能在根本不使用Pry的情况下使调试更容易

    或者,您可以在每个线程中放置断点:

    require 'pry'
    
    Thread.new do
      10.times do |i|
        binding.pry
        puts "subthread: #{i}"
      end
    end
    
    
    10.times do |i|
      binding.pry
      puts "main thread: #{i}"
    end
    
    这将在特定时刻停止主线程和子线程的执行。不幸的是,如果您想检查另一个线程,或者确切地知道当前线程停止时它在哪里,那么这将没有帮助。如果当前没有调试,注释掉所有断点也有点麻烦。(但您可以通过将disable_Pry环境变量设置为非nil值来完全禁用Pry。)

    如果您真的需要调试一个多线程程序,您可能会希望使用这样的工具来提供更多的支持