Option Soupは、ビルドフラグの組み合わせが本番クラッシュを生む怖さを教えてくれる

Mozilla Hacks記事紹介シリーズのアイキャッチ画像

執筆者:

カテゴリ:

Mozilla Hacksの「Option Soup: the subtle pitfalls of combining compiler flags」を読みました。Firefox 120 Betaで発生したLinux向けクラッシュを入口に、配布パッケージのビルド設定、C++標準ライブラリ、ELFのシンボル解決まで掘っていく技術調査の記事です。

記事の要点

最初に見えていた現象は、WebGLページを開いたときにstd::locale::operator=周辺でクラッシュするというものでした。一見するとWebGLやANGLEの問題に見えますが、問題のコードはstd::ostringstreamstd::locale::classic()を設定するだけの普通のC++コードです。

調査を進めると、Ubuntu 18.04 LTS向けのFirefox Betaパッケージでlibstdc++が静的リンクされていることが分かります。古い環境に新しいC++ランタイムを持ち込むための現実的な工夫でしたが、Firefox側では-Bsymbolic-functionsも使われていました。この組み合わせにより、関数シンボルと変数シンボルの解決のされ方がずれ、std::localeの初期化状態がモジュール間で食い違う状況が生まれた、というのが記事の核心です。

参照先も確認したこと

元記事から、Bugzillaのクラッシュ報告Firefox Beta PPAUbuntu向けビルドログLaunchpadの関連バグGCC/libstdc++側の議論NixOS側のWebGLクラッシュ報告NixOSの関連PRFirefox configureへの検出追加を確認しました。

Bugzilla側でも、クラッシュはFirefox Build Systemの問題として扱われ、Firefox 120以降で修正対象になっています。NixOS側の報告でも、Firefox 120でWebGLを使うと落ちる再現手順が共有されており、Mozilla側の調査結果がディストリビューション側の修正にもつながったことが分かります。

気づき

今回の気づきは、ビルドフラグは個別には妥当に見えても、組み合わせるとランタイムの前提を壊すことがあるという点です。-static-libstdc++は古いOS向けに新しいC++機能を届けるための手段で、-Bsymbolic-functionsもシンボル解決を制御するための手段です。しかし、それぞれの意図が正しくても、標準ライブラリの内部状態を複数モジュールがどう共有するかという低いレイヤーで矛盾が出ることがあります。

この話は、Firefoxのような巨大プロジェクトだけの特殊事例ではありません。OS配布、独自ビルド、古い実行環境への対応、静的リンク、最適化フラグの追加は、多くのプロダクトでも起こり得ます。クラッシュがアプリケーションコードの近くに見えても、原因はビルド設定やリンク時の挙動にあるかもしれない、という調査の視野を持つことが大事だと感じました。

記事タイトルの「Option Soup」はかなり的確です。オプションを足していくほど解決できる問題も増えますが、そのぶん組み合わせの意味を説明できない構成にも近づきます。最終的にFirefox側では、この特定の危険な構成をconfigureで検出する対策が追加されており、再発防止まで含めた読みごたえのある調査記録でした。

コメント

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です