如何配置ruby以在Ctrl-C(SIGINT)上进入调试器?

时间:2013-03-07 17:46:22

标签: ruby debugging signals sigint

我想在输入ctrl-C(或发送SIGINT)时输入调试器。我有installed the debugger(我正在运行Ruby 1.9.3)并验证它是否有效。我已将此添加到我的安装文件中(这适用于Padrino,但我认为它与Rails类似):

# file: config/boot.rb
Padrino.before_load do
  trap("SIGINT") { debugger } if Padrino.env == :development
end

...但是输入Ctrl-C不会调用调试器。实际上,如果我将debugger替换为puts "saw an interrupt!",则键入Ctrl-C也不会导致打印。

更新

this suggestion关注Mike Dunlavey后,我尝试在调试器中明确调用catch Interrupt

$ rdebug `which padrino` console
^Z^Z$HOME/usr/bin/padrino:9
require 'rubygems'
(rdb:1) catch Interrupt
Catch exception Interrupt.
(rdb:1) c
=> Loading development console (Padrino v.0.10.7)
=> Loading Application BlueDotAe
=> Loading Application Admin
irb(main):001:0>   C-c C-c^C
irb(main):001:0> 

没有欢乐 - 中断没有进入调试器。

我错过了什么?

2 个答案:

答案 0 :(得分:4)

如果你想在控制台中运行时捕获SIGINT,简短的回答是:除非你修补IRB,否则你不能。每个使用控制台的Ruby应用程序(无论是padrino,rails还是诸如此类)最终都会调用usr/lib/ruby/1.9.1/irb.rb,而IRB.start中的所有应用程序都会调用:

trap("SIGINT") do
  irb.signal_handle
end

...在进入主循环之前。这将覆盖您可能在启动代码中添加的任何陷阱(“SIGINT”)。

但是如果你想在一个脚本文件中捕获SIGINT(例如,如果你想按照by Mike Dunlavey here描述你的代码),你可以创建一个脚本文件,如:

# File: profile_complex_operation.rb
trap("SIGINT") { debugger }
MyApp.complex_operation

然后按以下方式调用它:

$ ruby profile_complex_operation.rb

现在,当你点击^ C(或从另一个进程发送SIGINT)时,它将进入调试器。

答案 1 :(得分:1)

您可以尝试使用GDB wrapper for RubyGitHub)。

通过以下方式在Linux上安装:

sudo apt-get install gdb python-dev ncurses-dev ruby-rvm
gem install gdb.rb

基本用法:

require 'gdb'

# create a new GDB::Ruby instance and attach it to
# pid 12345
gdb = GDB::Ruby.new(12345)

# print the (ruby) backtrace of the remote process
gdb.backtrace.each { |line| puts line }

# show the current local variables, and their values
p gdb.local_variables

# evaluate arbitrary ruby code in the remote process
p gdb.eval('%(pid #{$$})')

# show how many instances of each class exist in the
# remote process
p gdb.object_space

# raise an exception in the remote process
gdb.raise Exception, "go boom!"

# close the connection to the remote process
gdb.quit

或者调试挂起的进程,通过以下方式附加:

rvmsudo gdb.rb PID

然后:

# in gdb get a ruby stacktrace with file names and line numbers
# here I'm filtering by files that are actually in my app dir
(gdb) ruby eval caller.select{|l| l =~ /app\//}

来源:Using gdb to inspect a hung ruby process

一些替代方案:

  • rbtrace - 类似于strace,但是对于ruby代码(用法:rbtrace -p <PID> --firehose)。
  • tmm1(gdb.rb的作者)的
  • debug.rb脚本可以帮助使用strace / gdb调试进程。

另见: