我正在使用gdb尝试追踪ruby程序中的内存泄漏。 我正在尝试打印一些调试数据(或将其写入文件),看来任何时候任何打印到任何IO的程序,程序都会在我分离后无法恢复。
简单的测试用例是一个程序如下:
#!/usr/bin/env ruby
counter = 0
loop do
puts "#{counter}\n"
counter += 1
sleep 1
end
然后我通过gdb -p PID
将gdb附加到进程,并在gdb控制台上运行p rb_eval_string("$stderr.puts(\"hi\\n\")")
。这导致分离后失败。如果我运行p rb_eval_string("a = 1")
并分离,则ruby进程将恢复正常。
如果我尝试写入文件或$stdout
而发生同样的问题。
程序无法恢复时的回溯如下所示:
(gdb) bt
#0 0x00007fcfb6617414 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib/x86_64-linux-gnu/libpthread.so.0
#1 0x0000000000543773 in native_cond_wait (mutex=0x15fcf30, cond=<optimized out>) at thread_pthread.c:309
#2 gvl_acquire_common (vm=0x15fcf20) at thread_pthread.c:64
#3 gvl_acquire (th=0x15fd520, vm=0x15fcf20) at thread_pthread.c:82
#4 native_sleep (timeout_tv=<synthetic pointer>, th=0x15fd520) at thread_pthread.c:918
我在Ubuntu Trusty上使用gdb版本7.7和ruby 1.9.3。
有人可以建议如何让程序恢复吗?
谢谢!
答案 0 :(得分:0)
我还不明白发生了什么,但可能是因为Ruby的sleep
以及rb_thread_sleep
使用native_sleep的方式(我可以在本地重现您的问题)。
而不是使用sleep
我只考虑使用高成本的方法,这将消耗几乎一秒钟,所以我决定只使用未经优化的fibonacci
: - )
以下是代码:
# fibo.rb
def fibonacci(n)
return n if (0..1).include?(n)
fibonacci(n-1) + fibonacci(n-2)
end
i = 0
loop do
fibonacci(30)
i += 1
puts "#### i = #{i}"
end
现在,你应该能够(请注意我使用的是lldb而不是gdb,但它是一样的(几乎是:-)):
➜ ~ lldb ruby
Current executable set to 'ruby' (x86_64).
(lldb) r foo.rb
Process 41134 launched: '/Users/xxx/.rubies/ruby-2.1.0/bin/ruby' (x86_64)
#### i = 1
Process 41134 stopped
* thread #1: tid = 0x72502, 0x00000001000c4820 ruby`range_include + 256, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
frame #0: 0x00000001000c4820 ruby`range_include + 256
ruby`range_include + 256:
-> 0x1000c4820: movq 0x16a691(%rip), %rsi ; id_cmp
0x1000c4827: movq %rbx, %rdi
0x1000c482a: movl $0x1, %edx
0x1000c482f: movq %r12, %rcx
(lldb) call (void)rb_eval_string("puts 42")
42
(lldb) c
Process 41134 resuming
#### i = 2
#### i = 3
...