この記事はクラスター Advent Calendar 2020の12日目の記事です。
昨日はclngnさんの「clusterのアバターサムネイルを変えた話」でした。影のこだわりはさすがですね。
はじめに
みなさんこんにちは、スワンマンです。
普段はクラスターでイベントスタッフをやったり、イベントのMCをやったり、アバターの調整をしたり、スタジオの整備をしたり、Twitterの中の人をやったり…等々色んなことに携わっていますが、その中のメイン業務のひとつとしてカスタマーサポートもやっています。
今回はそのカスタマーサポートに寄せられた不具合の原因を自分で突き止めた時の話です。
原因不明のクラッシュが頻発…しない
カスタマーサポートには日々不具合の報告が寄せられます。その中には自分だけで解決できるものもあればそうでないものもあり、そうでないものは開発チームへと送られます。
しかし開発チームのリソースも有限であり、全ての不具合を調べてもらえるとは限りません。
当時たまに寄せられる不具合がそれで、「clusterを立ち上げることはできるものの、アバターを選択するとクラッシュする」というものでした。
これが頻発するのであれば当然本腰を入れて調査が始まったりするんですが、たまーに来るくらいという頻度だった(特に3月より前のclusterはまだワールドという概念が無かったのでイベントのある日にしかそういう報告が無かった)ため軽い調査をしたのみで一旦保留となっていたわけです。
さりとて報告は寄せられる
頻度が低いとは言え不具合の報告は来るわけで、カスタマーサポートとしてはそれに答えないといけないんですが、原因不明ということになっている不具合への返答はとても難しい…。
そこで「もうこうなったら自分で調べるしかないな!」と思い立ち、ひとまずUnity Dashboardのログを見ることにしました。
clusterはUnity製アプリなので、クラッシュが起こった場合Unity Dashboardにクラッシュログが残ります。そしてそのログからの事前調査で特定のDLL内でクラッシュしていることは分かっていました。しかしC#で書かれたアセンブリではなくネイティブDLLだったため、ここで一旦調査が打ち切られたようです。
つまり、この続きをやれば分かるのでは…?ということでデバッガを立ち上げました。
まずクラッシュ箇所を見に行く
clusterは64bitアプリなので、ネイティブDLLも64bitです。そのため普段使っているOllyDbgというデバッガが使えず、今回は64bitアプリにも対応しているx64dbgを使いました。
まずどこでクラッシュしているかを見ようとしたものの、Unity Dashboard上にログとして表示されているスタックトレースは実際のユーザー環境におけるメモリアドレス(絶対アドレス)のため、自分がローカルでデバッグする時とはアドレスが異なる可能性があります(ASLRがあるため、異なるアドレスにDLLが配置される可能性がある)。
これを回避するにはベースアドレス(DLLが配置された時の先頭アドレス)からのオフセットが必要になるんですが、Web上には表示されていないだけで実はUnity DashboardからエクスポートできるJSONファイルより「relative_pc」として取得できます。なのでローカルでDLLをロードした時のベースアドレスにこのオフセット値を足せばクラッシュ箇所を辿ることができます。
ついに原因が判明
クラッシュ箇所はポインタを逆参照してその値を代入するというコードだったため、「これは環境によってポインタがnullになってエラーが発生しているのでは?」と最初に考えました。ところがそのポインタを参照している箇所を探したところ、読むところはあるものの代入しているところが一箇所もない、つまりはただの定数でした。
単なる代入でどうして死んでしまうん…と諦めかけたところでしたが、実はこの代入こそが原因そのもので、ここで呼ばれていたのはMOVやLEAといったx86命令ではなく、AVX拡張命令セットに含まれるVMOVDQUという命令だったんです。
AVXはMMXやSSEみたいなCPUの拡張命令セットのひとつで、CPUによって実装があったりなかったりします。あったりなかったりするということは、なかった場合は命令が正常に実行できずに死んでしまうわけですね。
あとは答え合わせとしてそれまでクラッシュしていたPCがどのCPUを使っているか調べたところ、見事に全てAVX命令非対応CPUだった…ということで、ついに原因を突き止めることができました。
おわりに
原因を突き止めた結果、案内したくてもできない状態だったのが「CPUが原因」ということを伝えられるようになったのは大きかったですね。
実際に「使用するPCを変更することでclusterを使えるようになった」というユーザーの方もいました。わいわい。
ということでクラスターのカスタマーサポートは答えが分からない時は自力で答えを出すぞ!というお話でした。
明日はurauraさんの「nanka...」です。nankaとは一体何なのか…これは興味深い話になりそうです。