lutaml / expressir

Ruby parser for the ISO EXPRESS language
3 stars 2 forks source link

Crash on Ruby 3.0 and 3.1 after requiring `expressir/express/parser` #109

Closed ronaldtse closed 2 years ago

ronaldtse commented 2 years ago
$ irb
irb(main):001:0> quit
# Exits normally
$ irb
irb(main):001:0> require 'expressir/express/parser'
=> true
irb(main):002:0> quit
SEGV received in BUS handler
Abort trap: 6

Interestingly this only happens at exit?

From: https://github.com/lutaml/lutaml/issues/33

ronaldtse commented 2 years ago

I wonder if this is related to Expressir's occasional segfaults in #74

maxirmx commented 2 years ago

I was able to reproduce this issue on MacOS only Further, if I build express_parser extension using macOS toolchain (Apple clang) this issue is not reproducible either. I can see it only when pre-build extension is used and pre-build extension is created with Docker image https://github.com/rake-compiler/rake-compiler-dock

maxirmx commented 2 years ago

This is for the extension build at rake-compiler-dock

otool -L /Users/maxirmx/.rbenv/versions/3.0.0/lib/ruby/gems/3.0.0/gems/expressir-1.2.1-arm64-darwin/lib/expressir/express/3.0/express_parser.bundle    
/Users/maxirmx/.rbenv/versions/3.0.0/lib/ruby/gems/3.0.0/gems/expressir-1.2.1-arm64-darwin/lib/expressir/express/3.0/express_parser.bundle:
    /usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 904.4.0)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1292.60.1)

This is for locally built extension:

otool -L tmp/arm64-darwin21/express_parser/3.0.0/express_parser.bundle
tmp/arm64-darwin21/express_parser/3.0.0/express_parser.bundle:
    /Users/maxirmx/.rbenv/versions/3.0.0/lib/libruby.3.0.dylib (compatibility version 3.0.0, current version 3.0.0)
    /usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 1300.23.0)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1311.100.3)```

It looks like in the first static library was used and it may be the root cause

maxirmx commented 2 years ago

Latest findings If expressir is built with rake-compiler-dock, any call to rice causes this crash. I think it is some MacOS SDK compatibility problem since rake-compiler-dock uses 10.13, expressir compiles for 10.14 target but ruby 3 employs something higher

There are two possible approaches:

ronaldtse commented 2 years ago

I suppose we should do both?

maxirmx commented 2 years ago

@ronaldtse @opoudjis

Can I ask for your help, please ?

Attached please find an expresser prototype built differently. Does it fix this issue and https://github.com/metanorma/metanorma-cli/issues/272) in your environment ?

expressir-1.2.2-arm64-darwin-21.gem.gz

Your help is much appreciated. Thanks

ronaldtse commented 2 years ago

@maxirmx I've just tried it with Ruby 3.0 (it doesn't install on Ruby 3.1):

me:~/Downloads: gem install expressir-1.2.2-arm64-darwin-21.gem 
ERROR:  Error installing expressir-1.2.2-arm64-darwin-21.gem:
    expressir-1.2.2-arm64-darwin-21 requires Ruby version >= 3.0, < 3.1.dev. The current ruby version is 3.1.1.18.

When requiring 'expressir/express/parser', it can't find a library:

me:~/Downloads: rbenv shell 3.0.3
me:~/Downloads: gem install expressir-1.2.2-arm64-darwin-21.gem 
Fetching rice-4.0.3.gem
Successfully installed rice-4.0.3
Successfully installed expressir-1.2.2-arm64-darwin-21
2 gems installed
me:~/Downloads: irb
irb(main):001:0> require 'expressir'
=> true
irb(main):002:0> require 'expressir/express/parser'
/Users/me/.rbenv/versions/3.0.3/lib/ruby/gems/3.0.0/gems/expressir-1.2.2-arm64-darwin-21/lib/expressir/express/parser.rb:5:in `require_relative': dlopen(/Users/me/.rbenv/versions/3.0.3/lib/ruby/gems/3.0.0/gems/expressir-1.2.2-arm64-darwin-21/lib/expressir/express/express_parser.bundle, 0x0009): Library not loaded: /Users/maxirmx/.rbenv/versions/3.0.0/lib/libruby.3.0.dylib (LoadError)
  Referenced from: /Users/me/.rbenv/versions/3.0.3/lib/ruby/gems/3.0.0/gems/expressir-1.2.2-arm64-darwin-21/lib/expressir/express/express_parser.bundle
  Reason: tried: '/Users/maxirmx/.rbenv/versions/3.0.0/lib/libruby.3.0.dylib' (no such file), '/usr/local/lib/libruby.3.0.dylib' (no such file), '/usr/lib/libruby.3.0.dylib' (no such file) - /Users/me/.rbenv/versions/3.0.3/lib/ruby/gems/3.0.0/gems/expressir-1.2.2-arm64-darwin-21/lib/expressir/express/express_parser.bundle
    from /Users/me/.rbenv/versions/3.0.3/lib/ruby/gems/3.0.0/gems/expressir-1.2.2-arm64-darwin-21/lib/expressir/express/parser.rb:5:in `rescue in <top (required)>'
    from /Users/me/.rbenv/versions/3.0.3/lib/ruby/gems/3.0.0/gems/expressir-1.2.2-arm64-darwin-21/lib/expressir/express/parser.rb:1:in `<top (required)>'
    from <internal:/Users/me/.rbenv/versions/3.0.3/lib/ruby/3.0.0/rubygems/core_ext/kernel_require.rb>:85:in `require'
    from <internal:/Users/me/.rbenv/versions/3.0.3/lib/ruby/3.0.0/rubygems/core_ext/kernel_require.rb>:85:in `require'
    from (irb):2:in `<main>'
    from /Users/me/.rbenv/versions/3.0.3/lib/ruby/gems/3.0.0/gems/irb-1.3.7/exe/irb:11:in `<top (required)>'
    from /Users/me/.rbenv/versions/3.0.3/bin/irb:25:in `load'
    from /Users/me/.rbenv/versions/3.0.3/bin/irb:25:in `<main>'
/Users/me/.rbenv/versions/3.0.3/lib/ruby/gems/3.0.0/gems/expressir-1.2.2-arm64-darwin-21/lib/expressir/express/parser.rb:3:in `require_relative': cannot load such file -- /Users/me/.rbenv/versions/3.0.3/lib/ruby/gems/3.0.0/gems/expressir-1.2.2-arm64-darwin-21/lib/expressir/express/3.0/express_parser (LoadError)
    from /Users/me/.rbenv/versions/3.0.3/lib/ruby/gems/3.0.0/gems/expressir-1.2.2-arm64-darwin-21/lib/expressir/express/parser.rb:3:in `<top (required)>'
    from <internal:/Users/me/.rbenv/versions/3.0.3/lib/ruby/3.0.0/rubygems/core_ext/kernel_require.rb>:85:in `require'
    from <internal:/Users/me/.rbenv/versions/3.0.3/lib/ruby/3.0.0/rubygems/core_ext/kernel_require.rb>:85:in `require'
    from (irb):2:in `<main>'
    from /Users/me/.rbenv/versions/3.0.3/lib/ruby/gems/3.0.0/gems/irb-1.3.7/exe/irb:11:in `<top (required)>'
    from /Users/me/.rbenv/versions/3.0.3/bin/irb:25:in `load'
    from /Users/me/.rbenv/versions/3.0.3/bin/irb:25:in `<main>'
maxirmx commented 2 years ago

Thanks

maxirmx commented 2 years ago

Crash (segfault) happens during execution of static destructors of some Rice objects.
I believe we see it on MacOS precompiled extension because of some unknown specifics of osxcross clang compiler (as opposed to gcc and Apple native clang) To save space I refer to recent Google document that explains the risks and disadvantages of using non-trivially-destructable objects per se : https://google.github.io/styleguide/cppguide.html#Static_and_Global_Variables

PR #110 disables destructors for static objects. It may be considered as permanent solution IMHO

ronaldtse commented 2 years ago

Thank you @maxirmx ! I've created a new issue #111 to bump version so as to release this.