delhi09の勉強日記

技術トピック専用のブログです。自分用のメモ書きの投稿が多いです。あくまで「勉強日記」なので記事の内容は鵜呑みにしないでください。

Rails開発でのDISABLE_SPRING=trueのおまじないの意味をある程度理解する

前提

今の案件に参画当時、Railsのローカルの開発環境でrails consoleを実行してActive RecordでのDB操作を試みたり、rails runnerでDB操作を伴うコマンドを実行したりすると以下のようなエラーが発生するという事象に遭遇しました。

rails serverは正常に実行できました。

エラー

objc[8247]: +[Swift.__SharedStringStorage initialize] may have been in progress in another thread when fork() was called.
objc[8247]: +[Swift.__SharedStringStorage initialize] may have been in progress in another thread when fork() was called. We cannot safely call it or ignore it in the fork() child process. Crashing instead. Set a breakpoint on objc_initializeAfterForkError to debug.

案件内では既知の事象で対応が確立されており、以下のようにrails console実行時に先頭にDISABLE_SPRING=trueを付与することで解消できました。

DISABLE_SPRING=true bundle exec rails console

この事象はRailの公式リポジトリ上でもissue化されています。

github.com

ただ自分の中で完全におまじない化しているので、この機会にこのオプションの意味をある程度理解してみたいと思います。

環境

AppleシリコンのMacを使っています。

DISABLE_SPRING=true の意味

DISABLE_SPRING=true は直接的にはSpringというライブラリを無効化しています。

github.com

Springについては、以下のREADMEの説明の通り、開発環境での性能を改善してくれるライブラリのようです。

Spring is a Rails application preloader. It speeds up development by keeping your application running in the background, so you don't need to boot it every time you run a test, rake task or migration.

※ Rails7以降はSpringはデフォルトではインストールされない

SpringはRails7以降はデフォルトではインストールされなくなっています。従って、Rails7以降を使っている場合は明示的にSpringを使っている環境が対象になります。

Spring is no longer on by default, as faster computers have made it less relevant on anything but the largest applications.

rubyonrails.org

github.com

なぜSpringを使うと冒頭のエラーが発生するのか

github.com

上記のissueのやり取りをAIに解説してもらったところ、ざっくり以下のような感じのようです。

  • Springは内部でforkというMac OSAPIを呼んでいる
  • Mac OS側でforkの使い方がセキュアではないと判断してエラーで落としている

そのため、issueではOBJC_DISABLE_INITIALIZE_FORK_SAFETY=YESとしてMacのセキュリティ設定の方を変更する対応も提案されています。 (私の環境では機能しませんでした)

加えて、Springが使われるのはconsole, runner, generate, destroy, test のコマンドのみで、server は対象ではないそうです。

kinoppyd.dev

たしかにrails consoleを実行した場合は、Running via Spring preloader in process xxxというメッセージが表示されますが、rails serverでは表示されません。

rails serverでは発生しなかった理由が理解できます。

まとめ

おまじないだったDISABLE_SPRING=trueの意味が多少は理解できました。

  • 冒頭のエラーの原因はSpringという開発環境の性能向上用のライブラリがMac OSと相性が悪いことに起因
  • DISABLE_SPRING=trueはSpringを無効化している