Bug 412929 - Can we grab a frame from Ruby land?
Summary: Can we grab a frame from Ruby land?
Status: REPORTED
Alias: None
Product: Heaptrack
Classification: Applications
Component: general (show other bugs)
Version: unspecified
Platform: Other Linux
: NOR normal
Target Milestone: ---
Assignee: Milian Wolff
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2019-10-14 04:51 UTC by Sam Saffron
Modified: 2019-10-14 23:42 UTC (History)
0 users

See Also:
Latest Commit:
Version Fixed In:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Sam Saffron 2019-10-14 04:51:09 UTC
An interesting improvement would be allow at least 1 frame from Ruby land when possible. 

It could make it way easier to isolate Ruby leaks cause the backtrace would be richer allowing for the place in Ruby that caused a bug. Clearly this seems somewhat optional but in the cases where we have it, it could be quite amazing. Not sure if we need the entire backtrace cause that could be a bit expensive to grab.

https://80x24.org/mwrap.git

https://80x24.org/mwrap.git/tree/ext/mwrap/mwrap.c#n209

https://80x24.org/mwrap.git/tree/ext/mwrap/mwrap.c#n426
Comment 1 Milian Wolff 2019-10-14 12:04:48 UTC
I'm all for finding a way to inject frames from scripting languages in some way, but so far I haven't gotten there. It will require some kind of API that would then be called by ruby. Or do you have something else in mind?
Comment 2 Sam Saffron 2019-10-14 23:42:05 UTC
Yeah I think usability wise the best thing would be:

```
gem install heaptrack_ruby

# in the ruby script
require 'heaptrack_ruby'
```

Then heaptrack can publish some sort of library to register callbacks for scripting languages, and the ruby gem can then on require simply register the "lookup frame function" in the heaptrack library. 

Then you would use libunwind to get your stack followed by calling the callback which is injected via ruby.

The actual code the Ruby extension would call to get the frame is along the lines of:

```
if (ruby_thread_has_gvl_p() && ruby_current_vm_ptr &&
		ruby_current_execution_context_ptr) {
  int line;
  const char *ptr = rb_source_location_cstr(&line);
}
```

So I guess the signature of the method would be something like this if my C is write which it is likely not:

```
heaptrack_register_backtrace_lookup( *(char**)(void) )
```