さくらインターネット上で tDiary を ruby1.9.1-p0 で動かす (2)
2009-02-21
Ruby1.9で動かす話の続き。 Ruby1.9.1に移行してから1日経つと、個別(日表示)のページで例外が出るようになった。
Errors in plugins? Retry to Edit(2009-02-19) or Configure.
ArgumentError
invalid byte sequence in UTF-8
最新のページは普通に表示される。 これだけでは何も分からないので、いろいろと調べてみた。
プラグインを外す
プラグインのエラーなので、怪しいと思っているプラグインを外してみた。 それでも状況は変わらず。
スタックトレースを表示する
エラーの場所を特定するために、エラー画面にスタックトレースを表示するようにした。 エラーメッセージは skel/plugin_error.rhtml で出力されているので、このファイルを以下のように修正。 「$!」は例外を表す特殊変数で、 backtrace メソッドで取得したスタックトレースを出力している。
Index: plugin_error.rhtml
===================================================================
--- plugin_error.rhtml (revision 3404)
+++ plugin_error.rhtml (working copy)
@@ -20,6 +20,7 @@
<blockquote>
<strong><%=h $!.class %></strong><br>
<pre><%=h $! %></pre>
+ <pre><%=h $!.backtrace.join("\n") %></pre>
</blockquote>
</body>
</html>
この状態で個別日記にアクセスすると、以下のスタックトレースが出力された。
(plugin/05referer.rb):152:in `split'
(plugin/05referer.rb):152:in `block in referer_load'
(plugin/05referer.rb):149:in `open'
(plugin/05referer.rb):149:in `referer_load'
(plugin/05referer.rb):178:in `referer_load_volatile'
(plugin/05referer.rb):130:in `referer_update'
(plugin/05referer.rb):26:in `referer_save_trigger'
(plugin/05referer.rb):14:in `block (2 levels) in load_plugin'
該当するソースは以下のようになってる。
def referer_load( file, diary )
begin
File::open( file ) do |fh|
fh.flock( File::LOCK_SH )
fh.gets # read magic
fh.read.split( /\r?\n\.\r?\n/ ).each do |l|
headers, body = ::TDiary::parse_tdiary( l )
yield( headers, body )
end
end
rescue Errno::ENOENT
end
end
どうやら、ファイルに保存したリファラを開くときに、 UTF-8 として扱えない文字が含まれているのが原因っぽい。
場当たり的な対処
どのリファラに含まれる文字が不正なのかを調べようと思ったけど、いい方法が思いつかなかった。 それに、このまま日記が表示できないのは困るので、とりあえず例外を無視するように修正した。
- rescue Errno::ENOENT
+ rescue
これをやると他のバグまで見つからなくなるので、本当はやっちゃダメなんだよね。