Apple Silicon M3でRailsアセットプリコンパイル時に発生するセグメンテーション違反の解決策
Ruby on Rails アセットプリコンパイル時のセグメンテーション違反:原因と解決策
この解説は、Apple Silicon (M3) 上で Ruby 3.3.0 と Docker (Kamal 使用) を使って Rails アセットをプリコンパイルする際に発生するセグメンテーション違反について、原因と解決策を分かりやすく日本語で説明します。
問題
以下のコマンドを実行時にセグメンテーション違反が発生する。
SECRET_KEY_BASE_DUMMY=1 ./bin/rails assets:precompile
原因
この問題は、Ruby 3.3.0 と Apple Silicon M3 チップの組み合わせで、concurrent-ruby
ライブラリを使用する際に発生する既知のバグが原因です。
解決策
以下のいずれかの方法で解決できます。
Ruby 3.2.x を使用する
Ruby 3.2.x バージョンではこの問題は発生しないため、ダウングレードすることで解決できます。
rbenv install 3.2.x
concurrent-ruby ライブラリのバージョンを 1.1.0 以下に固定する
concurrent-ruby
ライブラリのバージョン 1.1.1 以降には、この問題を引き起こすコードが含まれています。
gem 'concurrent-ruby', '~> 1.1.0'
bin/rails assets:precompile を bundle exec bin/rails assets:precompile に置き換える
この方法では、bundle
コマンドを使用して、concurrent-ruby
ライブラリの特定のバージョンを強制的にロードできます。
RAILS_MAX_THREADS 環境変数を設定する
RAILS_MAX_THREADS
環境変数を設定することで、concurrent-ruby
ライブラリによって使用されるスレッドの最大数を制限できます。
RAILS_MAX_THREADS=1 SECRET_KEY_BASE_DUMMY=1 ./bin/rails assets:precompile
この問題は、今後の Ruby 3.3.x のバージョンで修正される可能性があります。最新情報を常に確認するようにしてください。
- セグメンテーション違反とは、プログラムがアクセスできないメモリ領域にアクセスしようとしたときに発生するエラーです。
concurrent-ruby
ライブラリは、Ruby プログラムで並行処理を行うためのライブラリです。Kamal
は、Docker を使用して Rails アプリケーションを開発・デプロイするためのツールです。
# Gemfile
gem 'rails', '~> 6.1'
gem 'concurrent-ruby', '~> 1.1.1'
# config/application.rb
config.assets.precompile += %w( *.js *.css *.png *.jpg *.gif )
# app/assets/javascripts/application.js
//= require jquery
//= require rails-ujs
//= require turbolinks
//= require_tree .
# app/assets/stylesheets/application.css
/*
*= require_self
*= require_tree .
*/
このコードを実行すると、以下のエラーが発生します。
Segmentation fault (core dumped)
セグメンテーション違反を解決する他の方法
bin/rails assets:precompile コマンドのオプションを変更する
--trace
オプションを指定することで、セグメンテーション違反が発生した場所を特定できます。
SECRET_KEY_BASE_DUMMY=1 ./bin/rails assets:precompile --trace
SECRET_KEY_BASE_DUMMY=1 ./bin/rails assets:precompile --verbose
rails assets:precompile コマンドを別の環境で実行する
別の Ruby バージョン、別の OS、別のマシンでコマンドを実行することで、問題を解決できる可能性があります。
ruby-on-rails ruby concurrent-ruby