Rails6 + Springな開発環境で環境変数をたくさん設定したらrails consoleがハングしたw
以下の環境でrails consoleを使おうと思ったらハングしました。
- Mac OS X 10.14.6
- Ruby 2.7
- Rails.envは
development
- Rails 6.0.3.1 or 6.0.3.2
- Spring 2.0.1(Springのバージョンは関係ない気がするが念の為)
原因はSpringの内部処理でsocketに環境変数を書き込む下記の処理の際に
# https://github.com/rails/spring/blob/v2.0.1/lib/spring/client/run.rb#L144 def run_command(client, application) log "sending command" application.send_io STDOUT application.send_io STDERR application.send_io STDIN send_json application, "args" => args, "env" => ENV.to_hash ... ensure application.close end # https://github.com/rails/spring/blob/v2.0.1/lib/spring/client/run.rb#L206 def send_json(socket, data) data = JSON.dump(data) socket.puts data.bytesize # 環境変数を書き込む処理 # dataには `JSON.dump(ENV.to_hash)` が入っている socket.write data end
書き込む環境変数のバイト数が大体128.4KBを超えると書き込みバッファが溢れてるっぽく、ここでハングしてしまってました。環境変数の容量を128.3KB以下に減らしたところハングせずに書き込めたため環境変数の容量が悪いと判断し、使っていなかった変数を消す作業を行い事なきを得ました。
※ 溢れてるっぽく
と書いたのは socket.write data
以降の処理にbinding.pryのstepで入れなかったためです。socket.writeの実態はIO#writeで、このメソッドはCで実装されているためこれ以上pryでデバッグできないんじゃないかと思ったのが諦めた背景です(ruby/rubyのコードもデバッグできるようになりたい...)。
後々社内の別の開発者がVM上のubuntu環境で同じ環境変数を用意してrails consoleを実行したところErrno::E2BIGが出ていました。E2BIGはLinuxによって定義されたシステムエラーの1つで、単一の引数や環境変数の文字列が128KBより大きい場合に返されるエラーなので、やはり環境変数の容量の問題だったねーということになりました。