💎

Puma の Cluster mode で TypeError が発生する

2024/03/29に公開

Rails アプリで Puma の Cluster mode を使おうとしたら下記のようなログが表示され、リクエストが返ってこなかった。

# 起動時
/Users/foo/.anyenv/envs/rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/stringio-3.1.0/lib/stringio.bundle: warning: already initialized constant StringIO::VERSION
# リクエスト時
2024-03-29 11:42:22 +0900 Listen loop: #<TypeError: wrong argument type strio (expected strio)>

調べたところ下記の条件で発生するらしいことがわかった。

  • Puma を Cluster mode で起動
  • Puma で prune_bundler を有効に
  • bootsnap を使っていて load_path_cache を有効に (require "bootsnap/setup" 使っていれば有効)
  • Ruby 3.2 (3.0, 3.1 では発生しないことを確認)
  • Gemfile.lock に psych がある

上記の条件を満たした上で require "yaml" を実行すると前掲の起動時のログが表示される。デフォルトだと bootsnap 内で require "yaml" が呼ばれるが、ここ以外で呼んでも同じ。

いまのところ根本的な解決方法がわかっていない (どこの issue に投げたらいいのかもわからない...) ので上記の条件のいずれかを回避する。

再現

mkdir puma_bootsnap_issue
cd puma_bootsnap_issue
rbenv local 3.2.2
# Gemfile
source "https://rubygems.org"

gem "bootsnap", "~> 1.18"
gem "sinatra", "~> 4.0"
gem "psych", "~> 5.1"
gem "puma", "~> 6.4"
# my_app.rb
require "bootsnap/setup"
require "yaml"

require "sinatra/base"

class MyApp < Sinatra::Base
  get "/" do
    "Hello"
  end
end
# config.ru
require "./my_app"
run MyApp
bundle
BOOTSNAP_CACHE_DIR=. bundle exec puma --prune-bundler -w 2

Discussion