Fixing Rails 5.2 Bus Error on ARMv7/Raspberry Pi
The Problem
Bringing up a small Rails 5.2 app on a Raspberry Pi 3B threw a really alarming bus error:
homebus@raspberrypi:~/HomeBus/current $ RAILS_ENV=production bin/rails s /home/homebus/HomeBus/shared/bundle/ruby/2.5.0/gems/bootsnap-1.3.0/lib/bootsnap/compile_cache/iseq.rb:18: [BUG] Bus Error at 0x02006b9d ruby 2.5.1p57 (2018-03-29 revision 63029) [armv7l-linux-eabihf] -- Control frame information ----------------------------------------------- c:0122 p:---- s:0641 e:000640 CFUNC :load_from_binary c:0121 p:0014 s:0636 e:000635 METHOD /home/homebus/HomeBus/shared/bundle/ruby/2.5.0/gems/bootsnap-1.3.0/lib/bootsnap/compile_cache/iseq.rb:18 [FINISH] c:0120 p:---- s:0630 e:000629 CFUNC :fetch c:0119 p:0069 s:0623 e:000622 METHOD /home/homebus/HomeBus/shared/bundle/ruby/2.5.0/gems/bootsnap-1.3.0/lib/bootsnap/compile_cache/iseq.rb:37 [FINISH] c:0118 p:---- s:0617 e:000616 CFUNC :require c:0117 p:0013 s:0612 e:000611 BLOCK /home/homebus/HomeBus/shared/bundle/ruby/2.5.0/gems/bootsnap-1.3.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:21 c:0116 p:0005 s:0609 e:000608 METHOD /home/homebus/HomeBus/shared/bundle/ruby/2.5.0/gems/bootsnap-1.3.0/lib/bootsnap/load_path_cache/loaded_features_index.rb:65 ...
A “bus error” is a hardware indication that a program tried to access memory that the hardware can’t address. It might be an alignment error (CPUs often have strict requirements about how data or instructions are aligned on even or odd word boundaries - don’t worry if that doesn’t mean anything to you). It’s not a permissions problem - it’s not caused by a program trying to access memory it’s not allowed to.
It’s a very low level fault which shouldn’t happen and may indicate a hardware issue or a compiler or language bug.
Debugging
I tried swapping the microSD card into another Raspberry Pi and got the same problem. I tried doing a clean reinstall on a new microSD card and also saw the same problem. So it wasn’t likely to be a hardware issue.
The problem seems to be a bad interaction between the bootsnap gem and the Ruby virtual machine. Rails 5.2 started using bootsnap in order to reduce startup time - and it works well, bootsnap is awesome - startup time may be improved by 50%. On ARMv7 CPUs there’s a bad interaction between bootsnap’s caching and the Ruby VM. This happens with multiple versions of Ruby - at the least, Ruby 2.4.1 through Ruby 2.5.1. It may be fixed in Ruby 2.6, or at least its frequency reduced.
Workaround
Phil Ferne suggests an easy workaround: edit Rails’ config/boot.rb file and comment out
# require 'bootsnap/setup'
This will disable bootsnap. If you deploy your Rails app to multiple platforms and want the benefits of bootsnap on CPUs other than ARMv7, you might try something like this in your config/boot.rb :
unless File.exists?("/proc/cpuinfo") && File.read("/proc/cpuinfo").include?("ARMv7") require 'bootsnap/setup' end
Hopefully Ruby 2.6 or a release soon after it will permanently fix this problem.