Web系やモバイル系でプログラムを書いていると、自分自身が作ったのでないバグや問題に遭遇することも、決して珍しいことではありません(Androidアプリの機種依存の問題を除いたとしても、年に数回はあります)。
今回は、ちょうど少し前に遭遇したPDO-MySQLのバグを例に、バグに遭遇した時はどうすればいいのか、流れを示していきます。
その0:とりあえず、再起動など
コードを書き換えた直後にトラブルが出ても、キャッシュが残っているなどで一時的にデータが整合しなくなっているだけ、ということもよくあります。ひとまず、サーバ系なら再起動、ビルドが必要なら完全リビルド、ブラウザの場合はブラウザキャッシュのクリアをして、それでも再現するか確認しましょう。
その1:エラーメッセージでググる
前にも書きましたが、エラーが起きた時に出るメッセージやエラーコードは重要な情報です。まずは、エラーメッセージでぐぐってみると、手がかりになる情報が手に入ることもあります。
今回の場合、ググってみると、このエラーはUnbuffered Queryにした場合に起こることがわかったので、そのクエリモードについても調べていたのですが、まったく切り替えは意図したものではなく、この段階では意味不明なままでした。
その2:再現条件を追いかける
CodeIgniterを3.0.3から3.0.6に上げて今回の現象が起きたのですが、どこのバージョンアップで不具合になったのかを特定するため、CodeIgniter 3.0.4にしてみたところ…同じ状況となったので、ここのバージョンアップでなにかがあったことがほぼ確定しました。
このように再現性が取れるバグであれば追いかけやすいのですが、そうでない場合、たとえば
- 日付・時間が特定の値になると動かない
- 他のメモリに入っている値によって状況が変化する
- 同時実行に関係したバグ
などは、再現条件を確定させるだけで一苦労します。もっとも、「どのようにすればバグが起きるか」を確定できれば、バグ調査の山場は超えたと言ってもいいです。
その3:差分を見る
自分でコードを書き換えてバグが出た場合、書き換えた部分で何かが起きています。今回はCodeIgniterの更新で起きたということなので、3.0.3と3.0.4の間で更新されたところに、原因があるということになります。
ソースコードの差分を取ったり、ChangeLogを見ていたところ、MySQLまわりで、「MySQL 5.7でSTRICTのデフォルトが変化するために、それを吸収する」コードが追加されていました。これが影響するとはにわかには考えられなかったのですが、実際に変わっているのがここぐらいだったので、ぐぐってみたところ、PHP側のIssueにたどり着きました。
その4:対策を考える
バグの原因がわかれば、対策を行うことができます。それにも、いくつかの手段があります。
まず、フレームワークなどの場合、ソースを見れば問題点が明らかになっていることもあるので、「直して自分からPRを投げる」という選択肢があります。一方で、今回のPHPのように、容易にソースを追えない部分、さらにはブラウザごとに起きるバグのように実行環境の側に手を入れることができない場合は、「バグを回避するようにコードを書き換える」ということになります。状況によっては、「バグを起こす機能そのものを削る」ことで回避する、なんていう苦渋の決断が必要となることもあります。