Bug #7214
closedRuby 2.0 breaks support for some debugging tools
Added by banister (john mair) about 12 years ago. Updated almost 12 years ago.
Description
Notably the "Pry" debugger breaks, and (though i haven't checked) I'm assuming the 'debugger' project as well. The reason for the breakages (as far as i can see) is that the rb_vm_make_env_object
function is now hidden. In the comments for 1.9.3's vm.c it was stated an alternative API for rb_vm_make_env_object
(see https://github.com/ruby/ruby/blob/ruby_1_9_3/vm.c#L53-60) would be provided, but I have been unable to find one.
Can you please inform me of where I can find the new API (if it exists), or alternatively, provide a work-around so we can get the debuggers working on Ruby 2.0
Thanks
Updated by ko1 (Koichi Sasada) about 12 years ago
Thank you for your comment.
I want to support debugging feature, but my hands doesn't work on it yet.
Does "debugging feature" guru attend RubyConf2012 next week?
I will attend it.
If there is (are), I want to finish a design (and an implementation I
hope) about it for 2.0.
Thanks,
Koichi
(2012/10/25 19:46), banister (john mair) wrote:
Issue #7214 has been reported by banister (john mair).
Bug #7214: Ruby 2.0 breaks support for some debugging tools
https://bugs.ruby-lang.org/issues/7214Author: banister (john mair)
Status: Open
Priority: Normal
Assignee:
Category:
Target version:
ruby -v: ruby 2.0.0dev (2012-10-18 trunk 37260) [x86_64-linux]Notably the "Pry" debugger breaks, and (though i haven't checked) I'm assuming the 'debugger' project as well. The reason for the breakages (as far as i can see) is that the
rb_vm_make_env_object
function is now hidden. In the comments for 1.9.3's vm.c it was stated an alternative API forrb_vm_make_env_object
(see https://github.com/ruby/ruby/blob/ruby_1_9_3/vm.c#L53-60) would be provided, but I have been unable to find one.Can you please inform me of where I can find the new API (if it exists), or alternatively, provide a work-around so we can get the debuggers working on Ruby 2.0
Thanks
--
// SASADA Koichi at atdot dot net
Updated by ko1 (Koichi Sasada) about 12 years ago
- Category set to core
- Assignee set to ko1 (Koichi Sasada)
- Target version set to 2.0.0
Updated by banister (john mair) about 12 years ago
Unfortunately I can't make it to rubconf2012.
What we need for Ruby 2.0 is the binding_of_caller
gem working (https://github.com/banister/binding_of_caller/blob/ruby-2.0/ext/binding_of_caller/binding_of_caller.c ). We need to generate Binding objects from parent frames further up the call-stack, and it looks like the thing stopping us in Ruby 2.0 is the visibility of the rb_vm_make_env_object
function.
We are using this binding_of_caller
functionality to great effect in the pry-rescue (https://github.com/conradirwin/pry-rescue ) and pry-stack_explorer (https://github.com/pry/pry-stack_explorer ) projects, they allow some very powerful smalltalk-style workflows, and it would be a great shame if they can't work in 2.0 as they work brilliantly in Ruby 1.9.2-1.9.3 currently.
I am willing to help in any way possible to make this a reality for Ruby 2.0, just let me know what you need.
Thanks!
Updated by ko1 (Koichi Sasada) about 12 years ago
(2012/10/28 5:14), banister (john mair) wrote:
Unfortunately I can't make it to rubconf2012.
What we need for Ruby 2.0 is the
binding_of_caller
gem working (https://github.com/banister/binding_of_caller/blob/ruby-2.0/ext/binding_of_caller/binding_of_caller.c). We need the ability to grab bindings from parent frames up the call-stack.We are using this
binding_of_caller
functionality to great effect in the pry-rescue (https://github.com/conradirwin/pry-capture) and pry-stack_explorer (https://github.com/pry/pry-stack_explorer) projects, they allow some very powerful workflows, and it would be a real shame if they can't work in 2.0 as they work brilliantly in Ruby 1.9.2-1.9.3 currently.I am willing to help in any way possible to make this a reality for Ruby 2.0, just let me know what you need.
Thank you. It is great information for me.
Can I find API description?
--
// SASADA Koichi at atdot dot net
Updated by banister (john mair) about 12 years ago
The API is this:
class methods¶
return the binding for the nth caller, where Binding.of_caller(0) == binding¶
Binding.of_caller(n)
return an array of all the caller bindings (this is useful when you want to take a snap-shot of the entire call stack for later inspection, as in pry-rescue)¶
Binding.callers
The number of frames currently on the stack¶
Binding.frame_count
instance methods¶
the frame type, e.g :block, :class, :top, :lambda, :method i.e VM_FRAME_MAGIC_METHOD¶
Binding#frame_type
The frame description, i.e cfp->iseq->name on 1.9.3, returns stuff like "block in my_method"¶
Binding#frame_description
Note that we skip some frames (such as VM_FRAME_MAGIC_IFUNC) as introspecting on them appears to return junk data.
Updated by ko1 (Koichi Sasada) about 12 years ago
Thank you for your explanation.
(2012/10/28 21:08), banister (john mair) wrote:
return the binding for the nth caller, where Binding.of_caller(0) == binding¶
Binding.of_caller(n)
`Kernel.binding' can't return binding of CFUNC.
Is it enough?
--
// SASADA Koichi at atdot dot net
Updated by banister (john mair) about 12 years ago
No problem, our current code skips CFUNC frames too :)
Are you thinking of exposing this API to Ruby (in core or stdlib) or just as a C API ?
Updated by ko1 (Koichi Sasada) about 12 years ago
(2012/10/28 22:59), banister (john mair) wrote:
No problem, our current code skips CFUNC frames too :)
Okay.
Are you thinking of exposing this API to Ruby (in core or stdlib) or just as a C API ?
I think it should be C API at Ruby 2.0.
or exposed on RubyVM::... (MRI, ruby 2.0 specific)?
--
// SASADA Koichi at atdot dot net
Updated by ko1 (Koichi Sasada) about 12 years ago
=begin
[PLEASE REVIEW!!]
= Abstract
I made debugger support interface.
https://github.com/ko1/ruby/compare/debugger_api
Currently, no docs, no tests.
Sorry for my laziness.
Please review it.
= Background
Generally, debugger needs two features.
(1) Flow (execution) control API
(2) Inpsection API
For (1), inserting breakpoints, watch points and so on.
However, I don't touch these features because of no time to discuss.
(set_trace_func and TracePoint will help it)
For (2), (2-1) inspecting current thread's frames, (2-2) thread frames and (2-3) global environment.
We can access (2-3) using Ruby's powerful reflecting features (such as global_variables and so on).
We lacks (2-1) and (2-2). Currently, we don't have flow control features ((1)'s feature) to stop other threads.
So I decide to support only (2-1) "inspecting current thread's frames".
To make (2-1), Binding.of_caller' (which is supported by 'binding_of_caller') gem is almost enough for debugger. However,
Binding.of_caller' is too powerful and it can break Ruby's semantics.
I feel that we need to restrict for debugging purpose.
= API
With above consideration, I made a new C/Ruby API.
https://github.com/ko1/ruby/compare/debugger_api
== C-Level APIs
Types:
- typedef struct rb_debug_inspector_struct rb_debug_inspector_t;
- typedef VALUE (*rb_debug_inspector_func_t)(const rb_debug_inspector_t *, void *);
Functions:
- VALUE rb_debug_inspector_open(rb_debug_inspector_func_t func, void *data);
- VALUE rb_debug_inspector_frame_binding_get(const rb_debug_inspector_t *dc, int index);
- VALUE rb_debug_inspector_frame_class_get(const rb_debug_inspector_t *dc, int index);
- VALUE rb_debug_inspector_backtrace_locations(const rb_debug_inspector_t *dc);
== Ruby-level APIs (RubVM::DebugInspector)
You can use the following APIs after "require 'rubyvm/debug_inspector'".
- RubVM::DebugInspector.open{|inspector| ...}
- RubVM::DebugInspector#backtrace_locations #=> locations array
- RubVM::DebugInspector#frame_binding(i) #=> i-th binding.
Generated bindings can bebroken' outside of
RubVM::DebugInspector.open' block
to avoid abusing this powerful feature (now, they are not broken) - RubVM::DebugInspector#frame_class(i) #=> i-th method class
Ruby level API is sample code of C-level APIs.
== Sample code
The following sample code is very simple debugger (breakpoint).
require 'rubyvm/debug_inspector'
def breakpoint
RubyVM::DebugInspector.open{|inspector|
$inspector = inspector
inspector.backtrace_locations.each_with_index{|location, i|
b = inspector.frame_binding(i) # binding is nil if it is for when C's context
vars = b ? b.eval('local_variables') : []
puts [i, location.to_s, vars, b, inspector.frame_class(i)].inspect
}
}
end
def foo
foo_a = foo_b = nil
breakpoint
end
hello = 1
foo
begin
# DebugInspector object is not active outside block of
# RubyVM::DebugInspector.open
p $inspector.backtrace_locations
rescue ArgumentError => e
p [:ok, e]
end
= Consideration
== Satisfaction
I'm sorry I don't make surveys about debugger APIs for current CRuby's debugger
and debuggers for alternative Ruby implementations.
Please point out that it is enough or not enough, misunderstood and so on.
== Toward Ruby 2.0.0
Ruby 2.0.0 spec was already frozen :(
Make debug_inspector gem for 2.0.0?
=end
Updated by ko1 (Koichi Sasada) about 12 years ago
I asked Matz about this feature.
His comments were:
(1) Do not need to break bindings at end of block. This is programmer's risk.
(2) Ruby-level API is also okay to contains Ruby 2.0.0.
Updated by ko1 (Koichi Sasada) about 12 years ago
I asked mame-san (2.0.0 release manager) about this feature.
His comments is:
DO IT ON A GEM SUCH A BIG FEATURE.
His comment is: it should be experimental just now. We need to make examination with real debugger.
Updated by Conrad.Irwin (Conrad Irwin) about 12 years ago
Hey ko1,
Your debugging API looks good :).
It would be great to do this in a gem, but we can't create binding objects anymore due to changes in symbol visibility. (for 1.9 we used rb_vm_make_env_object, but it's now not exported, see [1])
This patch "fixes" it, but there should be a better way: https://gist.github.com/2f19a3cffb1a7bdfaf22
Is there any chance you can make this function callable from C extensions?
Thanks!
Conrad
[1] https://github.com/banister/binding_of_caller/blob/ruby-2.0/ext/binding_of_caller/binding_of_caller.c#L156 (edit, updated link)
Updated by ko1 (Koichi Sasada) about 12 years ago
(2012/11/17 18:35), Conrad.Irwin (Conrad Irwin) wrote:
It would be great to do this in a gem, but we can't create binding objects anymore due to changes in symbol visibility. (for 1.9 we used rb_vm_make_env_object, but it's now not exported, see [1])
Why do you need `rb_vm_make_env_object'? New API is not enough?
--
// SASADA Koichi at atdot dot net
Updated by denofevil (Dennis Ushakov) about 12 years ago
I will try to rewrite ruby-debug-base for 2.0 using your fork during this week and will post about results
Updated by ko1 (Koichi Sasada) about 12 years ago
(2012/11/19 23:43), denofevil (Dennis Ushakov) wrote:
I will try to rewrite ruby-debug-base for 2.0 using your fork during this week and will post about results
Can I see ruby-debug-base source code?
I will try it and find out lacked feature.
--
// SASADA Koichi at atdot dot net
Updated by denofevil (Dennis Ushakov) about 12 years ago
Updated by ko1 (Koichi Sasada) about 12 years ago
(2012/11/20 17:46), denofevil (Dennis Ushakov) wrote:
Thanks! I'll try it.
BTW, I can't understand relationship between debugger' and
ruby-debug'.
--
// SASADA Koichi at atdot dot net
Updated by luislavena (Luis Lavena) about 12 years ago
On Tue, Nov 20, 2012 at 8:08 AM, SASADA Koichi ko1@atdot.net wrote:
Thanks! I'll try it.
BTW, I can't understand relationship between
debugger' and
ruby-debug'.
AFAIK: debugger gem was a response to many of the installation issues
ruby-debug-base19 had, specially due the need to download Ruby source
and extract the internal headers during installation.
Reason of fork:
https://github.com/cldwalker/debugger#reason-for-fork
And main differences:
https://github.com/cldwalker/debugger#whats-different-from-ruby-debug19
--
Luis Lavena
AREA 17
Perfection in design is achieved not when there is nothing more to add,
but rather when there is nothing more to take away.
Antoine de Saint-Exupéry
Updated by denofevil (Dennis Ushakov) about 12 years ago
luislavena (Luis Lavena) wrote:
AFAIK: debugger gem was a response to many of the installation issues
ruby-debug-base19 had, specially due the need to download Ruby source
and extract the internal headers during installation.
Actually link that I gave is sources of ruby-debug-base19x. These are both forks for the same reasons =)
ruby-debug-base19x was started earlier and intended to keep native frontend(base gem) and IDE/CLI backends separate.
Sources of the ruby-debug-base19x and debugger native part share lots of code
Updated by spastorino (Santiago Pastorino) almost 12 years ago
Hope this https://bugs.ruby-lang.org/issues/6586 could be done any time soon :)
Updated by nobu (Nobuyoshi Nakada) almost 12 years ago
- Status changed from Open to Third Party's Issue
Debuggers should use new TracePoint feature now.