danielpclark / rutie

“The Tie Between Ruby and Rust.”
MIT License
939 stars 62 forks source link

Ruby 3.0.4 SegFault when running `Fiddle::Function#call` #161

Open antstorm opened 2 years ago

antstorm commented 2 years ago

Dear @danielpclark,

First of all thank you for an amazing library!

I've ran into a problem that turned out to be a proper head scratcher. Basically I took the example from this repo and was able to successfully run it on my machine (I'm using an M1 chip, just in case). I then replicated the setup in my own project and caught a Segmentation Fault when trying to initialize Rust bindings (it points to calling the Fiddle::Function#call method) — https://gist.github.com/antstorm/1d01c783e4c0b514c869b04a1c362144.

I was able to narrow the difference down to how I run the cargo rustc command — using the provided Rakefile vs just copying the same exact command to the terminal (it's cargo rustc --release -- -C link-args=-Wl,-undefined,dynamic_lookup in my case). Now here's the crazy part — running this command from an empty irb shell (just wrapping it in backticks) produces a dylib that works, while running the same command directly in the terminal shell doesn't.

I stumbled upon this issue and did a cargo clean to get a fresh start. This unfortunately (as far as I can tell) did not affect the behaviour at all.

I can replicate this behaviour consistently in Ruby 3.0.4 and 3.1.2. However both approaches work just fine in Ruby 3.0.3.

I also ran the diff on the target directories produced by the 2 approaches and this is what I got (as far as I can tell the only difference is the order of the keys inside the "outputs" map, the keys themselves and their values are identical):

diff target/.rustc_info.json target2/.rustc_info.json
1c1
< {"rustc_fingerprint":9631749218497856628,"outputs":{"931469667778813386":{"success":true,"status":"","code":0,"stdout":"___\nlib___.rlib\nlib___.dylib\nlib___.dylib\nlib___.a\nlib___.dylib\n/opt/homebrew/Cellar/rust/1.59.0\ndebug_assertions\nproc_macro\ntarget_arch=\"aarch64\"\ntarget_endian=\"little\"\ntarget_env=\"\"\ntarget_family=\"unix\"\ntarget_os=\"macos\"\ntarget_pointer_width=\"64\"\ntarget_vendor=\"apple\"\nunix\n","stderr":""},"5309432699494263626":{"success":true,"status":"","code":0,"stdout":"___\nlib___.rlib\nlib___.dylib\nlib___.dylib\nlib___.a\nlib___.dylib\n","stderr":""},"17598535894874457435":{"success":true,"status":"","code":0,"stdout":"rustc 1.59.0\nbinary: rustc\ncommit-hash: unknown\ncommit-date: unknown\nhost: aarch64-apple-darwin\nrelease: 1.59.0\nLLVM version: 13.0.0\n","stderr":""},"2797684049618456168":{"success":true,"status":"","code":0,"stdout":"___\nlib___.rlib\nlib___.dylib\nlib___.dylib\nlib___.a\nlib___.dylib\n","stderr":""}},"successes":{}}
\ No newline at end of file
---
> {"rustc_fingerprint":9631749218497856628,"outputs":{"931469667778813386":{"success":true,"status":"","code":0,"stdout":"___\nlib___.rlib\nlib___.dylib\nlib___.dylib\nlib___.a\nlib___.dylib\n/opt/homebrew/Cellar/rust/1.59.0\ndebug_assertions\nproc_macro\ntarget_arch=\"aarch64\"\ntarget_endian=\"little\"\ntarget_env=\"\"\ntarget_family=\"unix\"\ntarget_os=\"macos\"\ntarget_pointer_width=\"64\"\ntarget_vendor=\"apple\"\nunix\n","stderr":""},"2797684049618456168":{"success":true,"status":"","code":0,"stdout":"___\nlib___.rlib\nlib___.dylib\nlib___.dylib\nlib___.a\nlib___.dylib\n","stderr":""},"5309432699494263626":{"success":true,"status":"","code":0,"stdout":"___\nlib___.rlib\nlib___.dylib\nlib___.dylib\nlib___.a\nlib___.dylib\n","stderr":""},"17598535894874457435":{"success":true,"status":"","code":0,"stdout":"rustc 1.59.0\nbinary: rustc\ncommit-hash: unknown\ncommit-date: unknown\nhost: aarch64-apple-darwin\nrelease: 1.59.0\nLLVM version: 13.0.0\n","stderr":""}},"successes":{}}
\ No newline at end of file
Common subdirectories: target/release and target2/release

Am I going completely mad? What am I missing? Any help greatly appreciated.

UPDATES:

danielpclark commented 2 years ago

Hey @antstorm , Thank you for reporting this.

I do need to update the test suite to run with Ruby 3+, I was going to wait until there were at least 3 minor versions of Ruby released in the 3 series as there are some breaking changes if you use the garbage collection methods written here that have the word mark in their name. But I suppose I could target the HEAD of the Github repo as the 3rd version and update them.

Looking at the trace you've provided I see the example is still using Rutie version 0.0.4 rutie/examples/rutie_ruby_example/.gems/ruby/3.0.0/gems/rutie-0.0.4/lib/rutie.rb, can you try it with a recent release of Rutie and let me know how that goes?

The fact that you've found it changes between Ruby 3.0.3 and Ruby 3.0.4 is most helpful.

There are two documented cases of segfaults in the README and #142 talks about loading without Rutie#init. This might help provide insight.

antstorm commented 2 years ago

@danielpclark thank you for responding 🙌

Getting Ruby 3+ support out would be super useful. As far as I can tell GC methods are only useful when calling Ruby from Rust, so maybe it can be deemed a partial support of Ruby 3+ only for Ruby -> Rust use cases.

Is there a version newer than 0.0.4 of the Ruby gem? I'm using the 0.8.4 rutie cargo package, but couldn't find the new Ruby gem (checked both RubyGems and GitHub).

I will check if loading the bindings without Rutie#init helps, will report back

mfeckie commented 1 year ago

Running into the same problem here and I also can't find a version higher that 0.0.4

Any tips?