macOS のフォークテストで発生する PostgreSQL GSS 暗号化クラッシュを回避
この PR は macOS 上で ReaperTest#test_connection_pool_starts_reaper_in_fork がクラッシュする原因を除去し、テストの安定化を実現します。具体的には、フォーク後の子プロセスで PostgreSQL 接続時に GSS 暗号化交渉を無効化し、セグメンテーションフォルトを防ぎます。
背景
macOS では fork() 後に子プロセスが新しい PostgreSQL 接続を作成すると、libpq の GSS 暗号化交渉が非 fork‑safe な Heimdal/Keychain スタックを呼び出し、セグメンテーションフォルト が発生します。テスト ReaperTest#test_connection_pool_starts_reaper_in_fork はこのコードパスをたどるため、CI 環境でも頻繁に失敗していました。この問題は PostgreSQL バグ #16041 と ruby‑pg イシュー #538 にも記録されており、現時点で根本的な修正は提供されていません。
技術的な変更
PR ではフォークされた子プロセスが ConnectionPool を生成する直前に GSS 暗号化を無効化する設定を追加しました。具体的な差分は以下の通りです。
変更前:
pool_config = duplicated_pool_config(reaping_frequency: "0.0001")
変更後:
pool_config = duplicated_pool_config(reaping_frequency: "0.0001", gssencmode: "disable")
duplicated_pool_config に gssencmode: "disable" を渡すことで、子プロセス側の環境変数 PGGSSENCMODE=disable が内部的に設定され、libpq の GSS パスがスキップされます。この変更はテストコードのみで完結しており、プロダクションコードや他のテストケースには影響しません。
設計判断
本変更は 環境依存の不安定要素をテスト側で除外 するという方針に基づいています。上流の PostgreSQL バグが解消されるまでの暫定策として、問題のある暗号化機構をオプションで無効化できるように設計されています。代替案として adapter のデフォルト設定を変更する案も考えられましたが、既存の設定や他プラットフォームへの影響を最小化するため、テストケースに限定したパラメータ追加が選択されました。このアプローチにより、後方互換性を保ちつつ macOS 固有のクラッシュを回避できます。
まとめ
gssencmode: "disable" をテスト用プール設定に組み込むことで、macOS の fork 環境で発生していた PostgreSQL GSS 暗号化関連のセグメンテーションフォルトを防止しました。上流バグが解消されるまでの安全策として、テストコードに限定した設定拡張という設計判断がなされた点が本変更の核心です。