続・0.22.2 用日本語パッチの問題への対処

一昨日公開したパッチの修正では問題が修正できていない(さらに別の問題も発生)ことがわかり、昨日さらなる修正を公開するもこれも根本的な問題解決には至らず、今日も修正版を公開。三度目の正直どころか、四度目の正直(いや、差し替えが4回目なのだから五度目か)なるかといった事態になってしまった。毎日のように修正が入るという状態になってしまい、テストに協力いただいている方の混乱を招いて大変申し訳なく思っている。ここに至るまでの過程を、自戒を込めて振り返ってみる。
問題が確実に再現されるメールを見つけたところまではよかったのだが、一昨日書いた対処方法で問題がきれいに解消したため、そこが原因だったのだと勝手に思い込んでしまったのがまずかった。他に原因がないのかどうかもっと検証してみるべきだった。さらに悪いことに、この修正によって辞書がどんどん開かれてしまって「Too many open files」というエラーが起こるという別の問題まで起こしてしまった。Text::Kakasi のドキュメントに getpot_argv を繰り返し呼んでも辞書ファイルが自動的に閉じられるため close_kanwadict を呼ばなくてもよいと書かれていたために大丈夫だと思い込んでいたのだが、実際には Kakasi のライブラリ自体に kanwadict が閉じられないという問題があり、やはりその都度 close_kanwadict を呼ぶ必要があったのだ。ここでも思い込みで動いてしまって厳密に動作確認しなかったというミスがあった。
エラーが発生する問題は、公開した次の日に報告をいただき、すぐに確認することができた。close_kanwadict を毎回呼ぶようにすれば問題は解決するのはわかっているが、それではパフォーマンス向上のための取り組みが無意味になってしまう。問題が起こるメールのサンプルをもとに、もっと詳しく調べてみることにした(というか最初からそうすべきだったのだが)。
件のメールにはひとつ気になる特徴があり、それは、件名が MIME エンコードされておらず、iso-2022-jp でもない謎の文字列(ようは最初から文字化けしたような状態)になっていることだった。試しに、Encode::Guess でそれぞれの行の漢字コードがどう判定されているのかを調べてみたところ、件名については「euc-jp」、本文については「shiftjis」という結果だった。そこで、試しに、Encode で漢字コードを変換する前の漢字コードが変更されたら Kakasi の辞書を閉じて開き直すという処理を加えてみた。すると、また問題がきれいに解消した(というか解消するようなプログラムを書いたのだから当然か)。ここでまた、それが原因なのだと思い込んでしまった(今思うと、なぜ Encode が関係しているのだと思ったのか不思議だが)。
しかし、これも間違いだった。1行目が euc-jp、2行目が shiftjis のテキストファイルを作って処理させてみても、問題は再現されなかった。が、件のメールを処理すると何度やってみても問題が起こる。ということは、このメールで使われている文字に原因があるのかもしれない。そう思い、メールのヘッダやらなにやらをばっさり削除し、件名と本文1行だけにしたテキストファイルで実験してみると、それでも問題が起こる。やはり文字が原因らしい。次に、Encode でコード変換を行ったあとのテキストを試すと、これでも再現された。どうやら Encode は関係なく、Text::Kakasi 単体の問題らしい。
さらに、件名の部分の文字をあれこれ変えてみると、1文字目の1バイト目(euc-jp で)のコードが 0xE? の場合に問題が起こることがわかった。ここまでわかったところで、Kakasi-dev メーリングリストに現象についての投稿を行った。症状からして、Text::Kakasi(あるいは Kakasi)の問題ではないかと考えたからだ。しかし、これも間違っていたのだった。
投稿後、kakasi でも同じ現象が起こるという情報をいただいた。自分でも試してみると、確かに再現した。ということは Kakasi 自体に問題があるのだろうかと考えつついろいろ試してみると、kakasi に -ieuc とパラメータを渡してやると問題が起こらなくなることを発見した。もしかしてこれは、漢字コードの誤判定が原因なのか?
しかし、Text::Kakasi を使ったサンプルでは漢字コードを指定しているはず。それで問題が起こるということは、kakasi と Text::Kakasi とで挙動が違うか、あるいは漢字コードの指定が間違っているか、だ。ソースコードを見る限り前者という可能性はなさそうなので、試しに漢字コードの指定部分を変更してみると、あっさりと問題が解決してしまった。ここには問題はないはずだと思っていたところに実は根本的な問題が潜んでいたのだった。
結局、漢字コードを指定したつもりが正しく伝わっておらず、Kakasi が漢字コードを誤認識(おそらく euc-jp を shiftjis として処理)し、それによって文字化けが起こってしまっていたようだ。文字化けの内容も、見た目にはでたらめになってしまっていたのでよく確認していなかったのだけど、バイナリエディタで開いて正常な場合と見比べてみると、スペース(0x20)が妙なところに挟まっている以外は正常な場所と同じだった。このことからも、漢字コードがご認識されて(euc-jp なのに shiftjis として)処理されてしまったということが伺える。
今回は問題の起こったメールだけでなく、似たようなパターンの文字列(問題が再現していたもの)で試してみても大丈夫だったので、今度こそ今回見つけた問題については大丈夫なはずだ。これですべての問題が解決するとよいのだけど。
今回の件で反省すべきは、時間があまりない中での作業だったとはいえ、思い込みがあまりにも多かったことだ。ある方法で問題が解決したとしても、それが唯一の正しい方法だと早合点してはいけない。もっと別の原因はないかどうか慎重に検討しなくてはいけない。ひとつ言い訳すると、長い間あれこれ考えても原因が判らなかったところに急に糸口(らしきもの)が見つかって判断力が鈍っていたのかもしれないなとも思う。そんなときこそ気をつけなければいけない、ということなのかな。