Sorbet: srb tc segfault

Created on 8 May 2020  Â·  15Comments  Â·  Source: sorbet/sorbet

Input

https://github.com/will/sorbetsegfault

srb tc

Observed output

/Users/will/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/sorbet-0.5.5585/bin/srb: 
  line 46: 58729 Segmentation fault: 11  "${sorbet}" "${args[@]}"

Expected behavior

not segfault


/t/sorbetseqf (master)> bundle info sorbet
  * sorbet (0.5.5585)
    Summary: A Typechecker for Ruby
    Homepage: https://sorbet.run
    Path: /Users/will/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/sorbet-0.5.5585
/t/sorbetseqf (master)> ruby -v
ruby 2.7.0p0 (2019-12-25 revision 647ee6f091) [x86_64-darwin19]
bug unconfirmed

Most helpful comment

Just realized I'd begun bundling for deployment. bundle exec srb tc --ignore=vendor/ fixed the issue for me. Sharing in case others find helpful.

All 15 comments

backtrace

/t/sorbetseqf (master) [139]> lldb /Users/will/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/sorbet-static-0.5.5585-universal-darwin-19/libexec/sorbet
(lldb) target create "/Users/will/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/sorbet-static-0.5.5585-universal-darwin-19/libexec/sorbet"
ruCurrent executable set to '/Users/will/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/sorbet-static-0.5.5585-universal-darwin-19/libexec/sorbet' (x86_64).
(lldb) run
Process 78919 launched: '/Users/will/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/sorbet-static-0.5.5585-universal-darwin-19/libexec/sorbet' (x86_64)
Process 78919 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x8)
    frame #0: 0x000000010054f2d4 sorbet`sorbet::core::File::isPayload() const + 4
sorbet`sorbet::core::File::isPayload:
->  0x10054f2d4 <+4>:  movl   0x8(%rdi), %eax
    0x10054f2d7 <+7>:  decl   %eax
    0x10054f2d9 <+9>:  cmpl   $0x2, %eax
    0x10054f2dc <+12>: setb   %al
Target 0: (sorbet) stopped.
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x8)
  * frame #0: 0x000000010054f2d4 sorbet`sorbet::core::File::isPayload() const + 4
    frame #1: 0x000000010032062e sorbet`sorbet::resolver::(anonymous namespace)::resolveTypeMembers(sorbet::core::GlobalState&, sorbet::core::SymbolRef, std::__1::vector<std::__1::vector<std::__1::pair<sorbet::core::SymbolRef, sorbet::core::SymbolRef>, std::__1::allocator<std::__1::pair<sorbet::core::SymbolRef, sorbet::core::SymbolRef> > >, std::__1::allocator<std::__1::vector<std::__1::pair<sorbet::core::SymbolRef, sorbet::core::SymbolRef>, std::__1::allocator<std::__1::pair<sorbet::core::SymbolRef, sorbet::core::SymbolRef> > > > >&, std::__1::vector<bool, std::__1::allocator<bool> >&) + 3934
    frame #2: 0x000000010031f5bd sorbet`sorbet::resolver::Resolver::finalizeSymbols(sorbet::core::GlobalState&) + 685
    frame #3: 0x00000001003242cd sorbet`sorbet::resolver::Resolver::run(sorbet::core::GlobalState&, std::__1::vector<sorbet::ast::ParsedFile, std::__1::allocator<sorbet::ast::ParsedFile> >, sorbet::WorkerPool&) + 669
    frame #4: 0x00000001001468b7 sorbet`sorbet::realmain::pipeline::resolve(std::__1::unique_ptr<sorbet::core::GlobalState, std::__1::default_delete<sorbet::core::GlobalState> >&, std::__1::vector<sorbet::ast::ParsedFile, std::__1::allocator<sorbet::ast::ParsedFile> >, sorbet::realmain::options::Options const&, sorbet::WorkerPool&, bool) + 1063
    frame #5: 0x0000000100006532 sorbet`sorbet::realmain::realmain(int, char**) + 7298
    frame #6: 0x00000001000021cb sorbet`main + 11
    frame #7: 0x00007fff705edcc9 libdyld.dylib`start + 1

This segfaults for me also, on GNU/Linux, with sorbet 0.5.5685 and ruby 2.6.6p146.

I have issues with this as well using the circleci/ruby:2.6.6 docker image.

getting segfault after switch to ruby 2.7.1 and sorbet update (platform MacOS)

bundle exec srb tc
/Users/koenhandekyn/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0/gems/sorbet-0.5.5756/bin/srb: line 46: 99280 Segmentation fault: 11  "${sorbet}" "${args[@]}"

  * sorbet (0.5.5756)
    Summary: A Typechecker for Ruby
    Homepage: https://sorbet.run
    Path: /Users/koenhandekyn/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0/gems/sorbet-0.5.5756

debug and backtrace

lldb ~/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0/gems/sorbet-static-0.5.5756-universal-darwin-19/libexec/sorbet
(lldb) target create "/Users/koenhandekyn/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0/gems/sorbet-static-0.5.5756-universal-darwin-19/libexec/sorbet"
Current executable set to '/Users/koenhandekyn/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0/gems/sorbet-static-0.5.5756-universal-darwin-19/libexec/sorbet' (x86_64).
(lldb) run
Process 99441 launched: '/Users/koenhandekyn/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0/gems/sorbet-static-0.5.5756-universal-darwin-19/libexec/sorbet' (x86_64)
Process 99441 stopped
* thread #3, name = 'typecheck', stop reason = EXC_BAD_ACCESS (code=1, address=0x28)
    frame #0: 0x000000010056a034 sorbet`sorbet::core::File::isStdlib() const + 4
sorbet`sorbet::core::File::isStdlib:
->  0x10056a034 <+4>:  movzbl 0x28(%rdi), %esi
    0x10056a038 <+8>:  testb  $0x1, %sil
    0x10056a03c <+12>: jne    0x10056a04a               ; <+26>
    0x10056a03e <+14>: addq   $0x28, %rdi
Target 0: (sorbet) stopped.
(lldb) bt
* thread #3, name = 'typecheck', stop reason = EXC_BAD_ACCESS (code=1, address=0x28)
  * frame #0: 0x000000010056a034 sorbet`sorbet::core::File::isStdlib() const + 4
    frame #1: 0x00000001002d8a26 sorbet`sorbet::definition_validator::ValidateWalk::preTransformMethodDef(sorbet::core::Context, sorbet::ast::TreePtr) + 150
    frame #2: 0x00000001002d6c6b sorbet`sorbet::ast::ShallowMapper<sorbet::definition_validator::ValidateWalk, sorbet::core::Context>::mapMethodDef(sorbet::ast::TreePtr, sorbet::core::Context) + 75
    frame #3: 0x00000001002d62a5 sorbet`sorbet::ast::ShallowMapper<sorbet::definition_validator::ValidateWalk, sorbet::core::Context>::mapIt(sorbet::ast::TreePtr, sorbet::core::Context) + 677
    frame #4: 0x00000001002d749b sorbet`sorbet::ast::ShallowMapper<sorbet::definition_validator::ValidateWalk, sorbet::core::Context>::mapClassDef(sorbet::ast::TreePtr, sorbet::core::Context) + 347
    frame #5: 0x00000001002d639d sorbet`sorbet::ast::ShallowMapper<sorbet::definition_validator::ValidateWalk, sorbet::core::Context>::mapIt(sorbet::ast::TreePtr, sorbet::core::Context) + 925
    frame #6: 0x00000001002d6f46 sorbet`sorbet::ast::ShallowMapper<sorbet::definition_validator::ValidateWalk, sorbet::core::Context>::mapInsSeq(sorbet::ast::TreePtr, sorbet::core::Context) + 182
    frame #7: 0x00000001002d62f5 sorbet`sorbet::ast::ShallowMapper<sorbet::definition_validator::ValidateWalk, sorbet::core::Context>::mapIt(sorbet::ast::TreePtr, sorbet::core::Context) + 757
    frame #8: 0x00000001002d749b sorbet`sorbet::ast::ShallowMapper<sorbet::definition_validator::ValidateWalk, sorbet::core::Context>::mapClassDef(sorbet::ast::TreePtr, sorbet::core::Context) + 347
    frame #9: 0x00000001002d639d sorbet`sorbet::ast::ShallowMapper<sorbet::definition_validator::ValidateWalk, sorbet::core::Context>::mapIt(sorbet::ast::TreePtr, sorbet::core::Context) + 925
    frame #10: 0x00000001002d6f46 sorbet`sorbet::ast::ShallowMapper<sorbet::definition_validator::ValidateWalk, sorbet::core::Context>::mapInsSeq(sorbet::ast::TreePtr, sorbet::core::Context) + 182
    frame #11: 0x00000001002d62f5 sorbet`sorbet::ast::ShallowMapper<sorbet::definition_validator::ValidateWalk, sorbet::core::Context>::mapIt(sorbet::ast::TreePtr, sorbet::core::Context) + 757
    frame #12: 0x00000001002d568c sorbet`sorbet::ast::TreePtr sorbet::ast::ShallowMap::apply<sorbet::core::Context, sorbet::definition_validator::ValidateWalk>(sorbet::core::Context, sorbet::definition_validator::ValidateWalk&, sorbet::ast::TreePtr) + 76
    frame #13: 0x00000001002d545b sorbet`sorbet::definition_validator::runOne(sorbet::core::Context, sorbet::ast::ParsedFile) + 155
    frame #14: 0x0000000100145379 sorbet`sorbet::realmain::pipeline::typecheckOne(sorbet::core::Context, sorbet::ast::ParsedFile, sorbet::realmain::options::Options const&) + 169
    frame #15: 0x000000010015cd6b sorbet`std::__1::__function::__func<sorbet::realmain::pipeline::typecheck(std::__1::unique_ptr<sorbet::core::GlobalState, std::__1::default_delete<sorbet::core::GlobalState> >&, std::__1::vector<sorbet::ast::ParsedFile, std::__1::allocator<sorbet::ast::ParsedFile> >, sorbet::realmain::options::Options const&, sorbet::WorkerPool&, bool, std::__1::optional<std::__1::shared_ptr<sorbet::core::lsp::PreemptionTaskManager> >)::$_4, std::__1::allocator<sorbet::realmain::pipeline::typecheck(std::__1::unique_ptr<sorbet::core::GlobalState, std::__1::default_delete<sorbet::core::GlobalState> >&, std::__1::vector<sorbet::ast::ParsedFile, std::__1::allocator<sorbet::ast::ParsedFile> >, sorbet::realmain::options::Options const&, sorbet::WorkerPool&, bool, std::__1::optional<std::__1::shared_ptr<sorbet::core::lsp::PreemptionTaskManager> >)::$_4>, void ()>::operator()() + 443
    frame #16: 0x00000001005ecd95 sorbet`std::__1::__function::__func<sorbet::WorkerPoolImpl::multiplexJob(std::__1::basic_string_view<char, std::__1::char_traits<char> >, std::__1::function<void ()>)::$_2, std::__1::allocator<sorbet::WorkerPoolImpl::multiplexJob(std::__1::basic_string_view<char, std::__1::char_traits<char> >, std::__1::function<void ()>)::$_2>, bool ()>::operator()() + 37
    frame #17: 0x00000001005ec36a sorbet`std::__1::__function::__func<sorbet::WorkerPoolImpl::WorkerPoolImpl(int, spdlog::logger&)::$_0, std::__1::allocator<sorbet::WorkerPoolImpl::WorkerPoolImpl(int, spdlog::logger&)::$_0>, void ()>::operator()() + 314
    frame #18: 0x00000001005edb64 sorbet`Joinable::trampoline(void*) + 68
    frame #19: 0x00007fff693a9109 libsystem_pthread.dylib`_pthread_start + 148
    frame #20: 0x00007fff693a4b8b libsystem_pthread.dylib`thread_start + 15

We're getting this error on ruby 2.6.5 on EC2 instances running AWS Linux 2. CI reports:

/var/lib/buildkite-agent/builds/buildkite-i-04a0ca492bb02a360-1/mynewsdesk/mynewsdesk/vendor/bundle/ruby/2.6.0/gems/sorbet-0.5.5790/bin/srb: line 46: 12015 Segmentation fault      "${sorbet}" "${args[@]}"
--
  | 🚨 Error: The command exited with status 139

Not sure what we can do to get a deeper stack trace output. If it would be helpful to add more info, let me know how we can produce it and I'll be glad to post it.

Apologies if this is a low-signal comment, but I'm still seeing this in the current release (0.5.5846) on Ruby 2.6.5:

$ bundle exec srb tc
/Users/duggiestyle/Projects/roboadvisor/vendor/bundle/ruby/2.6.0/gems/sorbet-0.5.5846/bin/srb: line 46: 36476 Segmentation fault: 11  "${sorbet}" "${args[@]}"

(Also, it would be nice if the output included some debugging suggestions.)

I appreciate the comment @dduugg. Maybe if there are enough posts on this issue, it may incite someone from stripe to at least acknowledge the existence of the problem.

Just realized I'd begun bundling for deployment. bundle exec srb tc --ignore=vendor/ fixed the issue for me. Sharing in case others find helpful.

Can confirm that we got srb to stop segfaulting on our CI by changing bundle install --path vendor/bundle to just bundle install (ie. relying on global gem installation). This has the unwanted consequence that we're not able to cache the vendor/bundle directory though so we end up having to install gem dependencies from scratch on each build for sorbet to run.

@will I would certainly appreciate an acknowledgement of the issue :)

I just started experiencing this issue past few days as well, running on ruby v2.5.7 and sorbet-0.5.5855

$ bundle exec srb etc

... /versions/2.5.7/lib/ruby/gems/2.5.0/gems/sorbet-0.5.5855/bin/srb: line 46: 63747 Segmentation fault: 11  "${sorbet}" "${args[@]}"

Still segfaulting on 0.5.5924 , and @dduugg 's workaround of ignoring the bundle directory makes it go away too. Thanks.

Another thing I found is that if you have too many classes defined in the rbi files it will segfault. This wouldn't have been the same reason as when I opened this, but could be something to look for.

I think I isolated the issue:

class Foo
  include Enumerable
end

class Bar < Foo
  Elem = type_member(:out)
end

Makes sorbet segfault: https://sorbet.run/#%23%20typed%3A%20true%0A%0Aclass%20Foo%0A%20%20include%20Enumerable%0Aend%0A%0Aclass%20Bar%20%3C%20Foo%0A%20%20Elem%20%3D%20type_member(%3Aout)%0Aend

This is what is happening with the definition in out.rbi coupled with DataSet including Enumerable in sequel.rbi.

Nice find @Morriar! I can reproduce that also

/tmp [1]> cat a.rb
class Foo
  include Enumerable
end

class Bar < Foo
  Elem = type_member(:out)
end
/tmp> srb tc a.rb
/Users/will/.asdf/installs/ruby/2.6.6/lib/ruby/gems/2.6.0/gems/sorbet-0.5.5923/bin/srb: line 46: 97347 Segmentation fault: 11  "${sorbet}" "${args[@]}"
/tmp [139]> srb --version
Sorbet typechecker 0.5.5923 git bccbb73b995e45eb8a9ed3123da5ac069438e9e5 debug_symbols=true clean=1

I am also seeing the seg fault.

⦗741fb18f develop ∙ϟ⦘
 api $ bundle exec srb tc --ignore=vendor/
/usr/local/var/rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/sorbet-0.5.5994/bin/srb: line 46:  2721 Segmentation fault: 11  "${sorbet}" "${args[@]}"
⦗741fb18f develop ∙ϟ⦘
 api $ ruby -v
ruby 2.7.2p137 (2020-10-01 revision 5445e04352) [x86_64-darwin19]

@dduugg's suggestion did not work. Any other ideas?

What does it take for this to become a confirmed bug?

Was this page helpful?
0 / 5 - 0 ratings