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